Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] Fix issues with emails category
From: Lukasz Pawlik @ 2010-08-23 13:45 UTC (permalink / raw)
  To: linux-bluetooth

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



[-- Attachment #2: 0001-Fix-issues-with-emails-category.patch --]
[-- Type: text/x-patch, Size: 5783 bytes --]

From 35e6beaea7a20c42c3bd13af9b18e0883dd33f66 Mon Sep 17 00:00:00 2001
From: Lukasz Pawlik <lucas.pawlik@gmail.com>
Date: Mon, 23 Aug 2010 15:25:20 +0200
Subject: [PATCH] Fix issues with emails category

Previously all emails sent during phonebook pull had the same
category INTERNET. Now email are sent with valid category name
(INTERNET;HOME or INTERNET;WORK)
---
 plugins/phonebook-tracker.c |   31 +++++++++++++++++--------
 plugins/vcard.c             |   53 ++++++++++++++++++++++++++++++++++---------
 plugins/vcard.h             |   11 +++++++++
 3 files changed, 74 insertions(+), 21 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 3f63dcb..35742b6 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -687,27 +687,38 @@ static void add_phone_number(struct phonebook_contact *contact,
 	contact->numbers = g_slist_append(contact->numbers, number);
 }
 
-static gchar *find_email(GSList *emails, const char *email)
+static struct phonebook_email *find_email(GSList *emails, const char *address,
+										int type)
 {
 	GSList *l;
 
-	for (l = emails; l; l = l->next)
-		if (g_strcmp0(l->data, email) == 0)
-			return l->data;
+	for (l = emails; l; l = l->next) {
+		struct phonebook_email *email;
+		email = l->data;
+		if (g_strcmp0(email->address, address) == 0 &&
+					email->type == type)
+			return email;
+	}
 
 	return NULL;
 }
 
-static void add_email(struct phonebook_contact *contact, const char *email)
+static void add_email(struct phonebook_contact *contact, const char *address,
+						int type)
 {
-	if (email == NULL || strlen(email) == 0)
+	struct phonebook_email *email;
+	if (address == NULL || strlen(address) == 0)
 		return;
 
 	/* Not adding email if there is already added with the same value */
-	if (find_email(contact->emails, email))
+	if (find_email(contact->emails, address, type))
 		return;
 
-	contact->emails = g_slist_append(contact->emails, g_strdup(email));
+	email = g_new0(struct phonebook_email, 1);
+	email->address = g_strdup(address);
+	email->type = type;
+
+	contact->emails = g_slist_append(contact->emails, email);
 }
 
 static GString *gen_vcards(GSList *contacts,
@@ -817,8 +828,8 @@ add_numbers:
 	add_phone_number(contact, reply[COL_FAX_NUMBER], TEL_TYPE_FAX);
 
 	/* Adding emails */
-	add_email(contact, reply[COL_HOME_EMAIL]);
-	add_email(contact, reply[COL_WORK_EMAIL]);
+	add_email(contact, reply[COL_HOME_EMAIL], EMAIL_TYPE_HOME);
+	add_email(contact, reply[COL_WORK_EMAIL], EMAIL_TYPE_WORK);
 
 	DBG("contact %p", contact);
 
diff --git a/plugins/vcard.c b/plugins/vcard.c
index 0eed8ae..3b67535 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -306,19 +306,39 @@ static void vcard_printf_slash_tag(GString *vcards, const char *tag,
 	vcard_printf(vcards, "%s:%s", buf, field);
 }
 
-static void vcard_printf_email(GString *vcards, const char *email)
+static void vcard_printf_email(GString *vcards, uint8_t format,
+								const char *address,
+								enum phonebook_email_type category)
 {
+	const char *category_string = "";
+	char field[LEN_MAX];
 	int len = 0;
 
-	if (email)
-		len = strlen(email);
+	if (!address || !(len = strlen(address)))
+		return;
 
-	if (len) {
-		char field[LEN_MAX];
-		add_slash(field, email, LEN_MAX, len);
-		vcard_printf(vcards,
-				"EMAIL;TYPE=INTERNET:%s", field);
+	switch (category){
+	case EMAIL_TYPE_HOME:
+		if (format == FORMAT_VCARD21)
+			category_string = "INTERNET;HOME";
+		else if (format == FORMAT_VCARD30)
+			category_string = "TYPE=INTERNET;TYPE=HOME";
+		break;
+	case EMAIL_TYPE_WORK:
+		if (format == FORMAT_VCARD21)
+			category_string = "INTERNET;WORK";
+		else if (format == FORMAT_VCARD30)
+			category_string = "TYPE=INTERNET;TYPE=WORK";
+		break;
+	default:
+		if (format == FORMAT_VCARD21)
+			category_string = "INTERNET";
+		else if (format == FORMAT_VCARD30)
+			category_string = "TYPE=INTERNET";
 	}
+
+	add_slash(field, address, LEN_MAX, len);
+	vcard_printf(vcards,"EMAIL;%s:%s", category_string, field);
 }
 
 static gboolean org_fields_present(struct phonebook_contact *contact)
@@ -421,8 +441,11 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 	if (filter & FILTER_EMAIL) {
 		GSList *l;
 
-		for (l = contact->emails; l; l = l->next)
-			vcard_printf_email(vcards, l->data);
+		for (l = contact->emails; l; l = l->next){
+			struct phonebook_email *email = l->data;
+
+			vcard_printf_email(vcards, format, email->address, email->type);
+		}
 	}
 
 	if (filter & FILTER_ADR)
@@ -459,6 +482,14 @@ static void number_free(gpointer data, gpointer user_data)
 	g_free(number);
 }
 
+static void email_free(gpointer data, gpointer user_data)
+{
+	struct phonebook_email *email = data;
+
+	g_free(email->address);
+	g_free(email);
+}
+
 void phonebook_contact_free(struct phonebook_contact *contact)
 {
 	if (contact == NULL)
@@ -467,7 +498,7 @@ void phonebook_contact_free(struct phonebook_contact *contact)
 	g_slist_foreach(contact->numbers, number_free, NULL);
 	g_slist_free(contact->numbers);
 
-	g_slist_foreach(contact->emails, (GFunc) g_free, NULL);
+	g_slist_foreach(contact->emails, email_free, NULL);
 	g_slist_free(contact->emails);
 
 	g_free(contact->fullname);
diff --git a/plugins/vcard.h b/plugins/vcard.h
index 0f52425..a22dfc1 100644
--- a/plugins/vcard.h
+++ b/plugins/vcard.h
@@ -27,6 +27,12 @@ enum phonebook_number_type {
 	TEL_TYPE_OTHER,
 };
 
+enum phonebook_email_type {
+	EMAIL_TYPE_HOME,
+	EMAIL_TYPE_WORK,
+	EMAIL_TYPE_OTHER,
+};
+
 enum phonebook_call_type {
 	CALL_TYPE_NOT_A_CALL,
 	CALL_TYPE_MISSED,
@@ -39,6 +45,11 @@ struct phonebook_number {
 	int type;
 };
 
+struct phonebook_email {
+	char *address;
+	int  type;
+};
+
 struct phonebook_contact {
 	char *fullname;
 	char *given;
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH v3] Firmware download for Qualcomm Bluetooth devices
From: Matt Wilson @ 2010-08-23 14:36 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth, marcel, rshaffer
In-Reply-To: <20100820223757.GA23924@jh-x301>

On Sat, 2010-08-21 at 01:37 +0300, Johan Hedberg wrote:
> Hi Matt,
> 
> On Fri, Aug 20, 2010, Matthew Wilson wrote:
> > Configures device address from hciattach parameter.
> > UART speed limited to 115200.
> > Requires separate device specific firmware.
> > ---
> >  Makefile.tools             |    3 +-
> >  tools/hciattach.c          |   10 ++
> >  tools/hciattach.h          |    1 +
> >  tools/hciattach_qualcomm.c |  279 ++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 292 insertions(+), 1 deletions(-)
> >  create mode 100644 tools/hciattach_qualcomm.c
> 
> Thanks, the patch applies cleanly now. However, I spotted a couple of
> whitespace/coding style issues that would be good to get fixed before
> pushing this upstream:
> 
> > +#define FAILIF(x, args...) do {   \
> > +	if (x) {					  \
> > +		fprintf(stderr, ##args);  \
> > +		return -1;				  \
> > +	}							  \
> > +} while(0)
> 
> Before each \ at the end of the line you use a mix of tabs and spaces.
> Please just use tabs.
> 

See below for origin of style.

> > +typedef struct {
> > +	uint8_t uart_prefix;
> > +	hci_event_hdr hci_hdr;
> > +	evt_cmd_complete cmd_complete;
> > +	uint8_t status;
> > +	uint8_t data[16];
> > +} __attribute__((packed)) command_complete_t;
> > +
> > +
> 
> Why the two consecutive empty lines? Please remove one.

No reason. Will remove.

> 
> > +static int read_command_complete(int fd, unsigned short opcode, unsigned char len) {
> 
> This one looks like it goes beyond 80 columns. Please split it. Also,
> the coding style is to put the opening brace of a function on its own
> line.

See below for origin of style.

> > +	FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE, /* event must be event-complete */
> > +		   "Error in response: not a cmd-complete event, "
> > +		   "but 0x%02x!\n", resp.hci_hdr.evt);
> 
> Mixed tabs and spaces for indentation. Please just use tabs.
> 

See below for origin of style.

> > +	FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
> > +		   "Error in response: plen is not >= 4, but 0x%02x!\n",
> > +		   resp.hci_hdr.plen);
> 
> Same here.
> 

See below for origin of style.

> > +
> > +	/* cmd-complete event: opcode */
> > +	FAILIF(resp.cmd_complete.opcode != 0,
> > +		   "Error in response: opcode is 0x%04x, not 0!",
> > +		   resp.cmd_complete.opcode);
> 
> And here.
> 

See below for origin of style.

> > +static int qualcomm_load_firmware(int fd, const char *firmware, const char *bdaddr_s) {
> 
> This one goes beyond 80 columns too and the opening brace should be on
> its own line.
> 
> > +	FAILIF(fw < 0,
> > +		   "Could not open firmware file %s: %s (%d).\n",
> > +		   firmware, strerror(errno), errno);
> 

See below for origin of style.

> Mixed tabs and spaces for indentation.
> 
> > +		FAILIF(read(fw, data, cmd->plen) != cmd->plen,
> > +			   "Could not read %d bytes of data for command with opcode %04x!\n",
> > +			   cmd->plen,
> > +			   cmd->opcode);
> 
> Same here.
> 

See below for origin of style.

> > +			FAILIF(nw != (int) sizeof(cmdp) + cmd->plen,
> > +				   "Could not send entire command (sent only %d bytes)!\n",
> > +				   nw);
> 
> And here.
> 

See below for origin of style.

> > +		if (read_command_complete(fd,
> > +					  cmd->opcode,
> > +					  cmd->plen) < 0) {
> 
> And here. Why do you split it into three lines when it all fits within
> 80 columns?
> 

The style is from prior commit a8de99bdd963f0980877e066c7802c4247c1000c
but I will fix anyway (just in this file; not in hciattach_tialt.c)

> Johan
> --
> 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

Many thanks for the comprehensive review. v4 coming shortly.

-Matt


^ permalink raw reply

* Re: [PATCH v3] Firmware download for Qualcomm Bluetooth devices
From: Matt Wilson @ 2010-08-23 14:38 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth, marcel, rshaffer
In-Reply-To: <20100820223757.GA23924@jh-x301>

On Sat, 2010-08-21 at 01:37 +0300, Johan Hedberg wrote:

> 
> And here. Why do you split it into three lines when it all fits within
> 80 columns?
> 
> Johan

Correction: prior style is actually from commit
13c0e26a0213f67f5bb9bd6915fddee9a7ca3b4 not
a8de99bdd963f0980877e066c7802c4247c1000c.

-Matt

--
Matthew Wilson
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
--

^ permalink raw reply

* [PATCH v4] Firmware download for Qualcomm Bluetooth devices
From: Matthew Wilson @ 2010-08-23 16:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, johan.hedberg, rshaffer, Matthew Wilson
In-Reply-To: <20100820223757.GA23924@jh-x301>

Configures device address from hciattach parameter.
UART speed limited to 115200.
Requires separate device specific firmware.
---
 Makefile.tools             |    3 +-
 tools/hciattach.c          |   10 ++
 tools/hciattach.h          |    1 +
 tools/hciattach_qualcomm.c |  279 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 292 insertions(+), 1 deletions(-)
 create mode 100644 tools/hciattach_qualcomm.c

diff --git a/Makefile.tools b/Makefile.tools
index 8ee1972..1c46542 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -24,7 +24,8 @@ tools_hciattach_SOURCES = tools/hciattach.c tools/hciattach.h \
 						tools/hciattach_st.c \
 						tools/hciattach_ti.c \
 						tools/hciattach_tialt.c \
-						tools/hciattach_ath3k.c
+						tools/hciattach_ath3k.c \
+						tools/hciattach_qualcomm.c
 tools_hciattach_LDADD = lib/libbluetooth.la
 
 tools_hciconfig_SOURCES = tools/hciconfig.c tools/csr.h tools/csr.c \
diff --git a/tools/hciattach.c b/tools/hciattach.c
index 5662f57..fd53710 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -312,6 +312,11 @@ static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)
 	return ath3k_post(fd, u->pm);
 }
 
+static int qualcomm(int fd, struct uart_t *u, struct termios *ti)
+{
+	return qualcomm_init(fd, u->speed, ti, u->bdaddr);
+}
+
 static int read_check(int fd, void *buf, int count)
 {
 	int res;
@@ -1116,6 +1121,11 @@ struct uart_t uart[] = {
 
 	{ "ath3k",    0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
 			FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm  },
+
+	/* QUALCOMM BTS */
+	{ "qualcomm",   0x0000, 0x0000, HCI_UART_H4,   115200, 115200,
+			FLOW_CTL, DISABLE_PM, NULL, qualcomm, NULL },
+
 	{ NULL, 0 }
 };
 
diff --git a/tools/hciattach.h b/tools/hciattach.h
index c133321..2d26b77 100644
--- a/tools/hciattach.h
+++ b/tools/hciattach.h
@@ -52,3 +52,4 @@ int stlc2500_init(int fd, bdaddr_t *bdaddr);
 int bgb2xx_init(int dd, bdaddr_t *bdaddr);
 int ath3k_init(int fd, char *bdaddr, int speed);
 int ath3k_post(int fd, int pm);
+int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr);
diff --git a/tools/hciattach_qualcomm.c b/tools/hciattach_qualcomm.c
new file mode 100644
index 0000000..b0df4b2
--- /dev/null
+++ b/tools/hciattach_qualcomm.c
@@ -0,0 +1,279 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2005-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (c) 2010, Code Aurora Forum. 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 <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "hciattach.h"
+
+#define FAILIF(x, args...) do { \
+	if (x) { \
+		fprintf(stderr, ##args); \
+		return -1; \
+	} \
+} while (0)
+
+typedef struct {
+	uint8_t uart_prefix;
+	hci_event_hdr hci_hdr;
+	evt_cmd_complete cmd_complete;
+	uint8_t status;
+	uint8_t data[16];
+} __attribute__((packed)) command_complete_t;
+
+static int read_command_complete(int fd,
+					unsigned short opcode,
+					unsigned char len)
+{
+	command_complete_t resp;
+	unsigned char vsevent[512];
+	int n;
+
+	/* Read reply. */
+	n = read_hci_event(fd, vsevent, sizeof(vsevent));
+	FAILIF(n < 0, "Failed to read response");
+
+	FAILIF(vsevent[1] != 0xFF, "Failed to read response");
+
+	n = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
+	FAILIF(n < 0, "Failed to read response");
+
+	/* event must be event-complete */
+	FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE,
+		"Error in response: not a cmd-complete event, "
+		"but 0x%02x!\n", resp.hci_hdr.evt);
+
+	FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
+		"Error in response: plen is not >= 4, but 0x%02x!\n",
+		resp.hci_hdr.plen);
+
+	/* cmd-complete event: opcode */
+	FAILIF(resp.cmd_complete.opcode != 0,
+		"Error in response: opcode is 0x%04x, not 0!",
+		resp.cmd_complete.opcode);
+
+	return resp.status == 0 ? 0 : -1;
+}
+
+static int qualcomm_load_firmware(int fd,
+					const char *firmware,
+					const char *bdaddr_s)
+{
+
+	int fw = open(firmware, O_RDONLY);
+
+	fprintf(stdout, "Opening firmware file: %s\n", firmware);
+
+	FAILIF(fw < 0,
+		"Could not open firmware file %s: %s (%d).\n",
+		firmware, strerror(errno), errno);
+
+	fprintf(stdout, "Uploading firmware...\n");
+	do {
+		/* Read each command and wait for a response. */
+		unsigned char data[1024];
+		unsigned char cmdp[1 + sizeof(hci_command_hdr)];
+		hci_command_hdr *cmd = (hci_command_hdr *)(cmdp + 1);
+		int nr;
+		nr = read(fw, cmdp, sizeof(cmdp));
+		if (!nr)
+			break;
+		FAILIF(nr != sizeof(cmdp),
+			"Could not read H4 + HCI header!\n");
+		FAILIF(*cmdp != HCI_COMMAND_PKT,
+			"Command is not an H4 command packet!\n");
+
+		FAILIF(read(fw, data, cmd->plen) != cmd->plen,
+			"Could not read %d bytes of data \
+			for command with opcode %04x!\n",
+			cmd->plen,
+			cmd->opcode);
+
+		if ((data[0] == 1) && (data[1] == 2) && (data[2] == 6)) {
+			bdaddr_t bdaddr;
+			if (bdaddr_s != NULL) {
+				(void) str2ba(bdaddr_s, &bdaddr);
+				memcpy(&data[3], &bdaddr, sizeof(bdaddr_t));
+			}
+		}
+
+		{
+			int nw;
+			struct iovec iov_cmd[2];
+			iov_cmd[0].iov_base = cmdp;
+			iov_cmd[0].iov_len	= sizeof(cmdp);
+			iov_cmd[1].iov_base = data;
+			iov_cmd[1].iov_len	= cmd->plen;
+			nw = writev(fd, iov_cmd, 2);
+			FAILIF(nw != (int) sizeof(cmdp) + cmd->plen,
+				"Could not send entire command \
+				(sent only %d bytes)!\n",
+				nw);
+		}
+
+		/* Wait for response */
+		if (read_command_complete(fd, cmd->opcode, cmd->plen) < 0)
+		{
+			return -1;
+		}
+
+	} while (1);
+	fprintf(stdout, "Firmware upload successful.\n");
+
+	close(fw);
+	return 0;
+}
+
+int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr)
+{
+	struct timespec tm = {0, 50000};
+	char cmd[5];
+	unsigned char resp[100];		/* Response */
+	char fw[100];
+	int n;
+
+	memset(resp, '\0', 100);
+
+	/* Get Manufacturer and LMP version */
+	cmd[0] = HCI_COMMAND_PKT;
+	cmd[1] = 0x01;
+	cmd[2] = 0x10;
+	cmd[3] = 0x00;
+
+	do {
+		n = write(fd, cmd, 4);
+		if (n < 4) {
+			perror("Failed to write init command");
+			return -1;
+		}
+
+		/* Read reply. */
+		if (read_hci_event(fd, resp, 100) < 0) {
+			perror("Failed to read init response");
+			return -1;
+		}
+
+		/* Wait for command complete event for our Opcode */
+	} while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+	/* Verify manufacturer */
+	if ((resp[11] & 0xFF) != 0x1d)
+		fprintf(stderr,
+			"WARNING : module's manufacturer is not Qualcomm\n");
+
+	/* Print LMP version */
+	fprintf(stderr,
+		"Qualcomm module LMP version : 0x%02x\n", resp[10] & 0xFF);
+
+	/* Print LMP subversion */
+	{
+		unsigned short lmp_subv = resp[13] | (resp[14] << 8);
+
+		fprintf(stderr,
+			"Qualcomm module LMP sub-version : 0x%04x\n", lmp_subv);
+
+	}
+
+	/* Get SoC type */
+	cmd[0] = HCI_COMMAND_PKT;
+	cmd[1] = 0x00;
+	cmd[2] = 0xFC;
+	cmd[3] = 0x01;
+	cmd[4] = 0x06;
+
+	do {
+		n = write(fd, cmd, 5);
+		if (n < 5) {
+			perror("Failed to write vendor init command");
+			return -1;
+		}
+
+		/* Read reply. */
+		if ((n = read_hci_event(fd, resp, 100)) < 0) {
+			perror("Failed to read vendor init response");
+			return -1;
+		}
+
+	} while (resp[3] != 0 && resp[4] != 2);
+
+	snprintf(fw, sizeof(fw),
+		"/etc/firmware/%c%c%c%c%c%c_%c%c%c%c.bin",
+		resp[18], resp[19], resp[20], resp[21],
+		resp[22], resp[23],
+		resp[32], resp[33], resp[34], resp[35]);
+
+	/* Wait for command complete event for our Opcode */
+	if (read_hci_event(fd, resp, 100) < 0) {
+		perror("Failed to read init response");
+		return -1;
+	}
+
+	qualcomm_load_firmware(fd, fw, bdaddr);
+
+	/* Reset */
+	cmd[0] = HCI_COMMAND_PKT;
+	cmd[1] = 0x03;
+	cmd[2] = 0x0C;
+	cmd[3] = 0x00;
+
+	do {
+		n = write(fd, cmd, 4);
+		if (n < 4) {
+			perror("Failed to write reset command");
+			return -1;
+		}
+
+		/* Read reply. */
+		if ((n = read_hci_event(fd, resp, 100)) < 0) {
+			perror("Failed to read reset response");
+			return -1;
+		}
+
+	} while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+	nanosleep(&tm, NULL);
+	return 0;
+}
-- 
1.7.1.1

--
Matthew Wilson
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 1/2] Bluetooth: Implement LE Set Advertise Enable cmd
From: Anderson Briglia @ 2010-08-23 19:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia

This patch implements LE Set Advertise Enable command for dual mode and
Low Energy hci controllers. It also adds new HCI flags in order to
indicate the Advertising state for userland applications and kernel
itself.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/hci.h |    6 ++++++
 net/bluetooth/hci_event.c   |   27 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index bcbdd6d..cae1816 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -76,6 +76,7 @@ enum {
 	HCI_INQUIRY,
 
 	HCI_RAW,
+	HCI_LE_ADV,
 };
 
 /* HCI ioctl defines */
@@ -593,6 +594,11 @@ struct hci_rp_read_bd_addr {
 	bdaddr_t bdaddr;
 } __packed;
 
+/* --- HCI LE Commands --- */
+#define HCI_OP_LE_SET_ADVERTISE_ENABLE	0x200a
+	#define ADVERTISE_ENABLED	0x01
+	#define ADVERTISE_DISABLED	0x00
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index bfef5ba..c86c655 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -822,6 +822,29 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cc_le_set_advertise(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+	void *sent;
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADVERTISE_ENABLE);
+	if (!sent)
+		return;
+
+	if (!status) {
+		__u8 param = *((__u8 *) sent);
+
+		clear_bit(HCI_LE_ADV, &hdev->flags);
+
+		if (param & ADVERTISE_ENABLED)
+			set_bit(HCI_LE_ADV, &hdev->flags);
+	}
+
+	hci_req_complete(hdev, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1310,6 +1333,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_read_bd_addr(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_ADVERTISE_ENABLE:
+		hci_cc_le_set_advertise(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/2] Bluetooth: Implement LE Set Scan Enable cmd
From: Anderson Briglia @ 2010-08-23 19:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Briglia
In-Reply-To: <1282591815-26934-1-git-send-email-anderson.briglia@openbossa.org>

This patch implements LE Set Scan Enable command for dual
mode and Low Energy hci controllers. It also adds new HCI flags
in order to indicate the LE Scanning state for userland applications
and kernel itself.

Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
---
 include/net/bluetooth/hci.h |    5 +++++
 net/bluetooth/hci_event.c   |   25 +++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index cae1816..268aa94 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -77,6 +77,7 @@ enum {
 
 	HCI_RAW,
 	HCI_LE_ADV,
+	HCI_LE_SCAN,
 };
 
 /* HCI ioctl defines */
@@ -599,6 +600,10 @@ struct hci_rp_read_bd_addr {
 	#define ADVERTISE_ENABLED	0x01
 	#define ADVERTISE_DISABLED	0x00
 
+#define HCI_OP_LE_SET_SCAN_ENABLE	0x200c
+	#define LESCAN_ENABLED		0x01
+	#define LESCAN_DISABLED		0x00
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c86c655..f483801 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -845,6 +845,27 @@ static void hci_cc_le_set_advertise(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_req_complete(hdev, status);
 }
 
+static void hci_cc_le_set_scan(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status = *((__u8 *) skb->data);
+	void *sent;
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
+	if (!sent)
+		return;
+
+	clear_bit(HCI_LE_SCAN, &hdev->flags);
+	if (!status) {
+		__u8 param = *((__u8 *) sent);
+		if (param & LESCAN_ENABLED)
+			set_bit(HCI_LE_SCAN, &hdev->flags);
+	}
+
+	hci_req_complete(hdev, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1337,6 +1358,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_le_set_advertise(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_SCAN_ENABLE:
+		hci_cc_le_set_scan(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH v4] Firmware download for Qualcomm Bluetooth devices
From: Johan Hedberg @ 2010-08-23 20:41 UTC (permalink / raw)
  To: Matthew Wilson; +Cc: linux-bluetooth, marcel, rshaffer
In-Reply-To: <1282580267-2146-1-git-send-email-mtwilson@codeaurora.org>

Hi Matt,

On Mon, Aug 23, 2010, Matthew Wilson wrote:
> Configures device address from hciattach parameter.
> UART speed limited to 115200.
> Requires separate device specific firmware.
> ---
>  Makefile.tools             |    3 +-
>  tools/hciattach.c          |   10 ++
>  tools/hciattach.h          |    1 +
>  tools/hciattach_qualcomm.c |  279 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 292 insertions(+), 1 deletions(-)
>  create mode 100644 tools/hciattach_qualcomm.c

Thanks. The patch is now pushed upstream with a few more cosmetic
(coding style) changes. Take a look at the upstream tree if you're
interested in the details.

Johan

^ permalink raw reply

* Re: [PATCH] Fix issues with emails category
From: Johan Hedberg @ 2010-08-23 20:50 UTC (permalink / raw)
  To: Lukasz Pawlik; +Cc: linux-bluetooth
In-Reply-To: <AANLkTi=KpD_dtVVe7tSBT-+Kv11QsXf-WbtanAe3ur9-@mail.gmail.com>

Hi Lukasz,

On Mon, Aug 23, 2010, Lukasz Pawlik wrote:
> From: Lukasz Pawlik <lucas.pawlik@gmail.com>
> Date: Mon, 23 Aug 2010 15:25:20 +0200
> Subject: [PATCH] Fix issues with emails category
> 
> Previously all emails sent during phonebook pull had the same
> category INTERNET. Now email are sent with valid category name
> (INTERNET;HOME or INTERNET;WORK)
> ---
>  plugins/phonebook-tracker.c |   31 +++++++++++++++++--------
>  plugins/vcard.c             |   53 ++++++++++++++++++++++++++++++++++---------
>  plugins/vcard.h             |   11 +++++++++
>  3 files changed, 74 insertions(+), 21 deletions(-)

Thanks. The patch is now pushed upstream, but I had to make a few coding
style fixes before that:

> +static struct phonebook_email *find_email(GSList *emails, const char *address,
> +										int type)

Over 80 column line.

> +	for (l = emails; l; l = l->next) {
> +		struct phonebook_email *email;
> +		email = l->data;

You don't really need the variable definition and assignment on
different lines here.

> +static void add_email(struct phonebook_contact *contact, const char *address,
> +						int type)

The continuation line should be indented as much as possible as long as
you don't go beyond 80 columns. (not sure if this is a kernel coding
style thingie but at least Marcel wants it that way).

> +static void vcard_printf_email(GString *vcards, uint8_t format,
> +								const char *address,
> +								enum phonebook_email_type category)

Way over 80 column lines. Are you using some other tab-width than 8?

Johan

^ permalink raw reply

* Re: [PATCHv2 2/2] Bluetooth: timer check sk is not owned before freeing
From: Gustavo F. Padovan @ 2010-08-23 22:45 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth
In-Reply-To: <1281619537-30096-3-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2010-08-12 16:25:37 +0300]:

> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> 
> In timer context we might delete l2cap channel used by krfcommd.
> The check makes sure that sk is not owned.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> ---
>  net/bluetooth/l2cap.c |   32 ++++++++++++++++++++------------
>  1 files changed, 20 insertions(+), 12 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 0221d05..2f8ac5d 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -73,6 +73,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
>  				u8 code, u8 ident, u16 dlen, void *data);
>  
>  /* ---- L2CAP timers ---- */
> +static void l2cap_sock_set_timer(struct sock *sk, long timeout)
> +{
> +	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
> +	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
> +}
> +
> +static void l2cap_sock_clear_timer(struct sock *sk)
> +{
> +	BT_DBG("sock %p state %d", sk, sk->sk_state);
> +	sk_stop_timer(sk, &sk->sk_timer);
> +}
> +
>  static void l2cap_sock_timeout(unsigned long arg)
>  {
>  	struct sock *sk = (struct sock *) arg;
> @@ -82,6 +94,14 @@ static void l2cap_sock_timeout(unsigned long arg)
>  
>  	bh_lock_sock(sk);
>  
> +	if (sock_owned_by_user(sk)) {
> +		/* sk is owned by user. Try again later */
> +		l2cap_sock_set_timer(sk, HZ * 2);
> +		bh_unlock_sock(sk);
> +		sock_put(sk);
> +		return;
> +	}

I'm not sure if I like this defer through timers. OTOH could be too much
overhead to do this defer through a work queue.
Also I think that 2 seconds is too much for this timer. 200 miliseconds
should be enough, what do you think?

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

^ permalink raw reply

* ping slowness over bluetooth PAN
From: Han @ 2010-08-24  6:06 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

I noticed that ping is much more slow over bluetooth PAN connection
than a typical WiFI LAN:

especially the first packet:  (Ubuntu 9.10)

PAN:

64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=365 ms

WLAN:

64 bytes from Amelie (192.168.1.71): icmp_seq=1 ttl=128 time=3.53 ms

The WLAN case is 100 times faster on the first ping!  Is this
expected?  (I don't think this is due to the absolute bandwidth).  Any
insight is appreciated.

Han

^ permalink raw reply

* Re: [PATCH 0/3] Parsing of AMP related HCI commands and events
From: Johan Hedberg @ 2010-08-24  8:44 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, rshaffer, marcel
In-Reply-To: <1282174734-1314-1-git-send-email-ingas@codeaurora.org>

Hi Inga,

On Wed, Aug 18, 2010, Inga Stotland wrote:
> Added support for interpreting of the following HCI commands:
> 
> Create Physical Link,
> Accept Physical Link,
> Disconnect Physical Link,
> Create Logical Link,
> Accept Logical Link,
> Disconnect Logical Link,
> Logical Link Cancel,
> Flow Spec Modify,
> Read Encryption Key Size,
> Read Local AMP Info,
> Read Local AMP ASSOC,
> Write Remote AMP ASSOC
> 
> and HCI events:
> 
> Physical Link Complete,
> Disconnect Physical Link Complete,
> Physical Link Loss Early Warning,
> Physical Link Recovery,
> Logical Link Complete,
> Disconnect Logical Link Complete,
> Flow Spec Modify Complete

Thanks. All three patches have been pushed upstream.

Johan

^ permalink raw reply

* [PATCH 0/4] Fix error reporting for SDP Requests
From: Angela Bartholomaus @ 2010-08-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: rshaffer, marcel, johan.hedberg

Fixed the following issues revealed while performing bluez qualification: 
- Incorrect error code was being reported for requests with invalid PDU size;
- No error was being reported if a request less than 0x07 was received.


Angela Bartholomaus
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* [PATCH 1/4] Send an Invalid PDU Size Error Response for Service Search Req
From: Angela Bartholomaus @ 2010-08-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: rshaffer, marcel, johan.hedberg, Angela Bartholomaus
In-Reply-To: <1282688060-10727-1-git-send-email-angelab@codeaurora.org>

Send error code for an SDP request received with an invalid PDU Size
---
 src/sdpd-request.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/sdpd-request.c b/src/sdpd-request.c
index d56ffc2..cc9fe82 100644
--- a/src/sdpd-request.c
+++ b/src/sdpd-request.c
@@ -367,7 +367,7 @@ static int service_search_req(sdp_req_t *req, sdp_buf_t *buf)
 	mlen = scanned + sizeof(uint16_t) + 1;
 	// ensure we don't read past buffer
 	if (plen < mlen || plen != mlen + *(uint8_t *)(pdata+sizeof(uint16_t))) {
-		status = SDP_INVALID_SYNTAX;
+		status = SDP_INVALID_PDU_SIZE;
 		goto done;
 	}
 
-- 
1.7.0.2
--
Angela Bartholomaus
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* [PATCH 2/4] Send an Invalid PDU Size Error Response for Service Attr Req
From: Angela Bartholomaus @ 2010-08-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: rshaffer, marcel, johan.hedberg, Angela Bartholomaus
In-Reply-To: <1282688060-10727-1-git-send-email-angelab@codeaurora.org>

Send error code for an SDP request received with an invalid PDU size
---
 src/sdpd-request.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/sdpd-request.c b/src/sdpd-request.c
index cc9fe82..ccbd920 100644
--- a/src/sdpd-request.c
+++ b/src/sdpd-request.c
@@ -667,7 +667,7 @@ static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf)
 	mlen = scanned + sizeof(uint32_t) + sizeof(uint16_t) + 1;
 	// ensure we don't read past buffer
 	if (plen < mlen || plen != mlen + *(uint8_t *)pdata) {
-		status = SDP_INVALID_SYNTAX;
+		status = SDP_INVALID_PDU_SIZE;
 		goto done;
 	}
 
-- 
1.7.0.2
--
Angela Bartholomaus
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* [PATCH 3/4] Send an Invalid PDU Size Error Resp for Service Attr Search Req
From: Angela Bartholomaus @ 2010-08-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: rshaffer, marcel, johan.hedberg, Angela Bartholomaus
In-Reply-To: <1282688060-10727-1-git-send-email-angelab@codeaurora.org>

Send error code for an SDP request received with an invalid PDU size
---
 src/sdpd-request.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/sdpd-request.c b/src/sdpd-request.c
index ccbd920..8547939 100644
--- a/src/sdpd-request.c
+++ b/src/sdpd-request.c
@@ -818,7 +818,7 @@ static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf)
 
 	plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
 	if (plen < totscanned || plen != totscanned + *(uint8_t *)pdata) {
-		status = SDP_INVALID_SYNTAX;
+		status = SDP_INVALID_PDU_SIZE;
 		goto done;
 	}
 
-- 
1.7.0.2
--
Angela Bartholomaus
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* [PATCH 4/4] Send Invalid Syntax Error if Resp Size Less Than 0x07
From: Angela Bartholomaus @ 2010-08-24 22:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: rshaffer, marcel, johan.hedberg, Angela Bartholomaus
In-Reply-To: <1282688060-10727-1-git-send-email-angelab@codeaurora.org>

Added in error catching, when a badly formed request comes in
---
 src/sdpd-request.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/src/sdpd-request.c b/src/sdpd-request.c
index 8547939..205b27b 100644
--- a/src/sdpd-request.c
+++ b/src/sdpd-request.c
@@ -684,6 +684,15 @@ static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf)
 	SDPDBG("max_rsp_size : %d", max_rsp_size);
 
 	/*
+	 * Check that max_rsp_size is within valid range
+	 * a minimum size of 0x0007 has to be used for data field
+	 */
+	if (max_rsp_size < 0x0007) {
+		status = SDP_INVALID_SYNTAX;
+		goto done;
+	}
+
+	/*
 	 * Calculate Attribute size acording to MTU
 	 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
 	 */
-- 
1.7.0.2
--
Angela Bartholomaus
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply related

* Re: [PATCH 0/4] Fix error reporting for SDP Requests
From: Marcel Holtmann @ 2010-08-24 22:21 UTC (permalink / raw)
  To: Angela Bartholomaus; +Cc: linux-bluetooth, rshaffer, johan.hedberg
In-Reply-To: <1282688060-10727-1-git-send-email-angelab@codeaurora.org>

Hi Angela,

> Fixed the following issues revealed while performing bluez qualification: 
> - Incorrect error code was being reported for requests with invalid PDU size;
> - No error was being reported if a request less than 0x07 was received.

I never needed any of these fixes when doing qualification. So why do
you? Please mention the test case numbers.

Regards

Marcel



^ permalink raw reply

* [PATCH v5 0/5] L2CAP updates for FCS, valid PSMs, and stream recv
From: Mat Martineau @ 2010-08-24 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm

These patches incorporate requested fixes from the 'v4' submission.


[PATCH 1/5] Bluetooth: Only enable for L2CAP FCS for ERTM or streaming

This got an "applied" response on the mailing list, but it looks like
the commit got dropped during a rebase.


[PATCH 2/5] Bluetooth: Validate PSM values in calls to connect() and bind()

Fixed comments.


[PATCH 3/5] Bluetooth: Add common code for stream-oriented recvmsg()
[PATCH 4/5] Bluetooth: Use common SOCK_STREAM receive code in RFCOMM
[PATCH 5/5] Bluetooth: Use a stream-oriented recvmsg with SOCK_STREAM L2CAP sockets.

No changes were requested in these patches.


--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply

* [PATCH 1/5] Bluetooth: Only enable for L2CAP FCS for ERTM or streaming
From: Mat Martineau @ 2010-08-24 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1282689346-20371-1-git-send-email-mathewm@codeaurora.org>

This fixes a bug which caused the FCS setting to show L2CAP_FCS_CRC16
with L2CAP modes other than ERTM or streaming.  At present, this only
affects the FCS value shown with getsockopt() for basic mode.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index fadf26b..c784703 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3071,6 +3071,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	return 0;
 }
 
+static inline void set_default_fcs(struct l2cap_pinfo *pi)
+{
+	/* FCS is enabled only in ERTM or streaming mode, if one or both
+	 * sides request it.
+	 */
+	if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
+		pi->fcs = L2CAP_FCS_NONE;
+	else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
+		pi->fcs = L2CAP_FCS_CRC16;
+}
+
 static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
 {
 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
@@ -3135,9 +3146,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		goto unlock;
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
-		if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-		    l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
-			l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
+		set_default_fcs(l2cap_pi(sk));
 
 		sk->sk_state = BT_CONNECTED;
 
@@ -3225,9 +3234,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
-		if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-		    l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
-			l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
+		set_default_fcs(l2cap_pi(sk));
 
 		sk->sk_state = BT_CONNECTED;
 		l2cap_pi(sk)->next_tx_seq = 0;
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 2/5] Bluetooth: Validate PSM values in calls to connect() and bind()
From: Mat Martineau @ 2010-08-24 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1282689346-20371-1-git-send-email-mathewm@codeaurora.org>

Valid L2CAP PSMs are odd numbers, and the least significant bit of the
most significant byte must be 0.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |   24 ++++++++++++++++++++----
 1 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index c784703..1f1fa3c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1008,10 +1008,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 		goto done;
 	}
 
-	if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
-				!capable(CAP_NET_BIND_SERVICE)) {
-		err = -EACCES;
-		goto done;
+	if (la.l2_psm) {
+		__u16 psm = __le16_to_cpu(la.l2_psm);
+
+		/* PSM must be odd and lsb of upper byte must be 0 */
+		if ((psm & 0x0101) != 0x0001) {
+			err = -EINVAL;
+			goto done;
+		}
+
+		/* Restrict usage of well-known PSMs */
+		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
+			err = -EACCES;
+			goto done;
+		}
 	}
 
 	write_lock_bh(&l2cap_sk_list.lock);
@@ -1190,6 +1200,12 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 		goto done;
 	}
 
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	/* Set destination address and psm */
 	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
 	l2cap_pi(sk)->psm = la.l2_psm;
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 3/5] Bluetooth: Add common code for stream-oriented recvmsg()
From: Mat Martineau @ 2010-08-24 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1282689346-20371-1-git-send-email-mathewm@codeaurora.org>

This commit adds a bt_sock_stream_recvmsg() function for use by any
Bluetooth code that uses SOCK_STREAM sockets.  This code is copied
from rfcomm_sock_recvmsg() with minimal modifications to remove
RFCOMM-specific functionality and improve readability.

L2CAP (with the SOCK_STREAM socket type) and RFCOMM have common needs
when it comes to reading data.  Proper stream read semantics require
that applications can read from a stream one byte at a time and not
lose any data.  The RFCOMM code already operated on and pulled data
from the underlying L2CAP socket, so very few changes were required to
make the code more generic for use with non-RFCOMM data over L2CAP.

Applications that need more awareness of L2CAP frame boundaries are
still free to use SOCK_SEQPACKET sockets, and may verify that they
connection did not fall back to basic mode by calling getsockopt().

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 include/net/bluetooth/bluetooth.h |    2 +
 net/bluetooth/af_bluetooth.c      |  109 +++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 27a902d..08b6c2a 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -126,6 +126,8 @@ int  bt_sock_unregister(int proto);
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
 int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int  bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+			struct msghdr *msg, size_t len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
 int  bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int  bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 421c45b..77a26fe 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -265,6 +265,115 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 }
 EXPORT_SYMBOL(bt_sock_recvmsg);
 
+static long bt_sock_data_wait(struct sock *sk, long timeo)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(sk_sleep(sk), &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (!skb_queue_empty(&sk->sk_receive_queue))
+			break;
+
+		if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
+			break;
+
+		if (signal_pending(current) || !timeo)
+			break;
+
+		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+	}
+
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+	return timeo;
+}
+
+int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+			       struct msghdr *msg, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+	size_t target, copied = 0;
+	long timeo;
+
+	if (flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	msg->msg_namelen = 0;
+
+	BT_DBG("sk %p size %zu", sk, size);
+
+	lock_sock(sk);
+
+	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
+	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
+	do {
+		struct sk_buff *skb;
+		int chunk;
+
+		skb = skb_dequeue(&sk->sk_receive_queue);
+		if (!skb) {
+			if (copied >= target)
+				break;
+
+			if ((err = sock_error(sk)) != 0)
+				break;
+			if (sk->sk_shutdown & RCV_SHUTDOWN)
+				break;
+
+			err = -EAGAIN;
+			if (!timeo)
+				break;
+
+			timeo = bt_sock_data_wait(sk, timeo);
+
+			if (signal_pending(current)) {
+				err = sock_intr_errno(timeo);
+				goto out;
+			}
+			continue;
+		}
+
+		chunk = min_t(unsigned int, skb->len, size);
+		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			if (!copied)
+				copied = -EFAULT;
+			break;
+		}
+		copied += chunk;
+		size   -= chunk;
+
+		sock_recv_ts_and_drops(msg, sk, skb);
+
+		if (!(flags & MSG_PEEK)) {
+			skb_pull(skb, chunk);
+			if (skb->len) {
+				skb_queue_head(&sk->sk_receive_queue, skb);
+				break;
+			}
+			kfree_skb(skb);
+
+		} else {
+			/* put message back and return */
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			break;
+		}
+	} while (size);
+
+out:
+	release_sock(sk);
+	return copied ? : err;
+}
+EXPORT_SYMBOL(bt_sock_stream_recvmsg);
+
 static inline unsigned int bt_accept_poll(struct sock *parent)
 {
 	struct list_head *p, *n;
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 4/5] Bluetooth: Use common SOCK_STREAM receive code in RFCOMM
From: Mat Martineau @ 2010-08-24 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1282689346-20371-1-git-send-email-mathewm@codeaurora.org>

To reduce code duplication, have rfcomm_sock_recvmsg() call
bt_sock_stream_recvmsg().  The common bt_sock_stream_recvmsg()
code is nearly identical, with the RFCOMM-specific functionality
for deferred setup and connection unthrottling left in
rfcomm_sock_recvmsg().

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/rfcomm/sock.c |  104 +++----------------------------------------
 1 files changed, 6 insertions(+), 98 deletions(-)

diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 44a6232..4396f47 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -617,121 +617,29 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 	return sent;
 }
 
-static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (!skb_queue_empty(&sk->sk_receive_queue) ||
-		    sk->sk_err ||
-		    (sk->sk_shutdown & RCV_SHUTDOWN) ||
-		    signal_pending(current) ||
-		    !timeo)
-			break;
-
-		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-	return timeo;
-}
-
 static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 			       struct msghdr *msg, size_t size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
-	int err = 0;
-	size_t target, copied = 0;
-	long timeo;
+	int len;
 
 	if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 		rfcomm_dlc_accept(d);
 		return 0;
 	}
 
-	if (flags & MSG_OOB)
-		return -EOPNOTSUPP;
-
-	msg->msg_namelen = 0;
-
-	BT_DBG("sk %p size %zu", sk, size);
+	len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags);
 
 	lock_sock(sk);
+	if (!(flags & MSG_PEEK) && len > 0)
+		atomic_sub(len, &sk->sk_rmem_alloc);
 
-	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
-	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
-
-	do {
-		struct sk_buff *skb;
-		int chunk;
-
-		skb = skb_dequeue(&sk->sk_receive_queue);
-		if (!skb) {
-			if (copied >= target)
-				break;
-
-			if ((err = sock_error(sk)) != 0)
-				break;
-			if (sk->sk_shutdown & RCV_SHUTDOWN)
-				break;
-
-			err = -EAGAIN;
-			if (!timeo)
-				break;
-
-			timeo = rfcomm_sock_data_wait(sk, timeo);
-
-			if (signal_pending(current)) {
-				err = sock_intr_errno(timeo);
-				goto out;
-			}
-			continue;
-		}
-
-		chunk = min_t(unsigned int, skb->len, size);
-		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
-			skb_queue_head(&sk->sk_receive_queue, skb);
-			if (!copied)
-				copied = -EFAULT;
-			break;
-		}
-		copied += chunk;
-		size   -= chunk;
-
-		sock_recv_ts_and_drops(msg, sk, skb);
-
-		if (!(flags & MSG_PEEK)) {
-			atomic_sub(chunk, &sk->sk_rmem_alloc);
-
-			skb_pull(skb, chunk);
-			if (skb->len) {
-				skb_queue_head(&sk->sk_receive_queue, skb);
-				break;
-			}
-			kfree_skb(skb);
-
-		} else {
-			/* put message back and return */
-			skb_queue_head(&sk->sk_receive_queue, skb);
-			break;
-		}
-	} while (size);
-
-out:
 	if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2))
 		rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc);
-
 	release_sock(sk);
-	return copied ? : err;
+
+	return len;
 }
 
 static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* [PATCH 5/5] Bluetooth: Use a stream-oriented recvmsg with SOCK_STREAM L2CAP sockets.
From: Mat Martineau @ 2010-08-24 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, rshaffer, linux-arm-msm, Mat Martineau
In-Reply-To: <1282689346-20371-1-git-send-email-mathewm@codeaurora.org>

L2CAP ERTM sockets can be opened with the SOCK_STREAM socket type,
which is a mandatory request for ERTM mode.

However, these sockets still have SOCK_SEQPACKET read semantics when
bt_sock_recvmsg() is used to pull data from the receive queue.  If the
application is only reading part of a frame, then the unread portion
of the frame is discarded.  If the application requests more bytes
than are in the current frame, only the current frame's data is
returned.

This patch utilizes common code derived from RFCOMM's recvmsg()
function to make L2CAP SOCK_STREAM reads behave like RFCOMM reads (and
other SOCK_STREAM sockets in general).  The application may read one
byte at a time from the input stream and not lose any data, and may
also read across L2CAP frame boundaries.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
---
 net/bluetooth/l2cap.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 1f1fa3c..05db244 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1960,6 +1960,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
 	release_sock(sk);
 
+	if (sock->type == SOCK_STREAM)
+		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+
 	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
 }
 
-- 
1.7.1

--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

^ permalink raw reply related

* Re: [PATCH 0/4] Fix error reporting for SDP Requests
From: angelab @ 2010-08-24 22:55 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1282688488.6841.34.camel@localhost.localdomain>

Hi Marcel,

Section 4.4 of the Bluetooth Corev2.1 spec, states that the error code
shall be 0x04 when an invalid PDU size is received. BlueZ is returning
error code 0x03 for the following:
TP/SERVER/SS/BI-01-C  [PATCH 1/4]
TP/SERVER/SA/BI-03-C  [PATCH 2/4]
TP/SERVER/SSA/BI-02-C [PATCH 3/4]

For this test case I sent a bad search attribute request where the max
amount Of Attribute Data to return is 0, but blueZ fails to respond with
an error code. The "max amount of attribute data" field has to be set to a
minimum size of 0x0007 for the request to be valid.
TP/SERVER/SA/BI-02-C [PATCH 4/4]

Sincerely,
Angela Bartholomaus
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.




> Hi Angela,
>
>> Fixed the following issues revealed while performing bluez
>> qualification:
>> - Incorrect error code was being reported for requests with invalid PDU
>> size;
>> - No error was being reported if a request less than 0x07 was received.
>
> I never needed any of these fixes when doing qualification. So why do
> you? Please mention the test case numbers.
>
> Regards
>
> Marcel
>
>
>

^ permalink raw reply

* Re: [PATCH 0/4] Fix error reporting for SDP Requests
From: Johan Hedberg @ 2010-08-24 23:15 UTC (permalink / raw)
  To: angelab; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <f5a72626c821919cb059a7efc6e7fb9f.squirrel@www.codeaurora.org>

Hi Angela,

On Tue, Aug 24, 2010, angelab@codeaurora.org wrote:
> Section 4.4 of the Bluetooth Corev2.1 spec, states that the error code
> shall be 0x04 when an invalid PDU size is received. BlueZ is returning
> error code 0x03 for the following:
> TP/SERVER/SS/BI-01-C  [PATCH 1/4]
> TP/SERVER/SA/BI-03-C  [PATCH 2/4]
> TP/SERVER/SSA/BI-02-C [PATCH 3/4]
> 
> For this test case I sent a bad search attribute request where the max
> amount Of Attribute Data to return is 0, but blueZ fails to respond with
> an error code. The "max amount of attribute data" field has to be set to a
> minimum size of 0x0007 for the request to be valid.
> TP/SERVER/SA/BI-02-C [PATCH 4/4]

Ok, so it sounds like you're using your own test system for this? I
don't think Marcel was referring to what the spec says but what the BITE
tester test vectors require in practice. So far there haven't been any
issues with the BITE with respect to this. Of course it's good to not
just pass with the BITE but to also be consistent with the spec, and so
these patches seem like a good idea. However, could you resend them with
the test case reference in each commit message as well as any other
relevant info like the section in the core spec? Thanks.

Johan

^ 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