Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH] De-register pbap drivers on init failure scenarios
From: Johan Hedberg @ 2010-07-27 12:31 UTC (permalink / raw)
  To: Counihan, Tom; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <B09AD526409DF14F8DA79CC5429052C299EE0FC7@irsmsx505.ger.corp.intel.com>

Hi Tom,

On Tue, Jul 27, 2010, Counihan, Tom wrote:
> Unwind the driver registration/phonebook initialization stack on pbap plugin init failure scenarios.
> 
> 
> ---
>  plugins/pbap.c |   25 ++++++++++++++++++++-----
>  1 files changed, 20 insertions(+), 5 deletions(-)

Thanks for the patch! It's now upstream. In the future please pay
attention to your commit message line length. It shouldn't exceed 74
characters (or so) in order to be nicely viewable on a 80-character wide
terminal using git log. I fixed it this time for you manually.

Johan

^ permalink raw reply

* Re: obexd 0.29 and N900 PC Suite
From: Luiz Augusto von Dentz @ 2010-07-27 13:03 UTC (permalink / raw)
  To: Harald Schmitt; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <4C4EC2B5.2030204@hschmitt.de>

Hi,

On Tue, Jul 27, 2010 at 2:27 PM, Harald Schmitt <linux@hschmitt.de> wrote:
> Hi,
>
> there are several users who test obexd 0.29 on the Nokia N900 running Maemo
> in order to have PBAP support. There are success reports with PBAP, but at
> the same time they cannot usb sync via Nokia PC Suite anymore. Is there any
> chance to get PC Suite working again in a future obexd version or does this
> depend on a non free Nokia code?
> Can you give any hints where to look at?
> In a forum a user posted success (with 0.19) and failure (with 0.29) logs:
> http://talk.maemo.org/showthread.php?p=763550#post763550

First thanks a lot for this feedback, I wasn't aware that there were
somebody trying to use newer version of obexd in N900, I will take a
look how I can make usb compatible with N900, actually it should be
just as bluetooth and work no matter which platform you are using but
we are not there yet :(

In the meantime you can try reverting the patch bellow and see if it helps:

http://git.kernel.org/?p=bluetooth/obexd.git;a=commitdiff;h=6f56a4355585eb29535782f977ba545cc41dd382

-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Re: [RFC v2] Bluetooth: Provide access to reassembled Rx packets
From: Suraj @ 2010-07-27 15:36 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Suraj Sumangala, linux-bluetooth@vger.kernel.org,
	Jothikumar Mothilal
In-Reply-To: <1280207657.2621.74.camel@localhost.localdomain>

Hi Marcel,

On 7/27/2010 10:44 AM, Marcel Holtmann wrote:
> Hi Suraj,
>
>>> So first of all, lets make something perfectly clear. All Bluetooth
>>> drivers are _transport_ drivers. They don't need to know what they are
>>> transporting. And in addition you should not look into the packets that
>>> you are sending or receiving. The Bluetooth core does that HCI packet
>>> parsing.
>>>
>>> This is how I want it and how this is going to stay. Everything else is
>>> an insane approach and cost every single driver overhead. In addition
>>> the lifetime rules of SKBs become more and more complicated. That is a
>>> pretty bad thing. It will result in excessive memory usage and will
>>> cause problems.
>>
>> I understand the point that you are making. But If I am not mistaken,
>> HCI transport driver is the only part of the system that could be vendor
>> specific ( HCI ATH3K, HCI LL etc). So a vendor specific command or event
>> makes more sense to a transport driver than anybody else.
>>
>> Is there anyway this requirement can be sufficed without causing the
>> issues you have mentioned above?
>
> so you might be able to convince me if you implement something proper
> for handling vendor commands. The basic assumption is still that a HCI
> driver is a pure transport driver.

My requirement is basically to use the command complete event of 
HCI_RESET to trigger a vendor specific command and verify its status by 
checking the status of the VSC.

So, does it makes sense to register a callback with HCI core with 
required Event ID so that HCI core can call the callback when it 
receives the corresponding Event? This would still make sure that HCI 
packets are handled by HCI core and "driver/whoever registers the 
callback" will be notified by the HCI core as and when required.

Not sure this would address the concern you have raised.

>
> However you have access to hci_dev. So if you create some functions to
> execute vendor commands and retrieve the results then this might be a
> way. The core already processes vendor commands and events. But keep in
> mind that there is no requirement to get a command status or command
> complete event for vendor commands. For example CSR doesn't send them
> for their vendor commands.

Thanks,

>
> Regards
>
> Marcel
>
>

Regards
Suraj

^ permalink raw reply

* Re: [PATCH] De-register pbap drivers on init failure scenarios
From: Marcel Holtmann @ 2010-07-27 15:41 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: Counihan, Tom, linux-bluetooth@vger.kernel.org
In-Reply-To: <20100727123129.GA6483@jh-x301>

Hi Johan,

> > Unwind the driver registration/phonebook initialization stack on pbap plugin init failure scenarios.
> > 
> > 
> > ---
> >  plugins/pbap.c |   25 ++++++++++++++++++++-----
> >  1 files changed, 20 insertions(+), 5 deletions(-)
> 
> Thanks for the patch! It's now upstream. In the future please pay
> attention to your commit message line length. It shouldn't exceed 74
> characters (or so) in order to be nicely viewable on a 80-character wide
> terminal using git log. I fixed it this time for you manually.

please pay attention to Outlook/Exchange users where the the firstname,
lastname thing is reversed :(

Tom, Ensure that patches have a proper From: line first with the correct
name in the correct order.

Regards

Marcel



^ permalink raw reply

* [PATCH] IrMC sync server support
From: Marcel Mol @ 2010-07-27 17:04 UTC (permalink / raw)
  To: linux-bluetooth

A reasonable working IrMC SYNC server (only full phonebook sync support)
Support for cal and note by just returning nothing.
---
 Makefile.am    |    3 +
 plugins/irmc.c |  488 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/main.c     |   12 ++-
 src/obex.h     |    1 +
 4 files changed, 502 insertions(+), 2 deletions(-)
 create mode 100644 plugins/irmc.c

diff --git a/Makefile.am b/Makefile.am
index 73e2f28..ce8c675 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -58,6 +58,9 @@ builtin_sources += plugins/pbap.c plugins/phonebook.h \
 builtin_modules += syncevolution
 builtin_sources += plugins/syncevolution.c
 
+builtin_modules += irmc
+builtin_sources += plugins/irmc.c plugins/phonebook.h
+
 builtin_nodist += plugins/phonebook.c
 
 libexec_PROGRAMS += src/obexd
diff --git a/plugins/irmc.c b/plugins/irmc.c
new file mode 100644
index 0000000..96fd807
--- /dev/null
+++ b/plugins/irmc.c
@@ -0,0 +1,488 @@
+/*
+ *
+ *  OBEX IrMC Sync Server
+ *
+ *  Copyright (C) 2010  Marcel Mol <marcel@mesa.nl>
+ *
+ *  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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "obex.h"
+#include "service.h"
+#include "phonebook.h"
+#include "mimetype.h"
+#include "filesystem.h"
+#include "dbus.h"
+
+#define IRMC_CHANNEL	17
+
+#define IRMC_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>	\
+<record>								\
+  <attribute id=\"0x0001\">						\
+    <sequence>								\
+      <uuid value=\"0x1104\"/>						\
+    </sequence>								\
+  </attribute>								\
+									\
+  <attribute id=\"0x0004\">						\
+    <sequence>								\
+      <sequence>							\
+        <uuid value=\"0x0100\"/>					\
+      </sequence>							\
+      <sequence>							\
+        <uuid value=\"0x0003\"/>					\
+        <uint8 value=\"%u\" name=\"channel\"/>				\
+      </sequence>							\
+      <sequence>							\
+        <uuid value=\"0x0008\"/>					\
+      </sequence>							\
+    </sequence>								\
+  </attribute>								\
+									\
+  <attribute id=\"0x0009\">						\
+    <sequence>								\
+      <sequence>							\
+        <uuid value=\"0x1104\"/>					\
+        <uint16 value=\"0x0100\" name=\"version\"/>			\
+      </sequence>							\
+    </sequence>								\
+  </attribute>								\
+									\
+  <attribute id=\"0x0100\">						\
+    <text value=\"%s\" name=\"name\"/>					\
+  </attribute>								\
+									\
+  <attribute id=\"0x0301\">						\
+    <sequence>								\
+      <uint8 value=\"0x01\"/>						\
+    </sequence>								\
+  </attribute>								\
+</record>"
+
+
+struct aparam_header {
+	uint8_t tag;
+	uint8_t len;
+	uint8_t val[0];
+} __attribute__ ((packed));
+
+#define DIDLEN 18
+struct irmc_session {
+	struct obex_session *os;
+	struct apparam_field *params;
+	uint16_t entries;
+	GString *buffer;
+	char sn[DIDLEN];
+	char did[DIDLEN];
+	char manu[DIDLEN];
+	char model[DIDLEN];
+};
+
+#define IRMC_TARGET_SIZE 9
+
+static const guint8 IRMC_TARGET[IRMC_TARGET_SIZE] = {
+			0x49, 0x52, 0x4d, 0x43,  0x2d, 0x53, 0x59, 0x4e, 0x43 };
+
+static void phonebook_size_result(const char *buffer, size_t bufsize,
+				int vcards, int missed, void *user_data)
+{
+	struct irmc_session *irmc = user_data;
+
+	DBG("vcards %d", vcards);
+
+	irmc->params->maxlistcount = vcards;
+}
+
+static void query_result(const char *buffer, size_t bufsize, int vcards,
+					int missed, void *user_data)
+{
+	struct irmc_session *irmc = user_data;
+	const char *s;
+	char *t;
+
+	DBG("bufsize %d vcards %d missed %d", bufsize, vcards, missed);
+
+	// first create an empty 'owner' vcard
+	t = "BEGIN:VCARD\r\n"
+		"VERSION:2.1\r\n"
+		"N:\r\n"
+		"TEL:\r\n"
+		"X-IRMX-LUID:0\r\n"
+		"END:VCARDi\r\n";
+	if (!irmc->buffer)
+		irmc->buffer = g_string_new_len(t, strlen(t));
+	else
+		irmc->buffer = g_string_append_len(irmc->buffer, t, strlen(t));
+
+	// loop around buffer and add X-IRMC-LUID attribs
+	s = buffer;
+	while ((t = strstr(s, "UID:")) != NULL) {
+		// add upto UID: into buffer
+		irmc->buffer = g_string_append_len(irmc->buffer, s, t-s);
+		// add UID: line into buffer
+		// Not sure if UID is still needed if X-IRMC-LUID is there
+		s = t;
+		t = strstr(s, "\r\n");
+		t += 2;
+		irmc->buffer = g_string_append_len(irmc->buffer, s, t-s);
+		// add X-IRMC-LUID with same number as UID
+		irmc->buffer = g_string_append_len(irmc->buffer,
+							"X-IRMC-LUID:", 12);
+		s += 4; // point to uid number
+		irmc->buffer = g_string_append_len(irmc->buffer, s, t-s);
+		s = t;
+	}
+	// add remaining bit of buffer
+	irmc->buffer = g_string_append_len(irmc->buffer, s,
+							bufsize - (s-buffer));
+
+	obex_object_set_io_flags(irmc, G_IO_IN, 0);
+}
+
+static void *irmc_connect(struct obex_session *os, int *err)
+{
+	struct irmc_session *irmc;
+	struct apparam_field *param;
+
+	DBG("");
+
+	manager_register_session(os);
+
+	irmc = g_new0(struct irmc_session, 1);
+	irmc->os = os;
+
+	/*
+	 * ideally get capabilities info here and use that to define
+	 * IrMC DID and SN etc parameters.
+	 * For now lets used hostname and some 'random' value
+	 */
+	gethostname(irmc->did, DIDLEN);
+	strncpy(irmc->sn, "12345", DIDLEN);
+	strncpy(irmc->manu, "obex", DIDLEN);
+	strncpy(irmc->model, "mymodel", DIDLEN);
+
+	/*
+         *  we need to know the number of contact/cal/nt entries
+         *  somewhere so why not do it now.
+         */
+	param = g_new0(struct apparam_field, 1);
+	param->maxlistcount = 0; // to count the number of vcards...
+	param->filter = 0x200085; // UID TEL N VERSION
+	irmc->params = param;
+	phonebook_pull("telecom/pb.vcf", irmc->params, phonebook_size_result,
+									irmc);
+
+	if (err)
+		*err = 0;
+
+	return irmc;
+}
+
+static int irmc_get(struct obex_session *os, obex_object_t *obj,
+		gboolean *stream, void *user_data)
+{
+	struct irmc_session *irmc = user_data;
+	const char *type = obex_get_type(os);
+	const char *name = obex_get_name(os);
+	char *path;
+	int ret;
+
+	DBG("name %s type %s irmc %p", name, type ? type : "NA", irmc);
+
+	path = g_strdup(name);
+	*stream = TRUE;
+
+	ret = obex_get_stream_start(os, path);
+
+	g_free(path);
+
+	return ret;
+}
+
+static void irmc_disconnect(struct obex_session *os, void *user_data)
+{
+	struct irmc_session *irmc = user_data;
+
+	DBG("");
+
+	manager_unregister_session(os);
+
+        if (irmc->params) {
+                if (irmc->params->searchval)
+			g_free(irmc->params->searchval);
+                g_free(irmc->params);
+        }
+	if (irmc->buffer) {
+		string_free(irmc->buffer);
+		irmc->buffer = NULL;
+	}
+
+	g_free(irmc);
+}
+
+static int irmc_chkput(struct obex_session *os, void *user_data)
+{
+	DBG("");
+	/* Reject all PUTs */
+	return -EBADR;
+}
+
+static void *irmc_open_devinfo(struct irmc_session *irmc, int *err)
+{
+	char mybuf[1024];
+
+	sprintf(mybuf, "MANU:%s\r\n"
+			"MOD:%s\r\n"
+			"SN:%s\r\n"
+			"PB-TYPE-TX:VCARD2.1\r\n",
+			irmc->manu, irmc->model, irmc->sn);
+
+	if (!irmc->buffer)
+		irmc->buffer = g_string_new(mybuf);
+	else
+		irmc->buffer = g_string_append(irmc->buffer, mybuf);
+
+	return irmc;
+}
+
+static void *irmc_open_pb(const char *name,
+		 struct irmc_session *irmc, int *err)
+{
+	char mybuf[1024];
+	int ret;
+
+	if (!g_strcmp0(name, ".vcf")) {
+		// how can we tell if the vcard count call already finished?
+		ret = phonebook_pull("telecom/pb.vcf", irmc->params,
+							query_result, irmc);
+		if (ret < 0) {
+			DBG("phonebook_pull failed...");
+			goto fail;
+		}
+		return irmc;
+	}
+
+	if (!g_strcmp0(name, "/info.log")) {
+		sprintf(mybuf, "Total-Records:%d\r\n"
+				"Maximum-Records:%d\r\n"
+				"DID:%s\r\n",
+				irmc->params->maxlistcount,
+				irmc->params->maxlistcount, irmc->did);
+	}
+	else if (!strncmp(name, "/luid/", 6)) {
+		name += 6;
+		if (!g_strcmp0(name, "cc.log"))
+			sprintf(mybuf, "%d\r\n", irmc->params->maxlistcount);
+		else {
+			int l = strlen(name);
+			/* FIXME
+			 * reply the same to any *.log so we hopefully force a
+			 * full phonebook dump.
+			 * Is IEL:2 ok?
+			 */
+			if (l > 4 && !g_strcmp0(name + l - 4, ".log")) {
+				DBG("changelog request, force whole book");
+				sprintf(mybuf, "SN:%s\r\n"
+						"IEL:2\r\n"
+						"DID:%s\r\n"
+						"Total-Records:%d\r\n"
+						"Maximum-Records:%d\r\n"
+						"*\r\n",
+					irmc->sn, irmc->did,
+					irmc->params->maxlistcount,
+					irmc->params->maxlistcount);
+			}
+			else {
+				ret = -EBADR;
+				goto fail;
+			}
+		}
+	}
+	else {
+		ret = -EBADR;
+		goto fail;
+	}
+
+	if (!irmc->buffer)
+		irmc->buffer = g_string_new(mybuf);
+	else
+		irmc->buffer = g_string_append(irmc->buffer, mybuf);
+
+	return irmc;
+
+fail:
+	if (err)
+		*err = ret;
+
+	return NULL;
+}
+
+static void *irmc_open_cal(const char *name,
+		 struct irmc_session *irmc, int *err)
+{
+	// no suport yet. Just return an empty buffer
+	//cal.vcs
+	DBG("unsupported, returning empty buffer");
+	if (!irmc->buffer)
+		irmc->buffer = g_string_new("");
+	else
+		irmc->buffer = g_string_append(irmc->buffer, "");
+
+	return irmc;
+}
+
+static void *irmc_open_nt(const char *name,
+		 struct irmc_session *irmc, int *err)
+{
+	// no suport yet. Just return an empty buffer
+	//nt.vnt
+	DBG("unsupported, returning empty buffer");
+	if (!irmc->buffer)
+		irmc->buffer = g_string_new("");
+	else
+		irmc->buffer = g_string_append(irmc->buffer, "");
+
+	return irmc;
+}
+
+static void *irmc_open(const char *name, int oflag, mode_t mode,
+		void *context, size_t *size, int *err)
+{
+	struct irmc_session *irmc = context;
+	int ret;
+	const char *p;
+
+	DBG("name %s context %p", name, context);
+	if (oflag != O_RDONLY) {
+		ret = -EPERM;
+		goto fail;
+	}
+	if (strncmp(name, "telecom/", 8) != NULL) {
+		ret = -EBADR;
+		goto fail;
+	}
+
+	p = name + 8;
+	if (!g_strcmp0(p, "devinfo.txt"))
+		return irmc_open_devinfo(irmc, err);
+	else if (!strncmp(p, "pb", 2))
+		return irmc_open_pb(p+2, irmc, err);
+	else if (!strncmp(p, "cal", 3))
+		return irmc_open_cal(p+3, irmc, err);
+	else if (!strncmp(p, "nt", 2))
+		return irmc_open_nt(p+2, irmc, err);
+
+fail:
+	if (err)
+		*err = ret;
+
+	return NULL;
+}
+
+static int irmc_close(void *object)
+{
+	struct irmc_session *irmc = object;
+
+	DBG("");
+	if (irmc->buffer) {
+		string_free(irmc->buffer);
+		irmc->buffer = NULL;
+	}
+
+	return 0;
+}
+
+static ssize_t irmc_read(void *object, void *buf, size_t count, uint8_t *hi)
+{
+	struct irmc_session *irmc = object;
+        int len;
+
+	DBG("buffer %p count %d", irmc->buffer, count);
+	if (!irmc->buffer)
+                return -EAGAIN;
+
+        *hi = OBEX_HDR_BODY;
+	len = string_read(irmc->buffer, buf, count);
+	DBG("returning %d bytes", len);
+	return len;
+}
+
+static struct obex_mime_type_driver irmc_driver = {
+	.target = IRMC_TARGET,
+	.target_size = IRMC_TARGET_SIZE,
+	.open = irmc_open,
+	.close = irmc_close,
+	.read = irmc_read,
+};
+
+static struct obex_service_driver irmc = {
+	.name = "IRMC Sync server",
+	.service = OBEX_IRMC,
+	.channel = IRMC_CHANNEL,
+	.record = IRMC_RECORD,
+	.target = IRMC_TARGET,
+	.target_size = IRMC_TARGET_SIZE,
+	.connect = irmc_connect,
+	.get = irmc_get,
+	.disconnect = irmc_disconnect,
+	.chkput = irmc_chkput
+};
+
+static int irmc_init(void)
+{
+	int err;
+
+	DBG("");
+	err = phonebook_init();
+	if (err < 0)
+		return err;
+
+	err = obex_mime_type_driver_register(&irmc_driver);
+	if (err < 0)
+		return err;
+
+	return obex_service_driver_register(&irmc);
+}
+
+static void irmc_exit(void)
+{
+	DBG("");
+	obex_service_driver_unregister(&irmc);
+	obex_mime_type_driver_unregister(&irmc_driver);
+	phonebook_exit();
+}
+
+OBEX_PLUGIN_DEFINE(irmc, irmc_init, irmc_exit)
diff --git a/src/main.c b/src/main.c
index 649acf9..96523a6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -83,6 +83,7 @@ static gboolean option_pbap = FALSE;
 static gboolean option_pcsuite = FALSE;
 static gboolean option_symlinks = FALSE;
 static gboolean option_syncevolution = FALSE;
+static gboolean option_irmc = FALSE;
 
 static gboolean parse_debug(const char *key, const char *value,
 				gpointer user_data, GError **error)
@@ -122,6 +123,8 @@ static GOptionEntry options[] = {
 				"Enable PC Suite Services server" },
 	{ "syncevolution", 'e', 0, G_OPTION_ARG_NONE, &option_syncevolution,
 				"Enable OBEX server for SyncEvolution" },
+	{ "irmc", 'i', 0, G_OPTION_ARG_NONE, &option_irmc,
+				"Enable IrMCSync server" },
 	{ NULL },
 };
 
@@ -208,9 +211,10 @@ int main(int argc, char *argv[])
 
 	if (option_opp == FALSE && option_ftp == FALSE &&
 				option_pbap == FALSE &&
-				option_syncevolution == FALSE) {
+				option_syncevolution == FALSE &&
+				option_irmc == FALSE) {
 		fprintf(stderr, "No server selected (use either "
-				"--opp, --ftp, --pbap or --syncevolution)\n");
+				"--opp, --ftp, --pbap --syncevolution or --irmc)\n");
 		exit(EXIT_FAILURE);
 	}
 
@@ -270,6 +274,10 @@ int main(int argc, char *argv[])
 		obex_server_init(OBEX_SYNCEVOLUTION, NULL, TRUE, FALSE,
 							FALSE, NULL);
 
+	if (option_irmc == TRUE)
+		obex_server_init(OBEX_IRMC, NULL, TRUE, FALSE, FALSE,
+				option_capability);
+
 	if (!root_folder_setup(option_root, option_root_setup)) {
 		error("Unable to setup root folder %s", option_root);
 		exit(EXIT_FAILURE);
diff --git a/src/obex.h b/src/obex.h
index 9424b6b..cfe9159 100644
--- a/src/obex.h
+++ b/src/obex.h
@@ -35,6 +35,7 @@
 #define OBEX_PBAP	(1 << 4)
 #define OBEX_PCSUITE	(1 << 5)
 #define OBEX_SYNCEVOLUTION	(1 << 6)
+#define OBEX_IRMC	(1 << 7)
 
 #define TARGET_SIZE 16
 
-- 
1.7.2


^ permalink raw reply related

* Re: [PATCH 2/5] Support for adding UUID128 to extended inquiry response
From: Luiz Augusto von Dentz @ 2010-07-27 18:25 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, rshaffer, marcel, johan.hedberg
In-Reply-To: <1279814780-29673-3-git-send-email-ingas@codeaurora.org>

Hi,

On Thu, Jul 22, 2010 at 7:06 PM, Inga Stotland <ingas@codeaurora.org> wrote=
:
> ---
> =A0src/sdpd-service.c | =A0108 ++++++++++++++++++++++++++++++++++++++++++=
++--------
> =A01 files changed, 92 insertions(+), 16 deletions(-)
>
> diff --git a/src/sdpd-service.c b/src/sdpd-service.c
> index cdbb4f4..1314ada 100644
> --- a/src/sdpd-service.c
> +++ b/src/sdpd-service.c
> @@ -49,6 +49,8 @@
> =A0#include "manager.h"
> =A0#include "adapter.h"
>
> +#define SIZEOF_UUID128 16
> +
> =A0static sdp_record_t *server =3D NULL;
>
> =A0static uint16_t did_vendor =3D 0x0000;
> @@ -174,41 +176,103 @@ static void update_svclass_list(const bdaddr_t *sr=
c)
>
> =A0}
>
> +static void eir_generate_uuid128(sdp_list_t *list,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 uint8_t *ptr, uint16_t *eir_len)
> +{
> + =A0 =A0 =A0 int i, k, index =3D 0;
> + =A0 =A0 =A0 uint16_t len =3D *eir_len;
> + =A0 =A0 =A0 uint8_t *uuid128;
> + =A0 =A0 =A0 gboolean truncated =3D FALSE;
> +
> + =A0 =A0 =A0 /* Store UUID128 in place, skip 2 bytes to insert type and =
length later */
> + =A0 =A0 =A0 uuid128 =3D ptr + 2;
> +
> + =A0 =A0 =A0 for (; list; list =3D list->next) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sdp_record_t *rec =3D (sdp_record_t *) list=
->data;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (rec->svclass.type !=3D SDP_UUID128)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Stop if not enough space to put next UUI=
D128 */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_L=
ENGTH) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 truncated =3D TRUE;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Check for duplicates, EIR data is Little=
 Endian */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (i =3D 0; i < index; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (k =3D 0; k < SIZEOF_UU=
ID128; k++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (uuid128=
[i*SIZEOF_UUID128 + k] !=3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 rec->svclass.value.uuid128.data[SIZEOF_UUID128 - k])
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (k =3D=3D SIZEOF_UUID128=
)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (i < index)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR data is Little Endian */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (k =3D 0; k < SIZEOF_UUID128; k++)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 uuid128[index*SIZEOF_UUID12=
8 + k] =3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rec->svclas=
s.value.uuid128.data[SIZEOF_UUID128 - 1 - k];
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len +=3D SIZEOF_UUID128;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 index++;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 if (index > 0 || truncated) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR Data length */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[0] =3D (index * SIZEOF_UUID128) + 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR Data type */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D (truncated) ? EIR_UUID128_SOME :=
 EIR_UUID128_ALL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len +=3D 2;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *eir_len =3D len;
> + =A0 =A0 =A0 }
> +}
> +

I think you should probably split this in two parts, first update with
the cleanups and then add the code to handle uuid 128.

> =A0void create_ext_inquiry_response(const char *name,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0int8_t tx_power, sdp_list_t *services,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0uint8_t *data)
> =A0{
> =A0 =A0 =A0 =A0sdp_list_t *list =3D services;
> =A0 =A0 =A0 =A0uint8_t *ptr =3D data;
> - =A0 =A0 =A0 uint16_t uuid[24];
> + =A0 =A0 =A0 uint16_t eir_len =3D 0;
> + =A0 =A0 =A0 uint16_t uuid16[EIR_DATA_LENGTH/2];
> =A0 =A0 =A0 =A0int i, index =3D 0;
> + =A0 =A0 =A0 gboolean truncated =3D FALSE;
>
> =A0 =A0 =A0 =A0if (name) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int len =3D strlen(name);
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR Data type */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (len > 48) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0len =3D 48;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D 0x08;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D EIR_NAME_SHORT;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D 0x09;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D EIR_NAME_COMPLET=
E;
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR Data length */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ptr[0] =3D len + 1;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0memcpy(ptr + 2, name, len);
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr +=3D len + 2;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 eir_len +=3D (len + 2);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr +=3D (len + 2);
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0if (tx_power !=3D 0) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D 2;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D 0x0a;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D EIR_TX_POWER;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (uint8_t) tx_power;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 eir_len +=3D 3;
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0if (did_vendor !=3D 0x0000) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0uint16_t source =3D 0x0002;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D 9;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D 0x10;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D EIR_DEVICE_ID;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (source & 0x00ff);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (source & 0xff00) >> 8;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (did_vendor & 0x00ff);
> @@ -217,10 +281,10 @@ void create_ext_inquiry_response(const char *name,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (did_product & 0xff00) >> 8;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (did_version & 0x00ff);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ptr++ =3D (did_version & 0xff00) >> 8;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 eir_len +=3D 10;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 ptr[1] =3D 0x03;
> -
> + =A0 =A0 =A0 /* Group all UUID16 types */
> =A0 =A0 =A0 =A0for (; list; list =3D list->next) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0sdp_record_t *rec =3D (sdp_record_t *) lis=
t->data;
>
> @@ -233,30 +297,42 @@ void create_ext_inquiry_response(const char *name,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (rec->svclass.value.uuid16 =3D=3D PNP_I=
NFO_SVCLASS_ID)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (index > 23) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D 0x02;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Stop if not enough space to put next UUI=
D16 */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((eir_len + 2 + sizeof(uint16_t)) > EIR_=
DATA_LENGTH) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 truncated =3D TRUE;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Check for duplicates */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (i =3D 0; i < index; i++)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (uuid[i] =3D=3D rec->svc=
lass.value.uuid16)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (uuid16[i] =3D=3D rec->s=
vclass.value.uuid16)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (i =3D=3D index - 1)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (i < index)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 uuid[index++] =3D rec->svclass.value.uuid16=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 uuid16[index++] =3D rec->svclass.value.uuid=
16;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 eir_len +=3D sizeof(uint16_t);
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0if (index > 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[0] =3D (index * 2) + 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR Data length */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[0] =3D (index * sizeof(uint16_t)) + 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* EIR Data type */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ptr[1] =3D (truncated) ? EIR_UUID16_SOME : =
EIR_UUID16_ALL;
> +
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ptr +=3D 2;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 eir_len +=3D 2;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (i =3D 0; i < index; i++) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D (uuid[i] & 0x00f=
f);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D (uuid[i] & 0xff0=
0) >> 8;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D (uuid16[i] & 0x0=
0ff);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *ptr++ =3D (uuid16[i] & 0xf=
f00) >> 8;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0}
> +
> + =A0 =A0 =A0 /* Group all UUID128 types */
> + =A0 =A0 =A0 if (eir_len <=3D EIR_DATA_LENGTH - 2)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 eir_generate_uuid128(services, ptr, &eir_le=
n);
> =A0}
>
> =A0void register_public_browse_group(void)
> --
> 1.7.1

Also this checks for duplicates looks suspicious, does it really need
to check that in place and every time, I think it might be more
efficient if we do that before generating the EIR data avoiding
comparing data with different endianess or maybe it just make more
sense to not allow duplicates in the database then we don't have to do
this at all.

--=20
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* [PATCH 1/2] Fix vcard filter setting
From: Marcel Mol @ 2010-07-27 19:04 UTC (permalink / raw)
  To: linux-bluetooth

The bits for VCARD version 2.1 and version 3.0 were wrong:
oin case of 2.1 the FN bit was on and for 3.0 it is off.
The comment state that 3.0 needs FN while 2.1 does not.
This patch fixes that.
---
 plugins/phonebook-ebook.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
index 2d5bec3..089b956 100644
--- a/plugins/phonebook-ebook.c
+++ b/plugins/phonebook-ebook.c
@@ -107,7 +107,7 @@ static char *evcard_to_string(EVCard *evcard, unsigned int format,
 	 * Mandatory attributes for vCard 2.1 are VERSION ,N and TEL.
 	 * Mandatory attributes for vCard 3.0 are VERSION, N, FN and TEL
 	 */
-	filter = format == EVC_FORMAT_VCARD_30 ? filter | 0x85: filter | 0x87;
+	filter = format == EVC_FORMAT_VCARD_30 ? filter | 0x87: filter | 0x85;
 
 	evcard2 = e_vcard_new();
 	for (i = 0; i < 29; i++) {
-- 
1.7.1.1


^ permalink raw reply related

* Re: [PATCH] Bluetooth: Fix permission of hci_ath.c
From: Marcel Holtmann @ 2010-07-27 19:33 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, marcel, suraj, Gustavo F. Padovan
In-Reply-To: <1279944365-15821-1-git-send-email-gustavo@padovan.org>

Hi Gustavo,

> From: Gustavo F. Padovan <padovan@profusion.mobi>
> 
> .c file shall not have the 'x' permission.
> 
> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> ---
>  0 files changed, 0 insertions(+), 0 deletions(-)
>  mode change 100755 => 100644 drivers/bluetooth/hci_ath.c

good catch. Patch has been applied.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] Bluetooth: Test 'count' value before enter the loop
From: Marcel Holtmann @ 2010-07-27 19:34 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, Gustavo F. Padovan
In-Reply-To: <1279946094-17478-1-git-send-email-gustavo@padovan.org>

Hi Gustavo,

> From: Gustavo F. Padovan <padovan@profusion.mobi>
> 
> Testing first we avoid enter the loop when count = 0.
> 
> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> ---
>  net/bluetooth/hci_core.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)

patch has been applied. Thanks.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] Bluetooth: Use hci_recv_stream_fragment() in UART driver
From: Marcel Holtmann @ 2010-07-27 19:35 UTC (permalink / raw)
  To: Ville Tervo
  Cc: ext Gustavo F. Padovan, linux-bluetooth@vger.kernel.org,
	Gustavo F. Padovan
In-Reply-To: <4C4E9809.2090107@nokia.com>

Hi Gustavo,

> > Use the new hci_recv_stream_fragment() to reassembly incoming UART
> > streams.
> >
> > Signed-off-by: Gustavo F. Padovan<padovan@profusion.mobi>
> > ---
> 
> I tried with h4 transport over usb serial. Seems to work like earlier.
> 
> Tested-by: Ville Tervo <ville.tervo@nokia.com>

patch has been applied.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 1/2] Bluetooth: Add __init and __exit marks to UART drivers
From: Marcel Holtmann @ 2010-07-27 19:36 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, Gustavo F. Padovan
In-Reply-To: <1279947885-19304-1-git-send-email-gustavo@padovan.org>

Hi Gustavo,

> Those marks are useful to save space in the binary and in the memory.
> 
> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> ---
>  drivers/bluetooth/hci_ath.c  |    4 ++--
>  drivers/bluetooth/hci_bcsp.c |    4 ++--
>  drivers/bluetooth/hci_h4.c   |    4 ++--
>  drivers/bluetooth/hci_ll.c   |    4 ++--
>  4 files changed, 8 insertions(+), 8 deletions(-)

patch has been applied. Thanks.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 2/2] Bluetooth: Add __init and __exit marks to RFCOMM
From: Marcel Holtmann @ 2010-07-27 19:37 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth, Gustavo F. Padovan
In-Reply-To: <1279947885-19304-2-git-send-email-gustavo@padovan.org>

Hi Gustavo,

> Those annotation save memory and space on the binary. __init code is
> discarded just after execute and __exit code is discarded if the module is
> built into the kernel image or unload of modules is not allowed.
> 
> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> ---
>  net/bluetooth/rfcomm/sock.c |    2 +-
>  net/bluetooth/rfcomm/tty.c  |    4 ++--
>  2 files changed, 3 insertions(+), 3 deletions(-)

patch has been applied. Thanks.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH v3] Bluetooth: Defer SCO setup if mode change is pending
From: Marcel Holtmann @ 2010-07-27 19:40 UTC (permalink / raw)
  To: Ron Shaffer; +Cc: linux-bluetooth, johan.hedberg
In-Reply-To: <1280153160-7166-1-git-send-email-rshaffer@codeaurora.org>

Hi Ron,

> Certain headsets such as the Motorola H350 will reject SCO and eSCO
> connection requests while the ACL is transitioning from sniff mode
> to active mode. Add synchronization so that SCO and eSCO connection
> requests will wait until the ACL has fully transitioned to active mode.
> 
> < HCI Command: Exit Sniff Mode (0x02|0x0004) plen 2
>     handle 12
> > HCI Event: Command Status (0x0f) plen 4
>     Exit Sniff Mode (0x02|0x0004) status 0x00 ncmd 1
> < HCI Command:  Setup Synchronous Connection (0x01|0x0028) plen 17
>     handle 12 voice setting 0x0040
> > HCI Event: Command Status (0x0f) plen 4
>     Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
> > HCI Event: Number of Completed Packets (0x13) plen 5
>     handle 12 packets 1
> > HCI Event: Mode Change (0x14) plen 6
>     status 0x00 handle 12 mode 0x00 interval 0
>     Mode: Active
> > HCI Event: Synchronous Connect Complete (0x2c) plen 17
>     status 0x10 handle 14 bdaddr 00:1A:0E:50:28:A4 type SCO
>     Error: Connection Accept Timeout Exceeded
> 
> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> Signed-off-by: Ron Shaffer <rshaffer@codeaurora.org>
> ---
>  include/net/bluetooth/hci_core.h |    2 ++
>  net/bluetooth/hci_conn.c         |   32 ++++++++++++++++++++++++++++----
>  net/bluetooth/hci_event.c        |   33 +++++++++++++++++----------------
>  3 files changed, 47 insertions(+), 20 deletions(-)

I did a small cleanup, but patch has been applied now.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 2/5] Support for adding UUID128 to extended inquiry   response
From: ingas @ 2010-07-27 20:08 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: Inga Stotland, linux-bluetooth, rshaffer, marcel, johan.hedberg
In-Reply-To: <AANLkTi=nW-E8S3ccyutn_LYafmhSXiGY62PVZJ6L2QnX@mail.gmail.com>

Hi Luiz,

> Hi,
>
> On Thu, Jul 22, 2010 at 7:06 PM, Inga Stotland <ingas@codeaurora.org>
> wrote:
>> ---
>>  src/sdpd-service.c |  108
>> ++++++++++++++++++++++++++++++++++++++++++++--------
>>  1 files changed, 92 insertions(+), 16 deletions(-)
>>
>> diff --git a/src/sdpd-service.c b/src/sdpd-service.c
>> index cdbb4f4..1314ada 100644
>> --- a/src/sdpd-service.c
>> +++ b/src/sdpd-service.c
>> @@ -49,6 +49,8 @@
>>  #include "manager.h"
>>  #include "adapter.h"
>
>> +
>
> I think you should probably split this in two parts, first update with
> the cleanups and then add the code to handle uuid 128.
>

Sure, I can split this in more patches.

>>  void create_ext_inquiry_response(const char *name,
>>                                        int8_t tx_power, sdp_list_t
>> *services,
>>                                        uint8_t *data)
>>
>> +               /* Check for duplicates */
>>                for (i = 0; i < index; i++)
>> -                       if (uuid[i] == rec->svclass.value.uuid16)
>> +                       if (uuid16[i] == rec->svclass.value.uuid16)
>>                                break;
>>
>> -               if (i == index - 1)
>> +               if (i < index)
>>                        continue;
>>

>
> Also this checks for duplicates looks suspicious, does it really need
> to check that in place and every time, I think it might be more
> efficient if we do that before generating the EIR data avoiding
> comparing data with different endianess or maybe it just make more
> sense to not allow duplicates in the database then we don't have to do
> this at all.
>

This check for duplicates was in place prior to my modifications. I merely
added a comment and fixed an existing problem.

If you examine the patch closely, you might notice that the previous
"check for duplicates" implementation was doing the following:
- cycling through the list of so far accumulated UUIDs in EIR and
comparing them to the current one. If duplicate is found, break out of
this cycling loop. Notice, that in the case of a duplicate, (i <
index)condition will be true, where index is the number of accumulated
UUIDs.
- the current implementation performs check for (i == index -1). Well, we
did not need to cycle through the whole array to cmpare to the last item
:) But if my reading of the original intent is correct, we don't want to
put a duplicate UUID in EIR, and, therefore, should go to next iteration
if a duplicate is found. Hence, the check should be (i < index).

Maybe it's a better idea to submit this fix separately.

I do not disagree that it would be better to check for duplicate records
elsewhere, but this  is outside the scope of this patch.

Regards,

Inga

^ permalink raw reply

* Re: [patch -next] bluetooth/hci_ath: kfree() => kfree_skb()
From: Marcel Holtmann @ 2010-07-27 22:28 UTC (permalink / raw)
  To: Gustavo F. Padovan
  Cc: Dan Carpenter, Suraj Sumangala, linux-bluetooth, kernel-janitors
In-Reply-To: <20100723181053.GN2620@vigoh>

Hi Dan,

> > sk_buffs have to be freed with kfree_skb() instead of kfree().
> > 
> > Signed-off-by: Dan Carpenter <error27@gmail.com>
> > 
> > diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
> > index 5ab258b..74a8f61 100755
> > --- a/drivers/bluetooth/hci_ath.c
> > +++ b/drivers/bluetooth/hci_ath.c
> > @@ -163,7 +163,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
> >  	struct ath_struct *ath = hu->priv;
> >  
> >  	if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
> > -		kfree(skb);
> > +		kfree_skb(skb);
> >  		return 0;
> >  	}
> 
> Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>

patch has been applied. Thanks.

Regards

Marcel



^ permalink raw reply

* Re: L2CAP unknown options
From: Gustavo F. Padovan @ 2010-07-28  3:32 UTC (permalink / raw)
  To: Ville Tervo; +Cc: linux-bluetooth@vger.kernel.org, Gustavo F. Padovan
In-Reply-To: <4C4EA1CB.2050406@nokia.com>

Hi Ville,

* Ville Tervo <ville.tervo@nokia.com> [2010-07-27 12:07:23 +0300]:

> Hi,
> 
> I found following problem with bluetooth-next-2.6.
> 
> Kernel disconnects if remote device replies with "unknown options"
> result code. I guess in that case a new config req should be sent
> without unknown option. I didn't check the spec yet.

It's a regression introduced by this commit 
625477523b4e656fbcc5ec2a8ca7a1beb39b1caf

It adds the RFC when requesting Basic Mode, this is a PTS requirement.
A possible fix should be send a new Config Req without RFC or do not
send the RFC in the first request when the other side doesn't support
Info Req.

> 
> The remote device is Nokia 9300.
> 
> 2010-07-27 11:44:07.364827 < ACL data: handle 11 flags 0x02 dlen 10
>     L2CAP(s): Info req: type 2
> 2010-07-27 11:44:07.365337 < HCI Command: Remote Name Request
> (0x01|0x0019) plen 10
>     bdaddr 00:12:37:F0:F1:77 mode 2 clkoffset 0x0000
> 2010-07-27 11:44:07.367793 > HCI Event: Command Status (0x0f) plen 4
>     Remote Name Request (0x01|0x0019) status 0x00 ncmd 1
> 2010-07-27 11:44:07.384797 > HCI Event: Max Slots Change (0x1b) plen 3
>     handle 11 slots 5
> 2010-07-27 11:44:07.406820 > ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Info rsp: type 2 result 1
>       Not supported
> 2010-07-27 11:44:07.406849 < ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Connect req: psm 1 scid 0x0040
> 2010-07-27 11:44:07.431790 > HCI Event: Remote Name Req Complete
> (0x07) plen 255
>     status 0x00 bdaddr 00:12:37:F0:F1:77 name 'vt-m'
> 2010-07-27 11:44:07.433780 > HCI Event: Number of Completed Packets
> (0x13) plen 5
>     handle 11 packets 2
> 2010-07-27 11:44:07.474801 > ACL data: handle 11 flags 0x02 dlen 16
>     L2CAP(s): Connect rsp: dcid 0x0042 scid 0x0040 result 1 status 2
>       Connection pending - Authorization pending
> 2010-07-27 11:44:07.668818 > ACL data: handle 11 flags 0x02 dlen 16
>     L2CAP(s): Connect rsp: dcid 0x0042 scid 0x0040 result 0 status 0
>       Connection successful
> 2010-07-27 11:44:07.668851 < ACL data: handle 11 flags 0x02 dlen 23
>     L2CAP(s): Config req: dcid 0x0042 flags 0x00 clen 11
>       RFC 0x00 (Basic)
> 2010-07-27 11:44:07.669814 > ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 0
> 2010-07-27 11:44:07.669840 < ACL data: handle 11 flags 0x02 dlen 18
>     L2CAP(s): Config rsp: scid 0x0042 flags 0x00 result 0 clen 4
>       MTU 672
> 2010-07-27 11:44:07.675794 > HCI Event: Number of Completed Packets
> (0x13) plen 5
>     handle 11 packets 2
> 2010-07-27 11:44:07.682822 > ACL data: handle 11 flags 0x02 dlen 19
>     L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 3 clen 5
>       Failure - unknown options
>       RFC QoS 0f 00 42
> 2010-07-27 11:44:07.682843 < ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Disconn req: dcid 0x0042 scid 0x0040
> 2010-07-27 11:44:07.693823 > ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Disconn rsp: dcid 0x0042 scid 0x0040

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: L2CAP unknown options
From: Gustavo F. Padovan @ 2010-07-28  4:16 UTC (permalink / raw)
  To: Ville Tervo; +Cc: linux-bluetooth@vger.kernel.org, Gustavo F. Padovan
In-Reply-To: <4C4EA1CB.2050406@nokia.com>

Hi Ville,

* Ville Tervo <ville.tervo@nokia.com> [2010-07-27 12:07:23 +0300]:

> Hi,
> 
> I found following problem with bluetooth-next-2.6.
> 
> Kernel disconnects if remote device replies with "unknown options"
> result code. I guess in that case a new config req should be sent
> without unknown option. I didn't check the spec yet.
> 
> The remote device is Nokia 9300.
> 
> 2010-07-27 11:44:07.364827 < ACL data: handle 11 flags 0x02 dlen 10
>     L2CAP(s): Info req: type 2
> 2010-07-27 11:44:07.365337 < HCI Command: Remote Name Request
> (0x01|0x0019) plen 10
>     bdaddr 00:12:37:F0:F1:77 mode 2 clkoffset 0x0000
> 2010-07-27 11:44:07.367793 > HCI Event: Command Status (0x0f) plen 4
>     Remote Name Request (0x01|0x0019) status 0x00 ncmd 1
> 2010-07-27 11:44:07.384797 > HCI Event: Max Slots Change (0x1b) plen 3
>     handle 11 slots 5
> 2010-07-27 11:44:07.406820 > ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Info rsp: type 2 result 1
>       Not supported
> 2010-07-27 11:44:07.406849 < ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Connect req: psm 1 scid 0x0040
> 2010-07-27 11:44:07.431790 > HCI Event: Remote Name Req Complete
> (0x07) plen 255
>     status 0x00 bdaddr 00:12:37:F0:F1:77 name 'vt-m'
> 2010-07-27 11:44:07.433780 > HCI Event: Number of Completed Packets
> (0x13) plen 5
>     handle 11 packets 2
> 2010-07-27 11:44:07.474801 > ACL data: handle 11 flags 0x02 dlen 16
>     L2CAP(s): Connect rsp: dcid 0x0042 scid 0x0040 result 1 status 2
>       Connection pending - Authorization pending
> 2010-07-27 11:44:07.668818 > ACL data: handle 11 flags 0x02 dlen 16
>     L2CAP(s): Connect rsp: dcid 0x0042 scid 0x0040 result 0 status 0
>       Connection successful
> 2010-07-27 11:44:07.668851 < ACL data: handle 11 flags 0x02 dlen 23
>     L2CAP(s): Config req: dcid 0x0042 flags 0x00 clen 11
>       RFC 0x00 (Basic)
> 2010-07-27 11:44:07.669814 > ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 0
> 2010-07-27 11:44:07.669840 < ACL data: handle 11 flags 0x02 dlen 18
>     L2CAP(s): Config rsp: scid 0x0042 flags 0x00 result 0 clen 4
>       MTU 672
> 2010-07-27 11:44:07.675794 > HCI Event: Number of Completed Packets
> (0x13) plen 5
>     handle 11 packets 2
> 2010-07-27 11:44:07.682822 > ACL data: handle 11 flags 0x02 dlen 19
>     L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 3 clen 5
>       Failure - unknown options
>       RFC QoS 0f 00 42

Actually the 9300 stack is broken here, it should only send the unknown
options that were in the ConfiqReq, i.e, only the RFC. But that doesn't
change the fact that we have a regression.

> 2010-07-27 11:44:07.682843 < ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Disconn req: dcid 0x0042 scid 0x0040
> 2010-07-27 11:44:07.693823 > ACL data: handle 11 flags 0x02 dlen 12
>     L2CAP(s): Disconn rsp: dcid 0x0042 scid 0x0040

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* RE: [PATCH 1/3] Add BT3 AMP device support, by Atheros Linux BT3 team.
From: Haijun Liu @ 2010-07-28  5:39 UTC (permalink / raw)
  To: David Vrabel, Dan Tian; +Cc: linux-bluetooth@vger.kernel.org, Luis Rodriguez
In-Reply-To: <4C4ECA72.50602@csr.com>

> -----Original Message-----
> From: David Vrabel [mailto:david.vrabel@csr.com]
> Sent: Tuesday, July 27, 2010 8:01 PM
> To: Dan Tian
> Cc: linux-bluetooth@vger.kernel.org; Haijun Liu; Luis Rodriguez
> Subject: Re: [PATCH 1/3] Add BT3 AMP device support, by Atheros Linux
> BT3 team.
> 
> What kernel were these diffed against?  I'd like to try them out but
> they don't apply to mainline.
> 
> David
> --
> David Vrabel, Senior Software Engineer, Drivers
> CSR, Churchill House, Cambridge Business Park,  Tel: +44 (0)1223 692562
> Cowley Road, Cambridge, CB4 0WZ                 http://www.csr.com/
> 
> 
> Member of the CSR plc group of companies. CSR plc registered in England
> and Wales, registered number 4187346, registered office Churchill House,
> Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United
> Kingdom


The branch is bluetooth-testing. 
Commit is 53a4bb8b3de6f74b6e1b8e684fba5cd6f60c0bfc

Best Regards
Haijun
86-21-61820900 Ext. 6331 Work
Haijun.Liu@Atheros.com
Skype: liu.haijun


^ permalink raw reply

* Re: [PATCH 2/5] Support for adding UUID128 to extended inquiry response
From: Luiz Augusto von Dentz @ 2010-07-28  5:59 UTC (permalink / raw)
  To: ingas; +Cc: linux-bluetooth, rshaffer, marcel, johan.hedberg
In-Reply-To: <94b1ecb27a99150d2cc0cae8fe6607af.squirrel@www.codeaurora.org>

Hi,

On Tue, Jul 27, 2010 at 11:08 PM,  <ingas@codeaurora.org> wrote:
> If you examine the patch closely, you might notice that the previous
> "check for duplicates" implementation was doing the following:
> - cycling through the list of so far accumulated UUIDs in EIR and
> comparing them to the current one. If duplicate is found, break out of
> this cycling loop. Notice, that in the case of a duplicate, (i <
> index)condition will be true, where index is the number of accumulated
> UUIDs.
> - the current implementation performs check for (i =3D=3D index -1). Well=
, we
> did not need to cycle through the whole array to cmpare to the last item
> :) But if my reading of the original intent is correct, we don't want to
> put a duplicate UUID in EIR, and, therefore, should go to next iteration
> if a duplicate is found. Hence, the check should be (i < index).

Yep, the check was already there before you touch it.

> Maybe it's a better idea to submit this fix separately.
>
> I do not disagree that it would be better to check for duplicate records
> elsewhere, but this =A0is outside the scope of this patch.

No problem, the other patches seems to be in good shape to be push
upstream, so lets try to do it this week.

--=20
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* [PATCH] Bluetooth: Resend ConfigReq on unknown options failure
From: Gustavo F. Padovan @ 2010-07-28  7:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo F. Padovan
In-Reply-To: <20100728033225.GB22156@vigoh>

From: Gustavo F. Padovan <padovan@profusion.mobi>

If the remote device send a ConfigRsp with the unknown options failure we
should remove that option from the ConfigReq and send it again.
This patch only remove the RFC option in the case it is a unknown option.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |   17 +++++++++--------
 net/bluetooth/l2cap.c         |   28 ++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 636724b..407af2b 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -373,14 +373,15 @@ struct l2cap_pinfo {
 	struct sock		*prev_c;
 };
 
-#define L2CAP_CONF_REQ_SENT       0x01
-#define L2CAP_CONF_INPUT_DONE     0x02
-#define L2CAP_CONF_OUTPUT_DONE    0x04
-#define L2CAP_CONF_MTU_DONE       0x08
-#define L2CAP_CONF_MODE_DONE      0x10
-#define L2CAP_CONF_CONNECT_PEND   0x20
-#define L2CAP_CONF_NO_FCS_RECV    0x40
-#define L2CAP_CONF_STATE2_DEVICE  0x80
+#define L2CAP_CONF_REQ_SENT       0x0001
+#define L2CAP_CONF_INPUT_DONE     0x0002
+#define L2CAP_CONF_OUTPUT_DONE    0x0004
+#define L2CAP_CONF_MTU_DONE       0x0008
+#define L2CAP_CONF_MODE_DONE      0x0010
+#define L2CAP_CONF_CONNECT_PEND   0x0020
+#define L2CAP_CONF_NO_FCS_RECV    0x0040
+#define L2CAP_CONF_STATE2_DEVICE  0x0080
+#define L2CAP_CONF_RFC_UNKNOWN    0x0200
 
 #define L2CAP_CONF_MAX_CONF_REQ 2
 #define L2CAP_CONF_MAX_CONF_RSP 2
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9ba1e8e..dc435a3 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2577,8 +2577,9 @@ done:
 		break;
 	}
 
-	l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-						(unsigned long) &rfc);
+	if (!(pi->conf_state & L2CAP_CONF_RFC_UNKNOWN))
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+							(unsigned long) &rfc);
 
 	/* FIXME: Need actual value of the flush timeout */
 	//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
@@ -2748,12 +2749,15 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_conf_req *req = data;
 	void *ptr = req->data;
-	int type, olen;
+	int type, olen, unknown = 0;
 	unsigned long val;
 	struct l2cap_conf_rfc rfc;
 
 	BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
 
+	if (*result == L2CAP_CONF_UNKNOWN)
+		unknown = 1;
+
 	while (len >= L2CAP_CONF_OPT_SIZE) {
 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
 
@@ -2774,6 +2778,11 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
 			break;
 
 		case L2CAP_CONF_RFC:
+			if (unknown) {
+				pi->conf_state |= L2CAP_CONF_RFC_UNKNOWN;
+				break;
+			}
+
 			if (olen == sizeof(rfc))
 				memcpy(&rfc, (void *)val, olen);
 
@@ -3161,6 +3170,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	u16 scid, flags, result;
 	struct sock *sk;
 	int len = cmd->len - sizeof(*rsp);
+	char req[64];
 
 	scid   = __le16_to_cpu(rsp->scid);
 	flags  = __le16_to_cpu(rsp->flags);
@@ -3180,7 +3190,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	case L2CAP_CONF_UNACCEPT:
 		if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
-			char req[64];
 
 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
 				l2cap_send_disconn_req(conn, sk, ECONNRESET);
@@ -3203,6 +3212,17 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 				goto done;
 			break;
 		}
+	case L2CAP_CONF_UNKNOWN:
+		len = l2cap_parse_conf_rsp(sk, rsp->data,
+						len, req, &result);
+		if (len < 0) {
+			l2cap_send_disconn_req(conn, sk, ECONNRESET);
+			goto done;
+		}
+
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+				l2cap_build_conf_req(sk, req), req);
+		goto done;
 
 	default:
 		sk->sk_err = ECONNRESET;
-- 
1.7.1.1


^ permalink raw reply related

* Re: [PATCH] Bluetooth: Resend ConfigReq on unknown options failure
From: Gustavo F. Padovan @ 2010-07-28  7:16 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: ville.tervo
In-Reply-To: <1280301080-565-1-git-send-email-gustavo@padovan.org>

Hi Ville,

* Gustavo F. Padovan <gustavo@padovan.org> [2010-07-28 04:11:20 -0300]:

> From: Gustavo F. Padovan <padovan@profusion.mobi>
> 
> If the remote device send a ConfigRsp with the unknown options failure we
> should remove that option from the ConfigReq and send it again.
> This patch only remove the RFC option in the case it is a unknown option.
> 
> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> ---
>  include/net/bluetooth/l2cap.h |   17 +++++++++--------
>  net/bluetooth/l2cap.c         |   28 ++++++++++++++++++++++++----
>  2 files changed, 33 insertions(+), 12 deletions(-)

Can you please test thi patch? I think it fix the unknown option
problem.


-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* MCAP patches
From: Santiago Carot-Nemesio @ 2010-07-28  8:00 UTC (permalink / raw)
  To: linux-bluetooth

Hello,
Next are the patches that we have prepared for MCAP.
Git can be cloned from git://gitorious.org/bluez-mcap-hdp/mcap-hdp.git

Regards.

^ permalink raw reply

* [PATCH 01/16] Initial support for MCAP
From: Santiago Carot-Nemesio @ 2010-07-28  8:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio
In-Reply-To: <1280304015-9230-1-git-send-email-sancane@gmail.com>

---
 Makefile.am       |   12 +++++++++-
 acinclude.m4      |    6 +++++
 health/mcap.c     |   55 +++++++++++++++++++++++++++++++++++++++++++++++
 health/mcap.h     |   38 +++++++++++++++++++++++++++++++++
 health/mcap_lib.h |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 171 insertions(+), 1 deletions(-)
 create mode 100644 health/mcap.c
 create mode 100644 health/mcap.h
 create mode 100644 health/mcap_lib.h

diff --git a/Makefile.am b/Makefile.am
index 65d4312..0781643 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -102,6 +102,7 @@ gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/object.c gdbus/watch.c
 builtin_modules =
 builtin_sources =
 builtin_nodist =
+mcap_sources =
 
 if PNATPLUGIN
 builtin_modules += pnat
@@ -168,6 +169,11 @@ builtin_modules += service
 builtin_sources += plugins/service.c
 endif
 
+if MCAP
+mcap_sources += health/mcap_lib.h 	\
+		health/mcap.h health/mcap.c
+endif
+
 builtin_modules += hciops
 builtin_sources += plugins/hciops.c
 
@@ -201,7 +207,8 @@ src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
 			src/adapter.h src/adapter.c \
 			src/device.h src/device.c \
 			src/dbus-common.c src/dbus-common.h \
-			src/dbus-hci.h src/dbus-hci.c
+			src/dbus-hci.h src/dbus-hci.c \
+			$(mcap_sources)
 src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
 							@CAPNG_LIBS@ -ldl
 src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
@@ -323,6 +330,9 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ \
 INCLUDES = -I$(builddir)/lib -I$(builddir)/src -I$(srcdir)/src \
 			-I$(srcdir)/audio -I$(srcdir)/sbc -I$(srcdir)/gdbus
 
+if MCAP
+INCLUDES += -I$(builddir)/health
+endif
 
 pkgconfigdir = $(libdir)/pkgconfig
 
diff --git a/acinclude.m4 b/acinclude.m4
index f5fdd66..239ccb1 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -167,6 +167,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	serial_enable=yes
 	network_enable=yes
 	service_enable=yes
+	mcap_enable=no
 	pnat_enable=no
 	tracer_enable=no
 	tools_enable=yes
@@ -216,6 +217,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		service_enable=${enableval}
 	])
 
+	AC_ARG_ENABLE(mcap, AC_HELP_STRING([--enable-mcap], [enable mcap support]), [
+		mcap_enable=${enableval}
+	])
+
 	AC_ARG_ENABLE(pnat, AC_HELP_STRING([--enable-pnat], [enable pnat plugin]), [
 		pnat_enable=${enableval}
 	])
@@ -330,6 +335,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(SERIALPLUGIN, test "${serial_enable}" = "yes")
 	AM_CONDITIONAL(NETWORKPLUGIN, test "${network_enable}" = "yes")
 	AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
+	AM_CONDITIONAL(MCAP, test "${mcap_enable}" = "yes")
 	AM_CONDITIONAL(ECHOPLUGIN, test "no" = "yes")
 	AM_CONDITIONAL(PNATPLUGIN, test "${pnat_enable}" = "yes")
 	AM_CONDITIONAL(TRACER, test "${tracer_enable}" = "yes")
diff --git a/health/mcap.c b/health/mcap.c
new file mode 100644
index 0000000..c17546b
--- /dev/null
+++ b/health/mcap.c
@@ -0,0 +1,55 @@
+/*
+ *
+ *  MCAP for BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  Authors:
+ *  Santiago Carot-Nemesio <sancane at gmail.com>
+ *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "log.h"
+#include "error.h"
+
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "mcap.h"
+#include "mcap_lib.h"
+
+struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
+					BtIOSecLevel sec,
+					uint16_t ccpsm,
+					uint16_t dcpsm,
+					mcap_mcl_event_cb mcl_connected,
+					mcap_mcl_event_cb mcl_reconnected,
+					mcap_mcl_event_cb mcl_disconnected,
+					mcap_mcl_event_cb mcl_uncached,
+					gpointer user_data,
+					GError **gerr)
+{
+	/* TODO: Create mcap_create_instance */
+	return NULL;
+}
+
+void mcap_release_instance(struct mcap_instance *mi)
+{
+	/* TODO: Create mcap_release_instance */
+}
diff --git a/health/mcap.h b/health/mcap.h
new file mode 100644
index 0000000..c1167fa
--- /dev/null
+++ b/health/mcap.h
@@ -0,0 +1,38 @@
+/*
+ *
+ *  MCAP for BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  Authors:
+ *  Santiago Carot-Nemesio <sancane at gmail.com>
+ *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
+ *
+ *  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
+ *
+ */
+
+#ifndef __MCAP_H
+#define __MCAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCAP_H */
diff --git a/health/mcap_lib.h b/health/mcap_lib.h
new file mode 100644
index 0000000..714610e
--- /dev/null
+++ b/health/mcap_lib.h
@@ -0,0 +1,61 @@
+/*
+ *
+ *  MCAP for BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  Authors:
+ *  Santiago Carot-Nemesio <sancane at gmail.com>
+ *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
+ *
+ *  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
+ *
+ */
+
+#ifndef __MCAP_LIB_H
+#define __MCAP_LIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "adapter.h"
+#include "btio.h"
+#include <bluetooth/l2cap.h>
+
+struct mcap_instance;
+struct mcap_mcl;
+
+typedef void (* mcap_mcl_event_cb) (struct mcap_mcl *mcl, gpointer data);
+
+/* MCAP main operations */
+
+struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
+					BtIOSecLevel sec, uint16_t ccpsm,
+					uint16_t dcpsm,
+					mcap_mcl_event_cb mcl_connected,
+					mcap_mcl_event_cb mcl_reconnected,
+					mcap_mcl_event_cb mcl_disconnected,
+					mcap_mcl_event_cb mcl_uncached,
+					gpointer user_data,
+					GError **gerr);
+
+void mcap_release_instance(struct mcap_instance *mi);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCAP_LIB_H */
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 02/16] Add MCAP instance management
From: Santiago Carot-Nemesio @ 2010-07-28  8:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio
In-Reply-To: <1280304015-9230-2-git-send-email-sancane@gmail.com>

---
 Makefile.am            |    2 +-
 health/mcap.c          |  153 +++++++++++++++++++++++++++++++++++++++++++++++-
 health/mcap.h          |    4 +
 health/mcap_internal.h |   52 ++++++++++++++++
 health/mcap_lib.h      |   30 +++++++++
 5 files changed, 237 insertions(+), 4 deletions(-)
 create mode 100644 health/mcap_internal.h

diff --git a/Makefile.am b/Makefile.am
index 0781643..c8bd62a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -170,7 +170,7 @@ builtin_sources += plugins/service.c
 endif
 
 if MCAP
-mcap_sources += health/mcap_lib.h 	\
+mcap_sources += health/mcap_lib.h health/mcap_internal.h \
 		health/mcap.h health/mcap.c
 endif
 
diff --git a/health/mcap.c b/health/mcap.c
index c17546b..54e6355 100644
--- a/health/mcap.c
+++ b/health/mcap.c
@@ -33,6 +33,30 @@
 
 #include "mcap.h"
 #include "mcap_lib.h"
+#include "mcap_internal.h"
+
+#define MCAP_ERROR g_quark_from_static_string("mcap-error-quark")
+
+
+static void mcap_mcl_shutdown(struct mcap_mcl *mcl)
+{
+	/* TODO: implement mcap_mcl_shutdown */
+}
+
+void mcap_mcl_unref(struct mcap_mcl *mcl)
+{
+	/* TODO: implement mcap_mcl_unref */
+}
+
+static void confirm_dc_event_cb(GIOChannel *chan, gpointer user_data)
+{
+	/* TODO: implement confirm_dc_event_cb */
+}
+
+static void confirm_mcl_event_cb(GIOChannel *chan, gpointer user_data)
+{
+	/* TODO: implement confirm_mcl_event_cb */
+}
 
 struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
 					BtIOSecLevel sec,
@@ -45,11 +69,134 @@ struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
 					gpointer user_data,
 					GError **gerr)
 {
-	/* TODO: Create mcap_create_instance */
-	return NULL;
+	struct mcap_instance *ms;
+
+	if (sec < BT_IO_SEC_MEDIUM) {
+		g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+				"Security level can't be minor of %d",
+				BT_IO_SEC_MEDIUM);
+		return NULL;
+	}
+
+	if (!(mcl_connected && mcl_reconnected &&
+			mcl_disconnected && mcl_uncached)) {
+		g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+				"The callbacks can't be null");
+		return NULL;
+	}
+
+	ms = g_new0(struct mcap_instance, 1);
+
+	adapter_get_address(btd_adapter, &ms->src);
+
+	ms->sec = sec;
+	ms->mcl_connected_cb = mcl_connected;
+	ms->mcl_reconnected_cb = mcl_reconnected;
+	ms->mcl_disconnected_cb = mcl_disconnected;
+	ms->mcl_uncached_cb = mcl_uncached;
+	ms->user_data = user_data;
+
+	/* Listen incoming connections in control channel */
+	ms->ccio = bt_io_listen(BT_IO_L2CAP, NULL, confirm_mcl_event_cb, ms,
+				NULL, gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &ms->src,
+				BT_IO_OPT_PSM, ccpsm,
+				BT_IO_OPT_MTU, MCAP_CC_MTU,
+				BT_IO_OPT_SEC_LEVEL, sec,
+				BT_IO_OPT_INVALID);
+	if (!ms->ccio) {
+		error("%s", (*gerr)->message);
+		g_free(ms);
+		return NULL;
+	}
+
+	/* Listen incoming connections in data channels */
+	ms->dcio = bt_io_listen(BT_IO_L2CAP, NULL, confirm_dc_event_cb, ms,
+				NULL, gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &ms->src,
+				BT_IO_OPT_PSM, dcpsm,
+				BT_IO_OPT_MTU, MCAP_DC_MTU,
+				BT_IO_OPT_SEC_LEVEL, sec,
+				BT_IO_OPT_INVALID);
+	if (!ms->dcio) {
+		g_io_channel_shutdown(ms->ccio, TRUE, NULL);
+		g_io_channel_unref(ms->ccio);
+		ms->ccio = NULL;
+		error("%s", (*gerr)->message);
+		g_free(ms);
+		return NULL;
+	}
+	/* Initialize random seed to generate mdlids for this instance */
+	srand(time(NULL));
+	return ms;
 }
 
 void mcap_release_instance(struct mcap_instance *mi)
 {
-	/* TODO: Create mcap_release_instance */
+	GSList *l;
+
+	if (!mi)
+		return;
+
+	if (mi->ccio) {
+		g_io_channel_shutdown(mi->ccio, TRUE, NULL);
+		g_io_channel_unref(mi->ccio);
+		mi->ccio = NULL;
+	}
+
+	if (mi->dcio) {
+		g_io_channel_shutdown(mi->dcio, TRUE, NULL);
+		g_io_channel_unref(mi->dcio);
+		mi->dcio = NULL;
+	}
+
+	for (l = mi->mcls; l; l = l->next) {
+		mcap_mcl_shutdown(l->data);
+		mcap_mcl_unref(l->data);
+	}
+	g_slist_free(mi->mcls);
+	mi->mcls = NULL;
+
+	for (l = mi->cached; l; l = l->next)
+		mcap_mcl_unref(l->data);
+	g_slist_free(mi->cached);
+	mi->cached = NULL;
+
+	g_free(mi);
+}
+
+uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err)
+{
+	uint16_t lpsm;
+
+	if (!(mi && mi->ccio)) {
+		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+			"Invalid MCAP instance");
+		return 0;
+	}
+
+	bt_io_get(mi->ccio, BT_IO_L2CAP, err,
+			BT_IO_OPT_PSM, &lpsm,
+			BT_IO_OPT_INVALID);
+	if (*err)
+		return 0;
+	return lpsm;
+}
+
+uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err)
+{
+	uint16_t lpsm;
+
+	if (!(mi && mi->dcio)) {
+		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
+			"Invalid MCAP instance");
+		return 0;
+	}
+
+	bt_io_get(mi->dcio, BT_IO_L2CAP, err,
+			BT_IO_OPT_PSM, &lpsm,
+			BT_IO_OPT_INVALID);
+	if (*err)
+		return 0;
+	return lpsm;
 }
diff --git a/health/mcap.h b/health/mcap.h
index c1167fa..139b562 100644
--- a/health/mcap.h
+++ b/health/mcap.h
@@ -31,6 +31,10 @@
 extern "C" {
 #endif
 
+/* maximum transmission unit for channels */
+#define MCAP_CC_MTU	48
+#define MCAP_DC_MTU	L2CAP_DEFAULT_MTU
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/health/mcap_internal.h b/health/mcap_internal.h
new file mode 100644
index 0000000..ed4ed58
--- /dev/null
+++ b/health/mcap_internal.h
@@ -0,0 +1,52 @@
+/*
+ *
+ *  MCAP for BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ *  Authors:
+ *  Santiago Carot-Nemesio <sancane at gmail.com>
+ *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
+ *
+ *  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
+ *
+ */
+
+#ifndef __MCAP_INTERNAL_H
+#define __MCAP_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct mcap_instance {
+	bdaddr_t		src;			/* Source address */
+	GIOChannel		*ccio;			/* Control Channel IO */
+	GIOChannel		*dcio;			/* Data Channel IO */
+	GSList			*mcls;			/* MCAP instance list */
+	GSList			*cached;		/* List with all cached MCLs (MAX_CACHED macro) */
+	BtIOSecLevel		sec;			/* Security level */
+	mcap_mcl_event_cb	mcl_connected_cb;	/* New MCL connected */
+	mcap_mcl_event_cb	mcl_reconnected_cb;	/* Old MCL has been reconnected */
+	mcap_mcl_event_cb	mcl_disconnected_cb;	/* MCL disconnected */
+	mcap_mcl_event_cb	mcl_uncached_cb;	/* MCL has been removed from MCAP cache */
+	gpointer		user_data;		/* Data to be provided in callbacks */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCAP_INTERNAL_H */
diff --git a/health/mcap_lib.h b/health/mcap_lib.h
index 714610e..81d8b14 100644
--- a/health/mcap_lib.h
+++ b/health/mcap_lib.h
@@ -35,11 +35,38 @@ extern "C" {
 #include "btio.h"
 #include <bluetooth/l2cap.h>
 
+typedef enum {
+/* MCAP Error Response Codes */
+	MCAP_ERROR_INVALID_OP_CODE = 1,
+	MCAP_ERROR_INVALID_PARAM_VALUE,
+	MCAP_ERROR_INVALID_MDEP,
+	MCAP_ERROR_MDEP_BUSY,
+	MCAP_ERROR_INVALID_MDL,
+	MCAP_ERROR_MDL_BUSY,
+	MCAP_ERROR_INVALID_OPERATION,
+	MCAP_ERROR_RESOURCE_UNAVAILABLE,
+	MCAP_ERROR_UNSPECIFIED_ERROR,
+	MCAP_ERROR_REQUEST_NOT_SUPPORTED,
+	MCAP_ERROR_CONFIGURATION_REJECTED,
+/* MCAP Internal Errors */
+	MCAP_ERROR_INVALID_ARGS,
+	MCAP_ERROR_ALREADY_EXISTS,
+	MCAP_ERROR_REQ_IGNORED,
+	MCAP_ERROR_MCL_CLOSED,
+	MCAP_ERROR_FAILED
+} McapError;
+
 struct mcap_instance;
 struct mcap_mcl;
 
+/************ Callbacks ************/
+
+/* mcl callbacks */
+
 typedef void (* mcap_mcl_event_cb) (struct mcap_mcl *mcl, gpointer data);
 
+/************ Operations ************/
+
 /* MCAP main operations */
 
 struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
@@ -54,6 +81,9 @@ struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
 
 void mcap_release_instance(struct mcap_instance *mi);
 
+uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err);
+uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH 03/16] Receive MCAP mcl connections from remote devices
From: Santiago Carot-Nemesio @ 2010-07-28  8:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Santiago Carot-Nemesio
In-Reply-To: <1280304015-9230-3-git-send-email-sancane@gmail.com>

---
 health/mcap.c          |  209 +++++++++++++++++++++++++++++++++++++++++++++++-
 health/mcap.h          |   21 +++++
 health/mcap_internal.h |   52 ++++++++++++
 health/mcap_lib.h      |   15 ++++
 4 files changed, 295 insertions(+), 2 deletions(-)

diff --git a/health/mcap.c b/health/mcap.c
index 54e6355..282580d 100644
--- a/health/mcap.c
+++ b/health/mcap.c
@@ -38,24 +38,229 @@
 #define MCAP_ERROR g_quark_from_static_string("mcap-error-quark")
 
 
+static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data)
+{
+	DBG("MCAP Unmanaged mdl connection");
+}
+
+static void default_mdl_closed_cb(struct mcap_mdl *mdl, gpointer data)
+{
+	DBG("MCAP Unmanaged mdl closed");
+}
+
+static void default_mdl_deleted_cb(struct mcap_mdl *mdl, gpointer data)
+{
+	DBG("MCAP Unmanaged mdl deleted");
+}
+
+static void default_mdl_aborted_cb(struct mcap_mdl *mdl, gpointer data)
+{
+	DBG("MCAP Unmanaged mdl aborted");
+}
+
+static uint8_t default_mdl_conn_req_cb(struct mcap_mcl *mcl,
+						uint8_t mdepid, uint16_t mdlid,
+						uint8_t *conf, gpointer data)
+{
+	DBG("MCAP mdl remote connection aborted");
+	/* Due to this callback isn't managed this request won't be supported */
+	return MCAP_REQUEST_NOT_SUPPORTED;
+}
+
+static uint8_t default_mdl_reconn_req_cb(struct mcap_mdl *mdl,
+						gpointer data)
+{
+	DBG("MCAP mdl remote reconnection aborted");
+	/* Due to this callback isn't managed this request won't be supported */
+	return MCAP_REQUEST_NOT_SUPPORTED;
+}
+
+static void set_default_cb(struct mcap_mcl *mcl)
+{
+	if (!mcl->cb)
+		mcl->cb = g_new0(struct mcap_mdl_cb, 1);
+
+	mcl->cb->mdl_connected = default_mdl_connected_cb;
+	mcl->cb->mdl_closed = default_mdl_closed_cb;
+	mcl->cb->mdl_deleted = default_mdl_deleted_cb;
+	mcl->cb->mdl_aborted = default_mdl_aborted_cb;
+	mcl->cb->mdl_conn_req = default_mdl_conn_req_cb;
+	mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb;
+}
+
+static struct mcap_mcl *find_mcl(GSList *list, const bdaddr_t *addr)
+{
+	GSList *l;
+	struct mcap_mcl *mcl;
+
+	for (l = list; l; l = l->next) {
+		mcl = l->data;
+
+		if (!bacmp(&mcl->addr, addr))
+			return mcl;
+	}
+
+	return NULL;
+}
+
 static void mcap_mcl_shutdown(struct mcap_mcl *mcl)
 {
 	/* TODO: implement mcap_mcl_shutdown */
 }
 
+static void mcap_mcl_release(struct mcap_mcl *mcl)
+{
+	/* TODO: implement mcap_mcl_release */
+}
+
+static void mcap_mcl_check_del(struct mcap_mcl *mcl)
+{
+	if (mcl->ctrl & MCAP_CTRL_CACHED)
+		mcap_mcl_shutdown(mcl);
+	else
+		mcap_mcl_unref(mcl);
+}
+
+static void mcap_uncache_mcl(struct mcap_mcl *mcl)
+{
+	if (!(mcl->ctrl & MCAP_CTRL_CACHED))
+		return;
+
+	DBG("Got MCL from cache");
+
+	mcl->ms->cached = g_slist_remove(mcl->ms->cached, mcl);
+	mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls, mcl);
+	mcl->ctrl &= ~MCAP_CTRL_CACHED;
+	mcl->ctrl &= ~MCAP_CTRL_FREE;
+}
+
+struct mcap_mcl *mcap_mcl_ref(struct mcap_mcl *mcl)
+{
+	mcl->ref++;
+
+	DBG("mcap_mcl_ref(%p): ref=%d", mcl, mcl->ref);
+
+	return mcl;
+}
+
 void mcap_mcl_unref(struct mcap_mcl *mcl)
 {
-	/* TODO: implement mcap_mcl_unref */
+	mcl->ref--;
+
+	DBG("mcap_mcl_unref(%p): ref=%d", mcl, mcl->ref);
+
+	if ((mcl->ctrl & MCAP_CTRL_CACHED) && (mcl->ref < 2)) {
+		/* Free space in cache memory due any other profile has a local
+		 * copy of current MCL stored in cache */
+		DBG("Remove from cache (%p): ref=%d", mcl, mcl->ref);
+		mcl->ms->cached = g_slist_remove(mcl->ms->cached, mcl);
+		mcap_mcl_release(mcl);
+		return;
+	}
+
+	if (mcl->ref > 0)
+		return;
+
+	mcap_mcl_release(mcl);
 }
 
+static gboolean mcl_control_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	/* TODO: Create mcl_control_cb */
+	return FALSE;
+}
 static void confirm_dc_event_cb(GIOChannel *chan, gpointer user_data)
 {
 	/* TODO: implement confirm_dc_event_cb */
 }
 
+static void connect_mcl_event_cb(GIOChannel *chan, GError *err,
+							gpointer user_data)
+{
+	struct mcap_mcl *mcl = user_data;
+	gboolean reconn;
+
+	if (err) {
+		mcap_mcl_check_del(mcl);
+		return;
+	}
+
+	mcl->state = MCL_CONNECTED;
+	mcl->role = MCL_ACCEPTOR;
+	mcl->req = MCL_AVAILABLE;
+	mcl->cc = g_io_channel_ref(chan);
+	mcl->ctrl |= MCAP_CTRL_STD_OP;
+
+	reconn = (mcl->ctrl & MCAP_CTRL_CACHED);
+	if (reconn)
+		mcap_uncache_mcl(mcl);
+	else
+		mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls, mcl);
+
+	mcl->wid = g_io_add_watch(mcl->cc,
+			G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+			(GIOFunc) mcl_control_cb, mcl);
+
+	/* Callback to report new MCL */
+	if (reconn)
+		mcl->ms->mcl_reconnected_cb(mcl, mcl->ms->user_data);
+	else
+		mcl->ms->mcl_connected_cb(mcl, mcl->ms->user_data);
+
+	if (mcl->ref == 1) {
+		mcl->ms->mcls = g_slist_remove(mcl->ms->mcls, mcl);
+		mcap_mcl_unref(mcl);
+	}
+}
+
 static void confirm_mcl_event_cb(GIOChannel *chan, gpointer user_data)
 {
-	/* TODO: implement confirm_mcl_event_cb */
+	struct mcap_instance *ms = user_data;
+	struct mcap_mcl *mcl;
+	bdaddr_t dst;
+	char address[18], srcstr[18];
+	GError *err = NULL;
+
+	bt_io_get(chan, BT_IO_L2CAP, &err,
+			BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_DEST, address,
+			BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto drop;
+	}
+
+	ba2str(&ms->src, srcstr);
+	mcl = find_mcl(ms->mcls, &dst);
+	if (mcl) {
+		error("Control channel already created with %s on adapter %s",
+				address, srcstr);
+		goto drop;
+	}
+
+	mcl = find_mcl(ms->cached, &dst);
+	if (!mcl) {
+		mcl = g_new0(struct mcap_mcl, 1);
+		mcl->ms = ms;
+		bacpy(&mcl->addr, &dst);
+		set_default_cb(mcl);
+		mcl->next_mdl = (rand() % MCAP_MDLID_FINAL) + 1;
+		mcl = mcap_mcl_ref(mcl);
+	}
+
+	if (!bt_io_accept(chan, connect_mcl_event_cb, mcl, NULL, &err)) {
+		error("mcap accept error: %s", err->message);
+		if (!(mcl->ctrl & MCAP_CTRL_CACHED))
+			mcap_mcl_unref(mcl);
+		g_error_free(err);
+		goto drop;
+	}
+
+	return;
+drop:
+	g_io_channel_shutdown(chan, TRUE, NULL);
 }
 
 struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
diff --git a/health/mcap.h b/health/mcap.h
index 139b562..a45cc8a 100644
--- a/health/mcap.h
+++ b/health/mcap.h
@@ -35,6 +35,27 @@ extern "C" {
 #define MCAP_CC_MTU	48
 #define MCAP_DC_MTU	L2CAP_DEFAULT_MTU
 
+/* MCAP Response codes */
+#define MCAP_SUCCESS			0x00
+#define MCAP_INVALID_OP_CODE		0x01
+#define MCAP_INVALID_PARAM_VALUE	0x02
+#define MCAP_INVALID_MDEP		0x03
+#define MCAP_MDEP_BUSY			0x04
+#define MCAP_INVALID_MDL		0x05
+#define MCAP_MDL_BUSY			0x06
+#define MCAP_INVALID_OPERATION		0x07
+#define MCAP_RESOURCE_UNAVAILABLE	0x08
+#define MCAP_UNSPECIFIED_ERROR		0x09
+#define MCAP_REQUEST_NOT_SUPPORTED	0x0A
+#define MCAP_CONFIGURATION_REJECTED	0x0B
+
+/* MDL IDs */
+#define MCAP_MDLID_RESERVED		0x0000
+#define MCAP_MDLID_INITIAL		0x0001
+#define MCAP_MDLID_FINAL		0xFEFF
+#define MCAP_ALL_MDLIDS			0xFFFF
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/health/mcap_internal.h b/health/mcap_internal.h
index ed4ed58..aab9e06 100644
--- a/health/mcap_internal.h
+++ b/health/mcap_internal.h
@@ -31,6 +31,33 @@
 extern "C" {
 #endif
 
+typedef enum {
+	MCL_CONNECTED,
+	MCL_PENDING,
+	MCL_ACTIVE,
+	MCL_IDLE
+} MCLState;
+
+typedef enum {
+	MCL_ACCEPTOR,
+	MCL_INITIATOR
+} MCLRole;
+
+typedef enum {
+	MCL_AVAILABLE,
+	MCL_WAITING_RSP
+} MCAPCtrl;
+
+struct mcap_mdl_cb {
+	mcap_mdl_event_cb 		mdl_connected;	/* Remote device has created a MDL */
+	mcap_mdl_event_cb 		mdl_closed;	/* Remote device has closed a MDL */
+	mcap_mdl_event_cb 		mdl_deleted;	/* Remote device requested deleting a MDL */
+	mcap_mdl_event_cb		mdl_aborted;	/* Remote device aborted the mdl creation */
+	mcap_remote_mdl_conn_req_cb	mdl_conn_req;	/* Remote device requested creating a MDL */
+	mcap_remote_mdl_reconn_req_cb 	mdl_reconn_req;	/* Remote device requested reconnecting a MDL */
+	gpointer			user_data;	/* User data */
+};
+
 struct mcap_instance {
 	bdaddr_t		src;			/* Source address */
 	GIOChannel		*ccio;			/* Control Channel IO */
@@ -45,6 +72,31 @@ struct mcap_instance {
 	gpointer		user_data;		/* Data to be provided in callbacks */
 };
 
+struct mcap_mcl {
+	struct mcap_instance	*ms;		/* MCAP instance where this MCL belongs */
+	bdaddr_t		addr;		/* Device address */
+	GIOChannel		*cc;		/* MCAP Control Channel IO */
+	guint			wid;		/* MCL Watcher id */
+	GSList			*mdls;		/* List of Data Channels shorted by mdlid */
+	MCLState		state;		/* Current MCL State */
+	MCLRole			role;		/* Initiator or acceptor of this MCL */
+	MCAPCtrl		req;		/* Request control flag */
+	void			*priv_data;	/* Temporal data to manage in responses */
+	struct mcap_mdl_cb	*cb;		/* MDL callbacks */
+	guint			tid;		/* Timer id for waiting for a response */
+	uint8_t			*lcmd;		/* Last command sent */
+	guint			ref;		/* References counter */
+	uint8_t			ctrl;		/* MCL control flag */
+	uint16_t		next_mdl;	/* id used to create next MDL */
+};
+
+#define	MCAP_CTRL_CACHED	0x01	/* MCL is cached */
+#define	MCAP_CTRL_STD_OP	0x02	/* Support for standard op codes */
+#define	MCAP_CTRL_SYNC_OP	0x04	/* Support for synchronization commands */
+#define	MCAP_CTRL_CONN		0x08	/* MCL is in connecting process */
+#define	MCAP_CTRL_FREE		0x10	/* MCL is marked as releasable */
+#define	MCAP_CTRL_NOCACHE	0x20	/* MCL is marked as not cacheable */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/health/mcap_lib.h b/health/mcap_lib.h
index 81d8b14..fcf69ee 100644
--- a/health/mcap_lib.h
+++ b/health/mcap_lib.h
@@ -58,15 +58,30 @@ typedef enum {
 
 struct mcap_instance;
 struct mcap_mcl;
+struct mcap_mdl;
 
 /************ Callbacks ************/
 
+/* mdl callbacks */
+
+typedef void (* mcap_mdl_event_cb) (struct mcap_mdl *mdl, gpointer data);
+
+/* Next function should return an MCAP appropriate response code */
+typedef uint8_t (* mcap_remote_mdl_conn_req_cb) (struct mcap_mcl *mcl,
+						uint8_t mdepid, uint16_t mdlid,
+						uint8_t *conf, gpointer data);
+typedef uint8_t (* mcap_remote_mdl_reconn_req_cb) (struct mcap_mdl *mdl,
+						gpointer data);
+
 /* mcl callbacks */
 
 typedef void (* mcap_mcl_event_cb) (struct mcap_mcl *mcl, gpointer data);
 
 /************ Operations ************/
 
+struct mcap_mcl *mcap_mcl_ref(struct mcap_mcl *mcl);
+void mcap_mcl_unref(struct mcap_mcl *mcl);
+
 /* MCAP main operations */
 
 struct mcap_instance *mcap_create_instance(struct btd_adapter *btd_adapter,
-- 
1.6.3.3


^ permalink raw reply related


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