Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 1/3] Fix not deinitializing telephony driver when there is no adapter powered
From: Luiz Augusto von Dentz @ 2010-11-23 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

This changes hook telephony driver de/initialization to powered state so
telephony drivers can now free their resources when there is no adapter
active in the system.
---
 audio/manager.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/audio/manager.c b/audio/manager.c
index 816c807..8a5616d 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -96,6 +96,7 @@ typedef enum {
 
 struct audio_adapter {
 	struct btd_adapter *btd_adapter;
+	gboolean powered;
 	uint32_t hsp_ag_record_id;
 	uint32_t hfp_ag_record_id;
 	uint32_t hfp_hs_record_id;
@@ -858,6 +859,49 @@ static struct audio_adapter *audio_adapter_get(struct btd_adapter *adapter)
 	return adp;
 }
 
+static void state_changed(struct btd_adapter *adapter, gboolean powered)
+{
+	struct audio_adapter *adp;
+	static gboolean telephony = FALSE;
+	GSList *l;
+
+	DBG("%s powered %s", adapter_get_path(adapter),
+						powered ? "on" : "off");
+
+	/* ignore powered change, adapter is powering down */
+	if (powered && adapter_powering_down(adapter))
+		return;
+
+	adp = find_adapter(adapters, adapter);
+	if (!adp)
+		return;
+
+	adp->powered = powered;
+
+	if (powered) {
+		/* telephony driver already initialized*/
+		if (telephony == TRUE)
+			return;
+		telephony_init();
+		telephony = TRUE;
+		return;
+	}
+
+	/* telephony not initialized just ignore power down */
+	if (telephony == FALSE)
+		return;
+
+	for (l = adapters; l; l = l->next) {
+		adp = l->data;
+
+		if (adp->powered == TRUE)
+			return;
+	}
+
+	telephony_exit();
+	telephony = FALSE;
+}
+
 static int headset_server_probe(struct btd_adapter *adapter)
 {
 	struct audio_adapter *adp;
@@ -871,10 +915,15 @@ static int headset_server_probe(struct btd_adapter *adapter)
 		return -EINVAL;
 
 	err = headset_server_init(adp);
-	if (err < 0)
+	if (err < 0) {
 		audio_adapter_unref(adp);
+		return err;
+	}
 
-	return err;
+	btd_adapter_register_powered_callback(adapter, state_changed);
+	state_changed(adapter, TRUE);
+
+	return 0;
 }
 
 static void headset_server_remove(struct btd_adapter *adapter)
@@ -910,6 +959,8 @@ static void headset_server_remove(struct btd_adapter *adapter)
 		adp->hfp_ag_server = NULL;
 	}
 
+	btd_adapter_unregister_powered_callback(adapter, state_changed);
+
 	audio_adapter_unref(adp);
 }
 
@@ -1177,10 +1228,8 @@ proceed:
 	if (enabled.media)
 		btd_register_adapter_driver(&media_server_driver);
 
-	if (enabled.headset) {
-		telephony_init();
+	if (enabled.headset)
 		btd_register_adapter_driver(&headset_server_driver);
-	}
 
 	if (enabled.gateway)
 		btd_register_adapter_driver(&gateway_server_driver);
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH v2] hciattach: download configuration at user requested baud rate
From: Johan Hedberg @ 2010-11-23 11:11 UTC (permalink / raw)
  To: Suraj Sumangala; +Cc: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <1290509963-11918-1-git-send-email-suraj@atheros.com>

Hi Suraj,

On Tue, Nov 23, 2010, Suraj Sumangala wrote:
> This patch support downloading configuration for
> Atheros AR300x HCI UART chip at user requested baud rate
> instead of the initial baud rate.
> ---
>  tools/hciattach.c       |    2 +-
>  tools/hciattach.h       |    3 +-
>  tools/hciattach_ath3k.c |   98 +++++++++++++++++++++++++++++++++-------------
>  3 files changed, 73 insertions(+), 30 deletions(-)

Thanks for the update. Now this patch is also pushed upstream.

Johan

^ permalink raw reply

* Re: [PATCH] hciattach: makes set_speed return error if any one operation fail
From: Johan Hedberg @ 2010-11-23 11:10 UTC (permalink / raw)
  To: Suraj Sumangala; +Cc: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <1290508783-31183-1-git-send-email-suraj@atheros.com>

Hi Suraj,

On Tue, Nov 23, 2010, Suraj Sumangala wrote:
> This patch lets set_speed function changing UART baud rate
> to return an error code if any one operation fails
> instead of returning only the last operation's status.
> 
> ---
>  tools/hciattach.c |   13 ++++++++++---
>  1 files changed, 10 insertions(+), 3 deletions(-)

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: [PATCHv4 6/7] Update D-Bus OOB API with RequestPairing method
From: Szymon Janc @ 2010-11-23 11:05 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org
In-Reply-To: <1290509592-9262-7-git-send-email-szymon.janc@tieto.com>

Fixed version (.orig removed)

---
 doc/oob-api.txt |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/doc/oob-api.txt b/doc/oob-api.txt
index 4796e4c..e08f6f8 100644
--- a/doc/oob-api.txt
+++ b/doc/oob-api.txt
@@ -60,3 +60,17 @@ Methods		void RegisterProvider(object provider)
 			Possible errors: org.bluez.Error.ReadFailed
 					 org.bluez.Error.NoProvider
 					 org.bluez.Error.InProgress
+
+--------------------------------------------------------------------------------
+
+Service		unique name
+Interface	org.bluez.Agent
+Object path	freely definable
+
+Methods		void RequestPairing(object device)
+
+			This method gets called when the service daemon
+			needs to confirm incoming pairing request.
+
+			Possible errors: org.bluez.Error.Rejected
+					 org.bluez.Error.Canceled
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2] hciattach: download configuration at user requested baud rate
From: Suraj Sumangala @ 2010-11-23 10:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jothikumar.Mothilal, Suraj Sumangala

This patch support downloading configuration for
Atheros AR300x HCI UART chip at user requested baud rate
instead of the initial baud rate.
---
 tools/hciattach.c       |    2 +-
 tools/hciattach.h       |    3 +-
 tools/hciattach_ath3k.c |   98 +++++++++++++++++++++++++++++++++-------------
 3 files changed, 73 insertions(+), 30 deletions(-)

diff --git a/tools/hciattach.c b/tools/hciattach.c
index 7cb8e9e..e4d5aa1 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -311,7 +311,7 @@ static int texasalt(int fd, struct uart_t *u, struct termios *ti)
 
 static int ath3k_ps(int fd, struct uart_t *u, struct termios *ti)
 {
-	return ath3k_init(fd, u->bdaddr, u->speed);
+	return ath3k_init(fd, u->speed, u->init_speed, u->bdaddr, ti);
 }
 
 static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)
diff --git a/tools/hciattach.h b/tools/hciattach.h
index 2d26b77..fed0d11 100644
--- a/tools/hciattach.h
+++ b/tools/hciattach.h
@@ -50,6 +50,7 @@ int texas_post(int fd, struct termios *ti);
 int texasalt_init(int fd, int speed, struct termios *ti);
 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_init(int fd, int speed, int init_speed, char *bdaddr,
+						struct termios *ti);
 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_ath3k.c b/tools/hciattach_ath3k.c
index 70ade30..728e660 100644
--- a/tools/hciattach_ath3k.c
+++ b/tools/hciattach_ath3k.c
@@ -922,14 +922,49 @@ int ath3k_post(int fd, int pm)
 #define WRITE_BAUD_CMD_LEN   6
 #define MAX_CMD_LEN          WRITE_BDADDR_CMD_LEN
 
+static int set_cntrlr_baud(int fd, int speed)
+{
+	int baud;
+	struct timespec tm = { 0, 500000 };
+	unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
+	unsigned char *ptr = cmd + 1;
+	hci_command_hdr *ch = (void *)ptr;
+
+	cmd[0] = HCI_COMMAND_PKT;
+
+	/* set controller baud rate to user specified value */
+	ptr = cmd + 1;
+	ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+						HCI_CHG_BAUD_CMD_OCF));
+	ch->plen = 2;
+	ptr += HCI_COMMAND_HDR_SIZE;
+
+	baud = speed/100;
+	ptr[0] = (char)baud;
+	ptr[1] = (char)(baud >> 8);
+
+	if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) {
+		perror("Failed to write change baud rate command");
+		return -ETIMEDOUT;
+	}
+
+	nanosleep(&tm, NULL);
+
+	if (read_hci_event(fd, rsp, sizeof(rsp)) < 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 /*
  * Atheros AR300x specific initialization and configuration file
  * download
  */
-int ath3k_init(int fd, char *bdaddr, int speed)
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
+						struct termios *ti)
 {
 	int r;
-	int baud;
+	int err = 0;
 	struct timespec tm = { 0, 500000 };
 	unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
 	unsigned char *ptr = cmd + 1;
@@ -937,11 +972,23 @@ int ath3k_init(int fd, char *bdaddr, int speed)
 
 	cmd[0] = HCI_COMMAND_PKT;
 
+	/* set both controller and host baud rate to maximum possible value */
+	err = set_cntrlr_baud(fd, speed);
+	if (err < 0)
+		return err;
+
+	err = set_speed(fd, ti, speed);
+	if (err < 0) {
+		perror("Can't set required baud rate");
+		return err;
+	}
+
 	/* Download PS and patch */
 	r = ath_ps_download(fd);
 	if (r < 0) {
 		perror("Failed to Download configuration");
-		return -ETIMEDOUT;
+		err = -ETIMEDOUT;
+		goto failed;
 	}
 
 	/* Write BDADDR */
@@ -960,12 +1007,14 @@ int ath3k_init(int fd, char *bdaddr, int speed)
 		if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) !=
 					WRITE_BDADDR_CMD_LEN) {
 			perror("Failed to write BD_ADDR command\n");
-			return -ETIMEDOUT;
+			err = -ETIMEDOUT;
+			goto failed;
 		}
 
 		if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
 			perror("Failed to set BD_ADDR\n");
-			return -ETIMEDOUT;
+			err = -ETIMEDOUT;
+			goto failed;
 		}
 	}
 
@@ -975,33 +1024,26 @@ int ath3k_init(int fd, char *bdaddr, int speed)
 	cmd[3] = 0x00;
 
 	r = write(fd, cmd, 4);
-	if (r != 4)
-		return -ETIMEDOUT;
+	if (r != 4) {
+		err = -ETIMEDOUT;
+		goto failed;
+	}
 
 	nanosleep(&tm, NULL);
-	if (read_hci_event(fd, rsp, sizeof(rsp)) < 0)
-		return -ETIMEDOUT;
-
-	/* set controller baud rate to user specified value */
-	ptr = cmd + 1;
-	ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
-						HCI_CHG_BAUD_CMD_OCF));
-	ch->plen = 2;
-	ptr += HCI_COMMAND_HDR_SIZE;
-
-	baud = speed/100;
-	ptr[0] = (char)baud;
-	ptr[1] = (char)(baud >> 8);
-
-	if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) {
-		perror("Failed to write change baud rate command");
-		return -ETIMEDOUT;
+	if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+		err = -ETIMEDOUT;
+		goto failed;
 	}
 
-	nanosleep(&tm, NULL);
+	err = set_cntrlr_baud(fd, speed);
+	if (err < 0)
+		return err;
 
-	if (read_hci_event(fd, rsp, sizeof(rsp)) < 0)
-		return -ETIMEDOUT;
+failed:
+	if (err < 0) {
+		set_cntrlr_baud(fd, init_speed);
+		set_speed(fd, ti, init_speed);
+	}
 
-	return 0;
+	return err;
 }
-- 
1.7.0.4


^ permalink raw reply related

* [PATCHv4 7/7] Add RequestPairing method in simple-agent for accepting incoming OOB pairing requests
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 test/simple-agent |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/test/simple-agent b/test/simple-agent
index f2cc3dd..bbadd31 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -69,6 +69,16 @@ class Agent(dbus.service.Object):
 		raise Rejected("Mode change by user")
 
 	@dbus.service.method("org.bluez.Agent",
+			in_signature="o", out_signature="")
+
+	def RequestPairing(self, device):
+		print "RequestPairing (%s)" % (device)
+		pair = raw_input("Incoming pairing request, allow? (yes/no): ")
+		if (pair == "yes"):
+			return
+		raise Rejected("Not allowed")
+
+	@dbus.service.method("org.bluez.Agent",
 					in_signature="", out_signature="")
 	def Cancel(self):
 		print "Cancel"
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 6/7] Update D-Bus OOB API with RequestPairing method
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 doc/oob-api.txt      |   14 +++++++++
 doc/oob-api.txt.orig |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 0 deletions(-)
 create mode 100644 doc/oob-api.txt.orig

diff --git a/doc/oob-api.txt b/doc/oob-api.txt
index 4796e4c..e08f6f8 100644
--- a/doc/oob-api.txt
+++ b/doc/oob-api.txt
@@ -60,3 +60,17 @@ Methods		void RegisterProvider(object provider)
 			Possible errors: org.bluez.Error.ReadFailed
 					 org.bluez.Error.NoProvider
 					 org.bluez.Error.InProgress
+
+--------------------------------------------------------------------------------
+
+Service		unique name
+Interface	org.bluez.Agent
+Object path	freely definable
+
+Methods		void RequestPairing(object device)
+
+			This method gets called when the service daemon
+			needs to confirm incoming pairing request.
+
+			Possible errors: org.bluez.Error.Rejected
+					 org.bluez.Error.Canceled
diff --git a/doc/oob-api.txt.orig b/doc/oob-api.txt.orig
new file mode 100644
index 0000000..95dd3a4
--- /dev/null
+++ b/doc/oob-api.txt.orig
@@ -0,0 +1,79 @@
+BlueZ D-Bus OOB API description
+*******************************
+
+Copyright (C) 2010  ST-Ericsson SA
+
+Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+
+OOB hierarchy
+=================
+
+Service         unique name
+Interface       org.bluez.OobProvider
+Object path     freely definable
+
+Methods		array{byte} hash, array{byte} randomizer
+			RequestRemoteOobData(object device)
+
+			This method gets called when the service daemon needs to
+			get device's hash and randomizer for an OOB
+			authentication. Each array should be 16 bytes long.
+
+			Possible errors: org.bluez.Error.NoData
+
+		void Release()
+
+			This method gets called when D-Bus plug-in for OOB was
+			deactivated. There is no need to unregister provider,
+			because when this method gets called it has already been
+			unregistered.
+
+--------------------------------------------------------------------------------
+
+Service		org.bluez
+Interface	org.bluez.OobManager
+Object path	[variable prefix]/{hci0,hci1,...}
+
+Methods		void RegisterProvider(object provider)
+
+			This method registers provider for D-Bus OOB plug-in.
+			When provider is successfully registered plug-in becomes
+			active. Only one provider per adapter can be registered.
+
+			Possible errors: org.bluez.Error.AlreadyExists
+
+		void UnregisterProvider(object provider)
+
+			This method unregisters provider for D-Bus OOB plug-in.
+
+			Possible errors: org.bluez.Error.DoesNotExist
+
+		array{byte} hash, array{byte} randomizer ReadLocalOobData()
+
+			This method reads local OOB data for adapter. Return
+			value is pair of arrays 16 bytes each. Only registered
+			provider should call this method.
+
+			Note: This method will generate and return new local
+			OOB data.
+
+			Possible errors: org.bluez.Error.ReadFailed
+					 org.bluez.Error.NoProvider
+					 org.bluez.Error.InProgress
+<<<<<<< HEAD
+=======
+
+--------------------------------------------------------------------------------
+
+Service		unique name
+Interface	org.bluez.Agent
+Object path	freely definable
+
+Methods		void RequestPairing(object device)
+
+			This method gets called when the service daemon
+			needs to confirm incoming pairing request.
+
+			Possible errors: org.bluez.Error.Rejected
+					 org.bluez.Error.Canceled
+>>>>>>> 4375d12... doc fix
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 5/7] Add request for accepting incoming pairing requests with OOB mechanism
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 plugins/hciops.c |   41 ++++++++++++++++++++++++++++---------
 src/adapter.c    |    7 ++++++
 src/adapter.h    |    4 +++
 src/agent.c      |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/agent.h      |    3 ++
 src/device.c     |   22 ++++++++++++++++++++
 src/device.h     |    1 +
 src/event.c      |   36 ++++++++++++++++++++++++++++++++
 src/event.h      |    1 +
 9 files changed, 163 insertions(+), 11 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index c62ac51..e54f706 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -663,15 +663,8 @@ static void remote_oob_data_request(int index, void *ptr)
 	adapter = manager_find_adapter(&BDADDR(index));
 	device = adapter_find_device(adapter, da);
 
-	if (!device_get_oob_data(device, NULL, NULL) {
-		remote_oob_data_reply_cp cp;
-
-		bacpy(&cp.bdaddr, dba);
-		device_get_oob_data(device,cp.hash,cp.randomizer);
-
-		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY,
-				REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
-	} else
+	if (!device_get_oob_data(device, NULL, NULL) ||
+				btd_event_user_pairing(&BDADDR(index), dba))
 		hci_send_cmd(SK(index),
 				OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_NEG_REPLY, 6,
 				ptr);
@@ -2463,6 +2456,34 @@ static int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey)
 	return err;
 }
 
+static int hciops_pairing_reply(int index, struct btd_device *device,
+					gboolean approved)
+{
+	int err;
+
+	if (approved) {
+		remote_oob_data_reply_cp cp;
+
+		device_get_address(device, &cp.bdaddr);
+		device_get_oob_data(device,cp.hash,cp.randomizer);
+
+		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
+					OCF_REMOTE_OOB_DATA_REPLY,
+					REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
+	} else {
+		bdaddr_t bdaddr;
+
+		device_get_address(device, &bdaddr);
+		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
+				OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, &bdaddr);
+	}
+
+	if (err < 0)
+		err = -errno;
+
+	return err;
+}
+
 static int hciops_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth)
 {
 	struct hci_auth_info_req req;
@@ -2571,7 +2592,6 @@ static void hciops_io_capa_request_reply(int index, struct btd_device *device)
 					IO_CAPABILITY_REPLY_CP_SIZE, &cp);
 }
 
-
 static struct btd_adapter_ops hci_ops = {
 	.setup = hciops_setup,
 	.cleanup = hciops_cleanup,
@@ -2607,6 +2627,7 @@ static struct btd_adapter_ops hci_ops = {
 	.pincode_reply = hciops_pincode_reply,
 	.confirm_reply = hciops_confirm_reply,
 	.passkey_reply = hciops_passkey_reply,
+	.pairing_reply = hciops_pairing_reply,
 	.get_auth_info = hciops_get_auth_info,
 	.read_scan_enable = hciops_read_scan_enable,
 	.write_le_host = hciops_write_le_host,
diff --git a/src/adapter.c b/src/adapter.c
index f0c2dad..78b5ce3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3673,6 +3673,13 @@ int btd_adapter_passkey_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 	return adapter_ops->passkey_reply(adapter->dev_id, bdaddr, passkey);
 }
 
+int btd_adapter_pairing_reply(struct btd_adapter *adapter,
+				struct btd_device *device, gboolean approve)
+{
+	DBG("reply %u", approve);
+	return adapter_ops->pairing_reply(adapter->dev_id, device, approve);
+}
+
 int btd_adapter_get_auth_info(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 								uint8_t *auth)
 {
diff --git a/src/adapter.h b/src/adapter.h
index 16b7f67..e2bd94a 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -225,6 +225,8 @@ struct btd_adapter_ops {
 	int (*pincode_reply) (int index, bdaddr_t *bdaddr, const char *pin);
 	int (*confirm_reply) (int index, bdaddr_t *bdaddr, gboolean success);
 	int (*passkey_reply) (int index, bdaddr_t *bdaddr, uint32_t passkey);
+	int (*pairing_reply) (int index, struct btd_device *device,
+						gboolean success);
 	int (*get_auth_info) (int index, bdaddr_t *bdaddr, uint8_t *auth);
 	int (*read_scan_enable) (int index);
 	int (*write_le_host) (int index, uint8_t le, uint8_t simul);
@@ -276,6 +278,8 @@ int btd_adapter_confirm_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 							gboolean success);
 int btd_adapter_passkey_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 							uint32_t passkey);
+int btd_adapter_pairing_reply(struct btd_adapter *adapter,
+				struct btd_device *device, gboolean approve);
 
 int btd_adapter_get_auth_info(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 								uint8_t *auth);
diff --git a/src/agent.c b/src/agent.c
index 2ddfd6e..7dd969e 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -55,7 +55,8 @@ typedef enum {
 	AGENT_REQUEST_CONFIRMATION,
 	AGENT_REQUEST_PINCODE,
 	AGENT_REQUEST_AUTHORIZE,
-	AGENT_REQUEST_CONFIRM_MODE
+	AGENT_REQUEST_CONFIRM_MODE,
+	AGENT_REQUEST_PAIRING
 } agent_request_type_t;
 
 struct agent {
@@ -693,6 +694,62 @@ failed:
 	return err;
 }
 
+static int pairing_request_new(struct agent_request *req,
+					const char *device_path)
+{
+	struct agent *agent = req->agent;
+
+	req->msg = dbus_message_new_method_call(agent->name, agent->path,
+				"org.bluez.Agent", "RequestPairing");
+	if (req->msg == NULL) {
+		error("Couldn't allocate D-Bus message");
+		return -ENOMEM;
+	}
+
+	dbus_message_append_args(req->msg,
+				DBUS_TYPE_OBJECT_PATH, &device_path,
+				DBUS_TYPE_INVALID);
+
+	if (dbus_connection_send_with_reply(connection, req->msg,
+				&req->call, REQUEST_TIMEOUT) == FALSE) {
+		error("D-Bus send failed");
+		return -EIO;
+	}
+
+	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+
+	return 0;
+}
+
+int agent_request_pairing (struct agent *agent, struct btd_device *device,
+			agent_cb cb, void *user_data, GDestroyNotify destroy)
+{
+	struct agent_request *req;
+	const gchar *dev_path = device_get_path(device);
+	int err;
+
+	if (agent->request)
+		return -EBUSY;
+
+	DBG("Calling Agent.RequestPairing: name=%s, path=%s", agent->name,
+								agent->path);
+
+	req = agent_request_new(agent, AGENT_REQUEST_PAIRING, cb,
+							user_data, destroy);
+
+	err = pairing_request_new(req, dev_path);
+	if (err < 0)
+		goto failed;
+
+	agent->request = req;
+
+	return 0;
+
+failed:
+	agent_request_free(req, FALSE);
+	return err;
+}
+
 static int request_fallback(struct agent_request *req,
 				DBusPendingCallNotifyFunction function)
 {
diff --git a/src/agent.h b/src/agent.h
index e184250..5aa2702 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -64,6 +64,9 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
 int agent_display_passkey(struct agent *agent, struct btd_device *device,
 				uint32_t passkey);
 
+int agent_request_pairing (struct agent *agent, struct btd_device *device,
+			agent_cb cb, void *user_data, GDestroyNotify destroy);
+
 int agent_cancel(struct agent *agent);
 
 gboolean agent_is_busy(struct agent *agent, void *user_data);
diff --git a/src/device.c b/src/device.c
index fd3c3b3..c1a3bfe 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2243,6 +2243,21 @@ static void passkey_cb(struct agent *agent, DBusError *err,
 	device->authr->agent = NULL;
 }
 
+static void pairing_cb(struct agent *agent, DBusError *err, void *data)
+{
+	struct authentication_req *auth = data;
+	struct btd_device *device = auth->device;
+
+	/* No need to reply anything if the authentication already failed */
+	if (auth->cb == NULL)
+		return;
+
+	((agent_cb) auth->cb)(agent, err, device);
+
+	device->authr->cb = NULL;
+	device->authr->agent = NULL;
+}
+
 int device_request_authentication(struct btd_device *device, auth_type_t type,
 						uint32_t passkey, void *cb)
 {
@@ -2281,6 +2296,10 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
 	case AUTH_TYPE_NOTIFY:
 		err = agent_display_passkey(agent, device, passkey);
 		break;
+	case AUTH_TYPE_PAIRING:
+		err = agent_request_pairing (agent, device, pairing_cb, auth,
+									NULL);
+		break;
 	case AUTH_TYPE_AUTO:
 		err = 0;
 		break;
@@ -2322,6 +2341,9 @@ static void cancel_authentication(struct authentication_req *auth)
 	case AUTH_TYPE_PASSKEY:
 		((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
 		break;
+	case AUTH_TYPE_PAIRING:
+		((agent_cb) auth->cb)(agent, &err, device);
+		break;
 	case AUTH_TYPE_NOTIFY:
 	case AUTH_TYPE_AUTO:
 		/* User Notify/Auto doesn't require any reply */
diff --git a/src/device.h b/src/device.h
index 1823f65..5e673d0 100644
--- a/src/device.h
+++ b/src/device.h
@@ -33,6 +33,7 @@ typedef enum {
 	AUTH_TYPE_CONFIRM,
 	AUTH_TYPE_NOTIFY,
 	AUTH_TYPE_AUTO,
+	AUTH_TYPE_PAIRING
 } auth_type_t;
 
 struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
diff --git a/src/event.c b/src/event.c
index a88a8f5..316273a 100644
--- a/src/event.c
+++ b/src/event.c
@@ -175,6 +175,15 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
 	btd_adapter_passkey_reply(adapter, &bdaddr, passkey);
 }
 
+static void pairing_cb(struct agent *agent, DBusError *err, void *user_data)
+{
+	struct btd_device *device = user_data;
+	struct btd_adapter *adapter = device_get_adapter(device);
+	gboolean approve = (err == NULL) ? TRUE : FALSE;
+
+	btd_adapter_pairing_reply(adapter, device, approve);
+}
+
 int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
 {
 	struct btd_adapter *adapter;
@@ -264,6 +273,33 @@ int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
 								passkey, NULL);
 }
 
+int btd_event_user_pairing(bdaddr_t *sba, bdaddr_t *dba)
+{
+	struct btd_adapter *adapter;
+	struct btd_device *device;
+	struct agent *agent;
+	uint8_t cap;
+
+	if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
+		return -ENODEV;
+
+	agent = device_get_agent(device);
+	if (!agent)
+		return -ENODEV;
+
+	cap = agent_get_io_capability(agent);
+
+	/* If initiator or agent has no input capability allow pairing
+	 * immediately. */
+	if (device_is_bonding(device, NULL) || cap == 0x00 || cap == 0x03) {
+		btd_adapter_pairing_reply(adapter, device, TRUE);
+		return 0;
+	}
+
+	return device_request_authentication(device, AUTH_TYPE_PAIRING, 0,
+								pairing_cb);
+}
+
 void btd_event_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
 								uint8_t status)
 {
diff --git a/src/event.h b/src/event.h
index 5c122ea..3fde56b 100644
--- a/src/event.h
+++ b/src/event.h
@@ -41,6 +41,7 @@ int btd_event_set_io_cap(bdaddr_t *local, bdaddr_t *remote,
 int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
 int btd_event_user_passkey(bdaddr_t *sba, bdaddr_t *dba);
 int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
+int btd_event_user_pairing(bdaddr_t *sba, bdaddr_t *dba);
 int btd_event_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
 				uint8_t *key, uint8_t key_type,
 				int pin_length, uint8_t old_key_type);
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 4/7] Add simple-oobprovider for testing
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 test/simple-oobprovider |   57 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 57 insertions(+), 0 deletions(-)
 create mode 100755 test/simple-oobprovider

diff --git a/test/simple-oobprovider b/test/simple-oobprovider
new file mode 100755
index 0000000..e5181f3
--- /dev/null
+++ b/test/simple-oobprovider
@@ -0,0 +1,57 @@
+#!/usr/bin/python
+# Copyright (C) 2010  ST-Ericsson SA
+# Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+
+import gobject
+
+import sys
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+
+class NoOobData(dbus.DBusException):
+        _dbus_error_name = "org.bluez.Error.NoData"
+
+
+class Provider(dbus.service.Object):
+
+	remotedata = None
+
+	@dbus.service.method("org.bluez.OobProvider",
+					in_signature="s", out_signature="ayay")
+
+	def RequestRemoteOobData(self, device):
+		print "RequestRemoteOobData for %s" % (device)
+		if (self.remotedata != None):
+			return self.remotedata
+		raise NoOobData("No OOB data present")
+
+if __name__ == '__main__':
+	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+	bus = dbus.SystemBus()
+
+	manager = dbus.Interface(bus.get_object("org.bluez", "/"),
+			"org.bluez.Manager")
+
+	adapter_path = manager.DefaultAdapter()
+	adapter = dbus.Interface(bus.get_object("org.bluez",
+			adapter_path), "org.bluez.OobManager")
+	path = "/test/oobprovider"
+	provider = Provider(bus, path)
+
+	mainloop = gobject.MainLoop()
+
+	adapter.RegisterProvider(path)
+
+	print "Local data for %s:" % (adapter_path)
+	print adapter.ReadLocalOobData()
+
+	provider.remotedata = input("Provide remote data (in python syntax):\n")
+
+	print "You may try pairing now"
+
+	mainloop.run()
+
+	#adapter.UnregisterProvider(path)
+	#print "Provider unregistered"
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 3/7] Add D-Bus OOB API documentation
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 Makefile.am     |    2 +-
 doc/oob-api.txt |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletions(-)
 create mode 100644 doc/oob-api.txt

diff --git a/Makefile.am b/Makefile.am
index 9607553..ab56edc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -360,7 +360,7 @@ EXTRA_DIST += doc/manager-api.txt \
 		doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
 		doc/serial-api.txt doc/network-api.txt \
 		doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
-		doc/hfp-api.txt doc/assigned-numbers.txt
+		doc/hfp-api.txt doc/assigned-numbers.txt doc/oob-api.txt
 
 AM_YFLAGS = -d
 
diff --git a/doc/oob-api.txt b/doc/oob-api.txt
new file mode 100644
index 0000000..4796e4c
--- /dev/null
+++ b/doc/oob-api.txt
@@ -0,0 +1,62 @@
+BlueZ D-Bus OOB API description
+*******************************
+
+Copyright (C) 2010  ST-Ericsson SA
+
+Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+
+OOB hierarchy
+=================
+
+Service         unique name
+Interface       org.bluez.OobProvider
+Object path     freely definable
+
+Methods		array{byte} hash, array{byte} randomizer
+			RequestRemoteOobData(object device)
+
+			This method gets called when the service daemon needs to
+			get device's hash and randomizer for an OOB
+			authentication. Each array should be 16 bytes long.
+
+			Possible errors: org.bluez.Error.NoData
+
+		void Release()
+
+			This method gets called when D-Bus plug-in for OOB was
+			deactivated. There is no need to unregister provider,
+			because when this method gets called it has already been
+			unregistered.
+
+--------------------------------------------------------------------------------
+
+Service		org.bluez
+Interface	org.bluez.OobManager
+Object path	[variable prefix]/{hci0,hci1,...}
+
+Methods		void RegisterProvider(object provider)
+
+			This method registers provider for D-Bus OOB plug-in.
+			When provider is successfully registered plug-in becomes
+			active. Only one provider per adapter can be registered.
+
+			Possible errors: org.bluez.Error.AlreadyExists
+
+		void UnregisterProvider(object provider)
+
+			This method unregisters provider for D-Bus OOB plug-in.
+
+			Possible errors: org.bluez.Error.DoesNotExist
+
+		array{byte} hash, array{byte} randomizer ReadLocalOobData()
+
+			This method reads local OOB data for adapter. Return
+			value is pair of arrays 16 bytes each. Only registered
+			provider should call this method.
+
+			Note: This method will generate and return new local
+			OOB data.
+
+			Possible errors: org.bluez.Error.ReadFailed
+					 org.bluez.Error.NoProvider
+					 org.bluez.Error.InProgress
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 2/7] Add D-Bus OOB plugin
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 Makefile.am       |    5 +
 acinclude.m4      |    6 +
 plugins/dbusoob.c |  412 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 423 insertions(+), 0 deletions(-)
 create mode 100644 plugins/dbusoob.c

diff --git a/Makefile.am b/Makefile.am
index 47da8eb..9607553 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -218,6 +218,11 @@ builtin_modules += maemo6
 builtin_sources += plugins/maemo6.c
 endif
 
+if DBUSOOBPLUGIN
+builtin_modules += dbusoob
+builtin_sources += plugins/dbusoob.c
+endif
+
 sbin_PROGRAMS += src/bluetoothd
 
 src_bluetoothd_SOURCES = $(gdbus_sources) $(builtin_sources) \
diff --git a/acinclude.m4 b/acinclude.m4
index 287f07d..6704d46 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -193,6 +193,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	configfiles_enable=yes
 	telephony_driver=dummy
 	maemo6_enable=no
+	dbusoob_enable=no
 
 	AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization]), [
 		optimization_enable=${enableval}
@@ -316,6 +317,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		maemo6_enable=${enableval}
 	])
 
+	AC_ARG_ENABLE(dbusoob, AC_HELP_STRING([--enable-dbusoob], [compile with D-Bus OOB plugin]), [
+		dbusoob_enable=${enableval}
+	])
+
 	AC_ARG_ENABLE(hal, AC_HELP_STRING([--enable-hal], [Use HAL to determine adapter class]), [
 		hal_enable=${enableval}
 	])
@@ -372,4 +377,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(UDEVRULES, test "${udevrules_enable}" = "yes")
 	AM_CONDITIONAL(CONFIGFILES, test "${configfiles_enable}" = "yes")
 	AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
+	AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
 ])
diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c
new file mode 100644
index 0000000..e137b81
--- /dev/null
+++ b/plugins/dbusoob.c
@@ -0,0 +1,412 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010  ST-Ericsson SA
+ *
+ *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ *  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 <errno.h>
+#include <gdbus.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/sdp.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "manager.h"
+#include "device.h"
+#include "adapter.h"
+#include "dbus-common.h"
+#include "event.h"
+#include "error.h"
+#include "oob.h"
+
+#define REQUEST_TIMEOUT		(60 * 1000)	/* 60 seconds */
+#define OOB_PROVIDER_INTERFACE	"org.bluez.OobProvider"
+#define OOB_MANAGER_INTERFACE	"org.bluez.OobManager"
+
+struct oob_provider {
+	char *name;
+	char *path;
+	struct btd_adapter *adapter;
+	DBusMessage *msg;
+	guint listener_id;
+	gboolean exited;
+};
+
+static GSList *providers = NULL;
+static DBusConnection *connection = NULL;
+static struct oob_plugin dbusoob;
+
+static void destroy_provider(struct oob_provider *provider)
+{
+	if (!provider->exited)
+		g_dbus_remove_watch(connection, provider->listener_id);
+
+	if (provider->msg)
+		dbus_message_unref(provider->msg);
+
+	DBG("Provider destroyed (%s at %s)", provider->name, provider->path);
+
+	g_free(provider->name);
+	g_free(provider->path);
+	g_free(provider);
+
+	providers = g_slist_remove(providers, provider);
+
+	if (!providers)
+		oob_deactivate_plugin(&dbusoob);
+}
+
+static void provider_exited(DBusConnection *conn, void *user_data)
+{
+	struct oob_provider *provider = user_data;
+
+	DBG("Provider exited without calling Unregister (%s at %s)",
+						provider->name, provider->path);
+
+	provider->exited = TRUE;
+	destroy_provider(provider);
+}
+
+static void create_provider(const char *path, const char *name,
+						struct btd_adapter *adapter)
+{
+	struct oob_provider *provider;
+
+	provider = g_new(struct oob_provider, 1);
+	provider->path = g_strdup(path);
+	provider->name = g_strdup(name);
+	provider->adapter = adapter;
+	provider->msg = NULL;
+	provider->exited = FALSE;
+	provider->listener_id = g_dbus_add_disconnect_watch(connection, name,
+					provider_exited, provider, NULL);
+
+	providers = g_slist_append(providers, provider);
+
+	DBG("OOB provider for %s registered at %s(%s)", provider->path,
+				provider->name, adapter_get_path(adapter));
+
+	oob_activate_plugin(&dbusoob);
+}
+
+static void request_remote_data_reply(DBusPendingCall *call, void *data)
+{
+	DBusMessage *msg;
+	DBusError err;
+	struct btd_device *device = data;
+	uint8_t *hash = NULL;
+	uint8_t *randomizer = NULL;
+	int32_t hlen, rlen;
+
+	msg = dbus_pending_call_steal_reply(call);
+
+	dbus_error_init(&err);
+	if (dbus_set_error_from_message(&err, msg)) {
+		error("Provider replied with an error: %s, %s", err.name,
+								err.message);
+		dbus_error_free(&err);
+		goto error;
+	}
+
+	dbus_error_init(&err);
+	if (!dbus_message_get_args(msg, &err,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hlen,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &rlen,
+			DBUS_TYPE_INVALID) || hlen != 16 || rlen != 16) {
+		error("RequestRemoteOobData reply signature error: %s, %s",
+							err.name, err.message);
+		dbus_error_free(&err);
+		hash = NULL;
+		randomizer = NULL;
+	}
+
+error:
+	dbus_message_unref(msg);
+	dbus_pending_call_unref(call);
+
+	device_set_oob_data(device, hash, randomizer);
+}
+
+static gint provider_adapter_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct oob_provider *provider = a;
+	const struct btd_adapter *adapter = b;
+
+	return provider->adapter != adapter;
+}
+
+static struct oob_provider* find_provider(struct btd_adapter *adapter)
+{
+	GSList *match;
+
+	match = g_slist_find_custom(providers, adapter, provider_adapter_cmp);
+	if (match)
+		return match->data;
+
+	return NULL;
+}
+
+static gboolean request_remote_data(struct btd_device *device)
+{
+	DBusMessage* msg;
+	DBusPendingCall *call = NULL;
+	const gchar *path;
+	gboolean ret = FALSE;
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct oob_provider *provider;
+
+	provider = find_provider(adapter);
+	if (!provider)
+		return ret;
+
+	msg = dbus_message_new_method_call(provider->name, provider->path,
+				OOB_PROVIDER_INTERFACE, "RequestRemoteOobData");
+
+	if (!msg) {
+		error("Couldn't allocate D-Bus message");
+		goto error;
+	}
+
+	path = device_get_path(device);
+
+	if (!dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID)) {
+		error ("Couldn't append arguments");
+		goto error;
+	}
+
+	if (!dbus_connection_send_with_reply(connection, msg, &call,
+							REQUEST_TIMEOUT)) {
+		error("D-Bus send failed");
+		goto error;
+	}
+
+	if (!dbus_pending_call_set_notify(call, request_remote_data_reply,
+								device, NULL)) {
+		error("Couldn't set reply notification.");
+		dbus_pending_call_unref(call);
+		goto error;
+	}
+
+	ret = TRUE;
+
+error:
+	if (msg)
+		dbus_message_unref(msg);
+
+	return ret;
+}
+
+static void local_data_read(struct btd_adapter *adapter, uint8_t *hash,
+				uint8_t *randomizer)
+{
+	struct DBusMessage *reply;
+	struct oob_provider *provider;
+
+	provider = find_provider(adapter);
+	if (!provider)
+		return;
+
+	if (hash && randomizer)
+		reply = g_dbus_create_reply(provider->msg,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, 16,
+			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, 16,
+			DBUS_TYPE_INVALID);
+	else
+		reply = g_dbus_create_error(provider->msg,
+					ERROR_INTERFACE ".ReadFailed",
+					"Failed to read local OOB data.");
+
+	dbus_message_unref(provider->msg);
+	provider->msg = NULL;
+
+	if (!reply) {
+		error("Couldn't allocate D-Bus message");
+		return;
+	}
+
+	if (!g_dbus_send_message(connection, reply))
+		error("D-Bus send failed");
+}
+
+static DBusMessage *read_local_data(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *name;
+	struct btd_adapter *adapter = data;
+	struct oob_provider *provider;
+
+	name = dbus_message_get_sender(msg);
+
+	provider = find_provider(adapter);
+	if (!provider)
+		return g_dbus_create_error(msg, ERROR_INTERFACE ".NoProvider",
+						"No provider registered");
+
+	if (!g_str_equal(provider->name, name))
+		return g_dbus_create_error(msg, ERROR_INTERFACE ".NoProvider",
+							"Not OOB provider");
+
+	if (provider->msg)
+		return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
+						"Another request in progress.");
+
+	if (btd_adapter_read_local_oob_data(adapter))
+		return g_dbus_create_error(msg, ERROR_INTERFACE ".ReadFailed",
+							"HCI request failed");
+
+	provider->msg = dbus_message_ref(msg);
+	return NULL;
+}
+
+static void release_provider(struct oob_provider *provider)
+{
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(provider->name, provider->path,
+					OOB_PROVIDER_INTERFACE, "Release");
+
+	if (!msg)
+		error("Couldn't allocate D-Bus message");
+	else if (!g_dbus_send_message(connection, msg))
+		error("D-Bus send failed");
+
+	destroy_provider(provider);
+}
+
+static void plugin_deactivated(void)
+{
+	g_slist_foreach(providers, (GFunc) release_provider, NULL);
+	g_slist_free(providers);
+}
+
+static DBusMessage *register_provider(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *path, *name;
+	struct btd_adapter *adapter = data;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return NULL;
+
+	if (find_provider(adapter))
+		return g_dbus_create_error(msg,
+					ERROR_INTERFACE ".AlreadyExists",
+					"OOB provider already registered");
+
+	name = dbus_message_get_sender(msg);
+	create_provider(path, name, adapter);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_provider(DBusConnection *conn, DBusMessage *msg,
+								void *data)
+{
+	const char *path, *name;
+	struct btd_adapter *adapter = data;
+	struct oob_provider *provider;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+							DBUS_TYPE_INVALID))
+		return NULL;
+
+	name = dbus_message_get_sender(msg);
+
+	provider = find_provider(adapter);
+	if (!provider)
+		return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
+						"No provider registered");
+
+	if (!g_str_equal(provider->path, path) ||
+			!g_str_equal(provider->name, name))
+		return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
+						"Not a registered provider");
+
+	DBG("OOB provider %s(%s) unregistered", provider->path, provider->name);
+
+	destroy_provider(provider);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable oob_methods[] = {
+	{ "RegisterProvider",	"o",	"",	register_provider	},
+	{ "UnregisterProvider",	"o",	"",	unregister_provider	},
+	{ "ReadLocalOobData",	"",	"ayay",	read_local_data,
+						G_DBUS_METHOD_FLAG_ASYNC},
+	{ }
+};
+
+static int oob_probe(struct btd_adapter *adapter)
+{
+	const char* path = adapter_get_path(adapter);
+
+	if (!g_dbus_register_interface(connection, path, OOB_MANAGER_INTERFACE,
+				oob_methods, NULL, NULL, adapter, NULL)) {
+			error("OOB interface init failed on path %s", path);
+			return -EIO;
+		}
+
+	return 0;
+}
+
+static void oob_remove(struct btd_adapter *adapter)
+{
+	g_dbus_unregister_interface(connection, adapter_get_path(adapter),
+							OOB_MANAGER_INTERFACE);
+}
+
+static struct btd_adapter_driver oob_driver = {
+	.name	= "oob",
+	.probe	= oob_probe,
+	.remove	= oob_remove,
+};
+
+static int dbusoob_init(void)
+{
+	DBG("Setup dbusoob plugin");
+
+	connection = get_dbus_connection();
+
+	dbusoob.request_remote_data = request_remote_data;
+	dbusoob.local_data_read = local_data_read;
+	dbusoob.plugin_deactivated = plugin_deactivated;
+
+	return btd_register_adapter_driver(&oob_driver);
+}
+
+static void dbusoob_exit(void)
+{
+	DBG("Cleanup dbusoob plugin");
+	oob_deactivate_plugin(&dbusoob);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+						dbusoob_init, dbusoob_exit)
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 1/7] Add support for Out of Band (OOB) association model
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1290509592-9262-1-git-send-email-szymon.janc@tieto.com>

---
 Makefile.am      |    3 +-
 lib/hci.h        |    3 ++
 plugins/hciops.c |   86 +++++++++++++++++++++++++++++++++++++++++++++--------
 src/adapter.c    |   14 ++++++++-
 src/adapter.h    |    6 ++++
 src/device.c     |   74 ++++++++++++++++++++++++++++++++++++++++++++++
 src/device.h     |   12 +++++++
 src/event.c      |   53 +++++++++++++++++++++------------
 src/event.h      |    3 +-
 src/oob.c        |   67 ++++++++++++++++++++++++++++++++++++++++++
 src/oob.h        |   47 +++++++++++++++++++++++++++++
 11 files changed, 332 insertions(+), 36 deletions(-)
 create mode 100644 src/oob.c
 create mode 100644 src/oob.h

diff --git a/Makefile.am b/Makefile.am
index 5f96975..47da8eb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -240,7 +240,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/event.h src/event.c
+			src/event.h src/event.c \
+			src/oob.c
 src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
 							@CAPNG_LIBS@ -ldl -lrt
 src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
diff --git a/lib/hci.h b/lib/hci.h
index 0cb120f..409abd9 100644
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -524,6 +524,9 @@ typedef struct {
 
 #define OCF_REMOTE_OOB_DATA_NEG_REPLY	0x0033
 
+#define OOB_DATA_NOT_PRESENT	0x00
+#define OOB_DATA_PRESENT	0x01
+
 #define OCF_IO_CAPABILITY_NEG_REPLY	0x0034
 typedef struct {
 	bdaddr_t	bdaddr;
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 9abe477..c62ac51 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -3,6 +3,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010  ST-Ericsson SA
  *
  *  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
@@ -47,6 +48,7 @@
 #include "event.h"
 #include "device.h"
 #include "manager.h"
+#include "oob.h"
 
 #define HCI_REQ_TIMEOUT         5000
 
@@ -652,20 +654,41 @@ static void user_passkey_notify(int index, void *ptr)
 
 static void remote_oob_data_request(int index, void *ptr)
 {
-	hci_send_cmd(SK(index), OGF_LINK_CTL,
-				OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, ptr);
+	bdaddr_t *dba = ptr;
+	struct btd_adapter *adapter;
+	struct btd_device *device;
+	char da[18];
+
+	ba2str(dba, da);
+	adapter = manager_find_adapter(&BDADDR(index));
+	device = adapter_find_device(adapter, da);
+
+	if (!device_get_oob_data(device, NULL, NULL) {
+		remote_oob_data_reply_cp cp;
+
+		bacpy(&cp.bdaddr, dba);
+		device_get_oob_data(device,cp.hash,cp.randomizer);
+
+		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY,
+				REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
+	} else
+		hci_send_cmd(SK(index),
+				OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_NEG_REPLY, 6,
+				ptr);
 }
 
 static void io_capa_request(int index, void *ptr)
 {
 	bdaddr_t *dba = ptr;
 	char sa[18], da[18];
-	uint8_t cap, auth;
 
 	ba2str(&BDADDR(index), sa); ba2str(dba, da);
 	info("io_capa_request (sba=%s, dba=%s)", sa, da);
 
-	if (btd_event_get_io_cap(&BDADDR(index), dba, &cap, &auth) < 0) {
+	/* If failed to establish IO capabilities then send negative reply
+	 * immediately. Positive reply will be sent when IO capabilities are
+	 * established. */
+	if (btd_event_request_io_cap(&BDADDR(index), dba)) {
 		io_capability_neg_reply_cp cp;
 		memset(&cp, 0, sizeof(cp));
 		bacpy(&cp.bdaddr, dba);
@@ -673,15 +696,6 @@ static void io_capa_request(int index, void *ptr)
 		hci_send_cmd(SK(index), OGF_LINK_CTL,
 					OCF_IO_CAPABILITY_NEG_REPLY,
 					IO_CAPABILITY_NEG_REPLY_CP_SIZE, &cp);
-	} else {
-		io_capability_reply_cp cp;
-		memset(&cp, 0, sizeof(cp));
-		bacpy(&cp.bdaddr, dba);
-		cp.capability = cap;
-		cp.oob_data = 0x00;
-		cp.authentication = auth;
-		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY,
-					IO_CAPABILITY_REPLY_CP_SIZE, &cp);
 	}
 }
 
@@ -995,6 +1009,9 @@ static inline void cmd_status(int index, void *ptr)
 
 	if (opcode == cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY))
 		start_inquiry(&BDADDR(index), evt->status, FALSE);
+	else if (opcode == cmd_opcode_pack(OGF_HOST_CTL,
+						OCF_READ_LOCAL_OOB_DATA))
+		oob_local_data_read(&BDADDR(index), NULL, NULL);
 }
 
 static void read_scan_complete(int index, uint8_t status, void *ptr)
@@ -1012,6 +1029,15 @@ static void read_scan_complete(int index, uint8_t status, void *ptr)
 	adapter_mode_changed(adapter, rp->enable);
 }
 
+static void read_local_oob_data_complete(bdaddr_t *local, uint8_t status,
+						read_local_oob_data_rp *rp)
+{
+	if (status)
+		oob_local_data_read(local, NULL, NULL);
+	else
+		oob_local_data_read(local, rp->hash, rp->randomizer);
+}
+
 static inline void cmd_complete(int index, void *ptr)
 {
 	evt_cmd_complete *evt = ptr;
@@ -1083,6 +1109,10 @@ static inline void cmd_complete(int index, void *ptr)
 		ptr += sizeof(evt_cmd_complete);
 		read_tx_power_complete(index, ptr);
 		break;
+	case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA):
+		ptr += sizeof(evt_cmd_complete);
+		read_local_oob_data_complete(&BDADDR(index), status, ptr);
+		break;
 	};
 }
 
@@ -2514,6 +2544,34 @@ static int hciops_get_remote_version(int index, uint16_t handle,
 	return 0;
 }
 
+static int hciops_read_local_oob_data(int index)
+{
+	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_READ_LOCAL_OOB_DATA, 0, 0)
+			< 0)
+		return -errno;
+
+	return 0;
+}
+
+
+static void hciops_io_capa_request_reply(int index, struct btd_device *device)
+{
+	io_capability_reply_cp cp;
+
+	memset(&cp, 0, sizeof(cp));
+	device_get_address(device, &cp.bdaddr);
+	device_get_local_auth_cap(device, &cp.authentication, &cp.capability);
+	cp.oob_data = device_get_oob_data(device, NULL, NULL)
+			? OOB_DATA_PRESENT : OOB_DATA_NOT_PRESENT;
+
+	DBG("final capabilities reply is cap=0x%02x, auth=0x%02x, oob=0x%02x",
+	cp.capability, cp.authentication, cp.oob_data);
+
+	hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_IO_CAPABILITY_REPLY,
+					IO_CAPABILITY_REPLY_CP_SIZE, &cp);
+}
+
+
 static struct btd_adapter_ops hci_ops = {
 	.setup = hciops_setup,
 	.cleanup = hciops_cleanup,
@@ -2554,6 +2612,8 @@ static struct btd_adapter_ops hci_ops = {
 	.write_le_host = hciops_write_le_host,
 	.get_remote_version = hciops_get_remote_version,
 	.encrypt_link = hciops_encrypt_link,
+	.read_local_oob_data = hciops_read_local_oob_data,
+	.io_capa_request_reply = hciops_io_capa_request_reply
 };
 
 static int hciops_init(void)
diff --git a/src/adapter.c b/src/adapter.c
index 6b4a354..f0c2dad 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3245,7 +3245,8 @@ void adapter_remove_connection(struct btd_adapter *adapter,
 	/* clean pending HCI cmds */
 	device_get_address(device, &bdaddr);
 
-	if (device_is_authenticating(device))
+	if (device_is_authenticating(device) ||
+			device_get_oob_data(device, NULL, NULL))
 		device_cancel_authentication(device, TRUE);
 
 	if (device_is_temporary(device)) {
@@ -3713,3 +3714,14 @@ int btd_adapter_encrypt_link(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 {
 	return adapter_ops->encrypt_link(adapter->dev_id, bdaddr, cb, user_data);
 }
+
+int btd_adapter_read_local_oob_data(struct btd_adapter *adapter)
+{
+	return adapter_ops->read_local_oob_data(adapter->dev_id);
+}
+
+void btd_adapter_io_capa_request_reply(struct btd_adapter *adapter,
+					struct btd_device *device)
+{
+	adapter_ops->io_capa_request_reply(adapter->dev_id, device);
+}
diff --git a/src/adapter.h b/src/adapter.h
index de6a6f5..16b7f67 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -232,6 +232,8 @@ struct btd_adapter_ops {
 						gboolean delayed);
 	int (*encrypt_link) (int index, bdaddr_t *bdaddr, bt_hci_result_t cb,
 							gpointer user_data);
+	int (*read_local_oob_data) (int index);
+	void (*io_capa_request_reply) (int index, struct btd_device *device);
 };
 
 int btd_register_adapter_ops(struct btd_adapter_ops *ops, gboolean priority);
@@ -291,3 +293,7 @@ int btd_adapter_get_remote_version(struct btd_adapter *adapter,
 
 int btd_adapter_encrypt_link(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 				bt_hci_result_t cb, gpointer user_data);
+
+int btd_adapter_read_local_oob_data(struct btd_adapter *adapter);
+void btd_adapter_io_capa_request_reply(struct btd_adapter *adapter,
+					struct btd_device *device);
diff --git a/src/device.c b/src/device.c
index 7c421e3..fd3c3b3 100644
--- a/src/device.c
+++ b/src/device.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010  ST-Ericsson SA
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -59,6 +60,7 @@
 #include "sdp-xml.h"
 #include "storage.h"
 #include "btio.h"
+#include "oob.h"
 
 #define DEFAULT_XML_BUF_SIZE	1024
 #define DISCONNECT_TIMER	2
@@ -132,6 +134,9 @@ struct btd_device {
 	uint8_t		cap;
 	uint8_t		auth;
 
+	uint8_t		local_cap;
+	uint8_t		local_auth;
+
 	uint16_t	handle;			/* Connection handle */
 
 	/* Whether were creating a security mode 3 connection */
@@ -149,6 +154,12 @@ struct btd_device {
 
 	gboolean	has_debug_key;
 	uint8_t		debug_key[16];
+
+	/* For OOB association model */
+	void (*oob_request_cb)(struct btd_device *device);
+	gboolean	has_oob_data;
+	uint8_t		hash[16];
+	uint8_t		randomizer[16];
 };
 
 static uint16_t uuid_list[] = {
@@ -829,6 +840,67 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+void device_set_oob_data(struct btd_device *device, uint8_t *hash,
+				uint8_t *randomizer)
+{
+	if (!device)
+		return;
+
+	if (hash && randomizer) {
+		memcpy(device->hash, hash, 16);
+		memcpy(device->randomizer, randomizer, 16);
+		device->has_oob_data = TRUE;
+	}
+
+	if (device->oob_request_cb) {
+		device->oob_request_cb(device);
+		device->oob_request_cb = NULL;
+	}
+}
+
+gboolean device_get_oob_data(struct btd_device *device, uint8_t *hash,
+				uint8_t *randomizer)
+{
+	if (!device || !device->has_oob_data)
+		return FALSE;
+
+	if (hash && randomizer) {
+		memcpy(hash, device->hash, 16);
+		memcpy(randomizer, device->randomizer, 16);
+	}
+
+	return TRUE;
+}
+
+gboolean device_request_oob_data(struct btd_device *device,
+					void (*cb)(struct btd_device *device))
+{
+	if (!device)
+		return FALSE;
+
+	device->oob_request_cb = cb;
+	return oob_request_remote_data(device);
+}
+
+void device_set_local_auth_cap(struct btd_device *device, uint8_t auth,
+				uint8_t cap)
+{
+	if (!device)
+		return;
+
+	device->local_auth = auth;
+	device->local_cap = cap;
+}
+void device_get_local_auth_cap(struct btd_device *device, uint8_t *auth,
+				uint8_t *cap)
+{
+	if (!device)
+		return;
+
+	*auth = device->local_auth;
+	*cap = device->local_cap;
+}
+
 static GDBusMethodTable device_methods[] = {
 	{ "GetProperties",	"",	"a{sv}",	get_properties	},
 	{ "SetProperty",	"sv",	"",		set_property	},
@@ -2264,6 +2336,8 @@ void device_cancel_authentication(struct btd_device *device, gboolean aborted)
 {
 	struct authentication_req *auth = device->authr;
 
+	device->has_oob_data = FALSE;
+
 	if (!auth)
 		return;
 
diff --git a/src/device.h b/src/device.h
index b570bd1..1823f65 100644
--- a/src/device.h
+++ b/src/device.h
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010  ST-Ericsson SA
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -89,6 +90,17 @@ void device_remove_connection(struct btd_device *device, DBusConnection *conn,
 gboolean device_has_connection(struct btd_device *device, uint16_t handle);
 void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
 
+void device_set_oob_data(struct btd_device *device, uint8_t *hash,
+				uint8_t *randomizer);
+gboolean device_get_oob_data(struct btd_device *device, uint8_t *hash,
+				uint8_t *randomizer);
+gboolean device_request_oob_data(struct btd_device *device,
+					void (*cb)(struct btd_device *device));
+void device_set_local_auth_cap(struct btd_device *device, uint8_t auth,
+				uint8_t cap);
+void device_get_local_auth_cap(struct btd_device *device, uint8_t *auth,
+				uint8_t *cap);
+
 typedef void (*disconnect_watch) (struct btd_device *device, gboolean removal,
 					void *user_data);
 
diff --git a/src/event.c b/src/event.c
index daab71a..a88a8f5 100644
--- a/src/event.c
+++ b/src/event.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2006-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010  ST-Ericsson SA
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -274,7 +275,8 @@ void btd_event_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
 	if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
 		return;
 
-	if (!device_is_authenticating(device)) {
+	if (!device_is_authenticating(device) &&
+			!device_get_oob_data(device, NULL, NULL)) {
 		/* This means that there was no pending PIN or SSP token
 		 * request from the controller, i.e. this is not a new
 		 * pairing */
@@ -724,26 +726,33 @@ void btd_event_returned_link_key(bdaddr_t *local, bdaddr_t *peer)
 	device_set_paired(device, TRUE);
 }
 
-int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
-						uint8_t *cap, uint8_t *auth)
+static void btd_event_io_cap_reply(struct btd_device *device)
+{
+	struct btd_adapter *adapter = device_get_adapter(device);
+
+	btd_adapter_io_capa_request_reply(adapter, device);
+}
+
+int btd_event_request_io_cap(bdaddr_t *local, bdaddr_t *remote)
 {
 	struct btd_adapter *adapter;
 	struct btd_device *device;
 	struct agent *agent = NULL;
 	uint8_t agent_cap;
 	int err;
+	uint8_t cap, auth;
 
 	if (!get_adapter_and_device(local, remote, &adapter, &device, TRUE))
 		return -ENODEV;
 
-	err = btd_adapter_get_auth_info(adapter, remote, auth);
+	err = btd_adapter_get_auth_info(adapter, remote, &auth);
 	if (err < 0)
 		return err;
 
-	DBG("initial authentication requirement is 0x%02x", *auth);
+	DBG("initial authentication requirement is 0x%02x", auth);
 
-	if (*auth == 0xff)
-		*auth = device_get_auth(device);
+	if (auth == 0xff)
+		auth = device_get_auth(device);
 
 	/* Check if the adapter is not pairable and if there isn't a bonding
 	 * in progress */
@@ -752,11 +761,11 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
 		if (device_get_auth(device) < 0x02) {
 			DBG("Allowing no bonding in non-bondable mode");
 			/* No input, no output */
-			*cap = 0x03;
+			cap = 0x03;
 			/* Kernel defaults to general bonding and so
 			 * overwrite for this special case. Otherwise
 			 * non-pairable test cases will fail. */
-			*auth = 0x00;
+			auth = 0x00;
 			goto done;
 		}
 		return -EPERM;
@@ -772,13 +781,13 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
 		}
 
 		/* No agent available, and no bonding case */
-		if (*auth == 0x00 || *auth == 0x04) {
+		if (auth == 0x00 || auth == 0x04) {
 			DBG("Allowing no bonding without agent");
 			/* No input, no output */
-			*cap = 0x03;
+			cap = 0x03;
 			/* If kernel defaults to general bonding, set it
 			 * back to no bonding */
-			*auth = 0x00;
+			auth = 0x00;
 			goto done;
 		}
 
@@ -788,7 +797,7 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
 
 	agent_cap = agent_get_io_capability(agent);
 
-	if (*auth == 0x00 || *auth == 0x04) {
+	if (auth == 0x00 || auth == 0x04) {
 		/* If remote requests dedicated bonding follow that lead */
 		if (device_get_auth(device) == 0x02 ||
 				device_get_auth(device) == 0x03) {
@@ -797,9 +806,9 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
 			 * then require it, otherwise don't */
 			if (device_get_cap(device) == 0x03 ||
 							agent_cap == 0x03)
-				*auth = 0x02;
+				auth = 0x02;
 			else
-				*auth = 0x03;
+				auth = 0x03;
 		}
 
 		/* If remote indicates no bonding then follow that. This
@@ -807,7 +816,7 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
 		 * as default. */
 		if (device_get_auth(device) == 0x00 ||
 					device_get_auth(device) == 0x01)
-			*auth = 0x00;
+			auth = 0x00;
 
 		/* If remote requires MITM then also require it, unless
 		 * our IO capability is NoInputNoOutput (so some
@@ -815,13 +824,19 @@ int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
 		if (device_get_auth(device) != 0xff &&
 					(device_get_auth(device) & 0x01) &&
 					agent_cap != 0x03)
-			*auth |= 0x01;
+			auth |= 0x01;
 	}
 
-	*cap = agent_get_io_capability(agent);
+	cap = agent_get_io_capability(agent);
 
 done:
-	DBG("final authentication requirement is 0x%02x", *auth);
+	DBG("final authentication requirement is 0x%02x", auth);
+
+	device_set_local_auth_cap(device, auth, cap);
+
+	/* If failed to request remote OOB data then reply immediately. */
+	if (!device_request_oob_data(device, btd_event_io_cap_reply))
+		btd_event_io_cap_reply(device);
 
 	return 0;
 }
diff --git a/src/event.h b/src/event.h
index 4321949..5c122ea 100644
--- a/src/event.h
+++ b/src/event.h
@@ -35,8 +35,7 @@ void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t
 void btd_event_setscan_enable_complete(bdaddr_t *local);
 void btd_event_le_set_scan_enable_complete(bdaddr_t *local, uint8_t status);
 void btd_event_returned_link_key(bdaddr_t *local, bdaddr_t *peer);
-int btd_event_get_io_cap(bdaddr_t *local, bdaddr_t *remote,
-						uint8_t *cap, uint8_t *auth);
+int btd_event_request_io_cap(bdaddr_t *local, bdaddr_t *remote);
 int btd_event_set_io_cap(bdaddr_t *local, bdaddr_t *remote,
 						uint8_t cap, uint8_t auth);
 int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
diff --git a/src/oob.c b/src/oob.c
new file mode 100644
index 0000000..3b9714c
--- /dev/null
+++ b/src/oob.c
@@ -0,0 +1,67 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010  ST-Ericsson SA
+ *
+ *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ *  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 <glib.h>
+#include "manager.h"
+#include "adapter.h"
+#include "oob.h"
+
+static struct oob_plugin *active_plugin = NULL;
+
+void oob_activate_plugin(struct oob_plugin *plugin)
+{
+	if (!plugin)
+		return;
+
+	if (!plugin->local_data_read || !plugin->plugin_deactivated ||
+			!plugin->request_remote_data)
+		return;
+
+	if (active_plugin == plugin)
+		return;
+
+	if (active_plugin)
+		active_plugin->plugin_deactivated();
+
+	active_plugin = plugin;
+}
+
+void oob_deactivate_plugin(struct oob_plugin *plugin)
+{
+	if (active_plugin == plugin)
+		active_plugin = NULL;
+}
+
+gboolean oob_request_remote_data(struct btd_device *device)
+{
+	return active_plugin && active_plugin->request_remote_data(device);
+}
+
+void oob_local_data_read(bdaddr_t *ba, uint8_t *hash, uint8_t *randomizer)
+{
+	if (active_plugin)
+		active_plugin->local_data_read(manager_find_adapter(ba), hash,
+								randomizer);
+}
diff --git a/src/oob.h b/src/oob.h
new file mode 100644
index 0000000..db678de
--- /dev/null
+++ b/src/oob.h
@@ -0,0 +1,47 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010  ST-Ericsson SA
+ *
+ *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
+ *
+ *
+ *  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
+ *
+ */
+
+struct oob_plugin
+{
+	/* If request was successfully send this functions should return TRUE.
+	 * Function should not block for too long. */
+	gboolean (*request_remote_data)(struct btd_device *device);
+
+	/* New local OOB data was read. If corresponding HCI command failed,
+	 * hash and randomizer are NULL */
+	void (*local_data_read)(struct btd_adapter *adapter, uint8_t *hash,
+			uint8_t *randomizer);
+
+	/* Plug-in was deactivated (called only for active plug-in). */
+	void (*plugin_deactivated)(void);
+};
+
+/* These functions are called by OOB plug-in. */
+void oob_activate_plugin(struct oob_plugin *plugin);
+void oob_deactivate_plugin(struct oob_plugin *plugin);
+
+/* These functions are called from stack to interact with OOB plug-in. */
+gboolean oob_request_remote_data(struct btd_device *device);
+void oob_local_data_read(bdaddr_t *ba, uint8_t *hash, uint8_t *randomizer);
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 0/7] Support for out of band association model
From: Szymon Janc @ 2010-11-23 10:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Changes in this version:
  - code style/flow comments from Johan included
  - changes in D-Bus OOB api - ReadLocalOobData and provider
    register/unregister moved to adapter path (OobManager interface), provider
    is registered per adapter now
  - some bug fixes

Some things I'd like to collect comments about:
  - OobManager interface could be only available on 2.1 or higher adapters
    (this would require some adapter interface to be able check this in
    dbusoob plugin)
  - Agent's RequestPairing method name
  - RequestPairing is called only on device accepting incoming connection when
    it has OOB data for remote device (on RequestRemoteOobData event).
    Consequence is that when only initiator has OOB data RequestPairing is not
    called. We could store initiator's OOB capability in device structure (now
    only auth and cap are stored) to be able to know if initiator has OOB data.
    Yet, in such case RequestRemoteOobData on accepting device will not be 
    called and I have no idea where/when OOB capability should be check to call
    RequestPairing (and reject pairing if necessary)..


Comments are welcome.

BR,
Szymon Janc
on behalf of ST-Ericsson


Szymon Janc (7):
  Add support for Out of Band (OOB) association model
  Add D-Bus OOB plugin
  Add D-Bus OOB API documentation
  Add simple-oobprovider for testing
  Add request for accepting incoming pairing requests with OOB
    mechanism
  Update D-Bus OOB API with RequestPairing method
  Add RequestPairing method in simple-agent for accepting incoming OOB 
       pairing requests

 Makefile.am             |   10 +-
 acinclude.m4            |    6 +
 doc/oob-api.txt         |   76 +++++++++
 doc/oob-api.txt.orig    |   79 +++++++++
 lib/hci.h               |    3 +
 plugins/dbusoob.c       |  412 +++++++++++++++++++++++++++++++++++++++++++++++
 plugins/hciops.c        |  107 +++++++++++--
 src/adapter.c           |   21 +++-
 src/adapter.h           |   10 ++
 src/agent.c             |   59 +++++++-
 src/agent.h             |    3 +
 src/device.c            |   96 +++++++++++
 src/device.h            |   13 ++
 src/event.c             |   89 ++++++++---
 src/event.h             |    4 +-
 src/oob.c               |   67 ++++++++
 src/oob.h               |   47 ++++++
 test/simple-agent       |   10 ++
 test/simple-oobprovider |   57 +++++++
 19 files changed, 1131 insertions(+), 38 deletions(-)
 create mode 100644 doc/oob-api.txt
 create mode 100644 doc/oob-api.txt.orig
 create mode 100644 plugins/dbusoob.c
 create mode 100644 src/oob.c
 create mode 100644 src/oob.h
 create mode 100755 test/simple-oobprovider


^ permalink raw reply

* [PATCH] hciattach: makes set_speed return error if any one operation fail
From: Suraj Sumangala @ 2010-11-23 10:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jothikumar.Mothilal, Suraj Sumangala

This patch lets set_speed function changing UART baud rate
to return an error code if any one operation fails
instead of returning only the last operation's status.

---
 tools/hciattach.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/tools/hciattach.c b/tools/hciattach.c
index fd53710..7cb8e9e 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -144,9 +144,16 @@ static int uart_speed(int s)
 
 int set_speed(int fd, struct termios *ti, int speed)
 {
-	cfsetospeed(ti, uart_speed(speed));
-	cfsetispeed(ti, uart_speed(speed));
-	return tcsetattr(fd, TCSANOW, ti);
+	if (cfsetospeed(ti, uart_speed(speed)) < 0)
+		return -errno;
+
+	if (cfsetispeed(ti, uart_speed(speed)) < 0)
+		return -errno;
+
+	if (tcsetattr(fd, TCSANOW, ti) < 0)
+		return -errno;
+
+	return 0;
 }
 
 /*
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] hciattach: download configuration at maximum baud rate possible
From: Johan Hedberg @ 2010-11-23 10:15 UTC (permalink / raw)
  To: Suraj Sumangala; +Cc: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <4CEB9296.2060702@Atheros.com>

Hi Suraj,

On Tue, Nov 23, 2010, Suraj Sumangala wrote:
> The set_speed function is defined in hciattach.c as
> 
> int set_speed(...)
> {
> 	cfsetospeed(...);
> 	cfsetispeed(...);
> 	return tcsetattr(...);
> }
> 
> I think this function could end up returning Success even if the
> first two function calls failed?

Seems so, yes.

> Does it makes sense to rewrite it to
> 
> int set_speed(...)
> {
> 	if(cfsetospeed(...) < 0)
> 		return -errno;
> 	if(cfsetispeed(...) < 0)
> 		return -errno;

This looks fine, except for the coding style: space between if and (

> 	return tcsetattr(...);

I guess this should be a similar if statement as for the other two
calls, and then a final "return 0" at the end of the function. This
set_speed fix should be in a separate patch though.

Johan

^ permalink raw reply

* Re: [PATCH] hciattach: download configuration at maximum baud rate possible
From: Suraj Sumangala @ 2010-11-23 10:08 UTC (permalink / raw)
  To: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <20101123092346.GB28017@jh-x301>

Hi Johan,

On 11/23/2010 2:53 PM, Johan Hedberg wrote:
> In general the patch looks ok'ish, but:
>
>> >  +	if (set_speed(fd, ti, speed)<  0) {
>> >  +		perror("Can't set required baud rate");
>> >  +		return -1;
>> >  +	}
> To be consistent with the other return values, instead of -1 you should
> be returning a proper errno here. I.e. probably something like:
>
> 	if (set_speed(fd, ti, speed)<  0) {
> 		err = -errno;
> 		perror("Can't set required baud rate");
> 		return err;

The set_speed function is defined in hciattach.c as

int set_speed(...)
{
	cfsetospeed(...);
	cfsetispeed(...);
	return tcsetattr(...);
}

I think this function could end up returning Success even if the first 
two function calls failed?

Does it makes sense to rewrite it to

int set_speed(...)
{
	if(cfsetospeed(...) < 0)
		return -errno;
	if(cfsetispeed(...) < 0)
		return -errno;
	return tcsetattr(...);
}

Then, I can return the error code directly in my function call.

Regards
Suraj
	

^ permalink raw reply

* Re: [PATCH] hciattach: download configuration at maximum baud rate possible
From: Johan Hedberg @ 2010-11-23  9:23 UTC (permalink / raw)
  To: Suraj Sumangala; +Cc: linux-bluetooth, Jothikumar.Mothilal
In-Reply-To: <1290423480-29840-1-git-send-email-suraj@atheros.com>

Hi Suraj,

On Mon, Nov 22, 2010, Suraj Sumangala wrote:
> This patch support downloading configuration files for
> Atheros AR300x HCI UART chip at user requested baud rate
> instead of the initial baud rate.
> ---
>  tools/hciattach.c       |    2 +-
>  tools/hciattach.h       |    3 +-
>  tools/hciattach_ath3k.c |   97 +++++++++++++++++++++++++++++++++-------------
>  3 files changed, 72 insertions(+), 30 deletions(-)

In general the patch looks ok'ish, but:

> +	if (set_speed(fd, ti, speed) < 0) {
> +		perror("Can't set required baud rate");
> +		return -1;
> +	}

To be consistent with the other return values, instead of -1 you should
be returning a proper errno here. I.e. probably something like:

	if (set_speed(fd, ti, speed) < 0) {
		err = -errno;
		perror("Can't set required baud rate");
		return err;
	}


> +exit:

Could you use a label name that's more consistent with the rest of the
BlueZ code base. I think "failed" would be the most suitable one here.

Johan

^ permalink raw reply

* Re: [PATCH] Add a runtime option to set the BCSP communication rate
From: Johan Hedberg @ 2010-11-23  9:13 UTC (permalink / raw)
  To: Wade Brown; +Cc: linux-bluetooth
In-Reply-To: <1290466992-5023-1-git-send-email-brownw@us.panasonic.com>

Hi Wade,

On Mon, Nov 22, 2010, Wade Brown wrote:
> ---
>  tools/bccmd.c    |   45 ++++++++++++++++++++++++++++++++++++++++-----
>  tools/csr.h      |    3 ++-
>  tools/csr_bcsp.c |    4 ++--
>  3 files changed, 44 insertions(+), 8 deletions(-)

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* How to change the waiting time when building bluetooth connection
From: Roc Bai @ 2010-11-23  8:06 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth

2010/11/22 Gustavo F. Padovan <padovan@profusion.mobi>:
> Hi Roc,
>
> * Roc Bai <buroc83@gmail.com> [2010-11-22 11:13:27 +0800]:
>
>> Hi, All:
>>  When i pair my phone with the PC, i have to quickly input the PIN code
>> with the linux-2.6.35.1 kernel. But i can do it slowly with linux-2.6.26
>> kernel. All the application and library are same. So i think the waiting
>> timeout is changed, but i cann't find the changement. I hope get your help
>> on the issue. Thanks very much!
>>
>> My hcid version is 3.36.
>
> Please move to the latest bluez 4 version and then report it again if it
> is the case.

The same phenomenon. But one strange result, some phone can connect
normally, but some phone should input PIN quickly.  But those phones
can work in the old kernel. I think some phones have special
parameters and the changement of new kernel are sensitive with them.
More idea ?
>
> --
> Gustavo F. Padovan
> http://profusion.mobi
>



-- 
------------------------

Thinking before action, but you are wasting time if you don't do action.

^ permalink raw reply

* sdptool hanging remote
From: Grahame Jordan @ 2010-11-23  5:37 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

I am using bluez-4.77 on a Gumstix Verdex kernel 2.4.32 patch 21

When I run:
sdptool records 00:80:37:2F:06:08"
from the Workstation Ubuntu 10.04 Bluez-4.6? to the Gumstix the Gumstix 
hangs.
It does not hang completely but is very busy. It hangs for about 20 
seconds and then releases for about 1 second
before it locks up again.

I have tried this on several different Gumstix with the same issue.

Changing workstations from Ubuntu 10.04 to Ubuntu 8.04 does make a 
difference.
 From Ubuntu 8.04 there seems to be no problem. blue-utils 3.26?

Appreciate help


Thanks

Grahame Jordan

^ permalink raw reply

* Re: [PATCH] Fix managing dbus filters depending on BT state
From: Bartosz Szatkowski @ 2010-11-22 23:17 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <AANLkTin5t-=bMeBmAJ2A+hV4h=dXQeu5dNFbMby43ssS@mail.gmail.com>

On Mon, Nov 22, 2010 at 8:12 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi,
>
> On Mon, Nov 22, 2010 at 4:33 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> Hi Bartosz,
>>
>> On Mon, Nov 22, 2010, Bartosz Szatkowski wrote:
>>> Previously even if BT was disabled, bluetoothd would handle some dbus
>>> singals (mostly connected with HFP). Now filters are added when
>>> BT is enabled and removed when BT is disabled.
>>> ---
>>>  audio/manager.c          |    4 ++--
>>>  audio/telephony-dummy.c  |   10 ++++++++++
>>>  audio/telephony-maemo5.c |   10 ++++++++++
>>>  audio/telephony-maemo6.c |   10 ++++++++++
>>>  audio/telephony-ofono.c  |   10 ++++++++++
>>>  audio/telephony.h        |    1 +
>>>  src/adapter.c            |    5 +++++
>>>  7 files changed, 48 insertions(+), 2 deletions(-)
>>
>> Nack on this one. I understand the issue you're trying to fix but it
>> needs to be done differently.
>>
>>> diff --git a/audio/manager.c b/audio/manager.c
>>> index 816c807..2fc7bf1 100644
>>> --- a/audio/manager.c
>>> +++ b/audio/manager.c
>>> @@ -1178,7 +1178,7 @@ proceed:
>>>               btd_register_adapter_driver(&media_server_driver);
>>>
>>>       if (enabled.headset) {
>>> -             telephony_init();
>>> +             telephony_set_state(1);
>>>               btd_register_adapter_driver(&headset_server_driver);
>>>       }
>>
>> If you're gonna call this "state" you should have proper defines or
>> enums for the values, however in this case it's essentially a boolean so
>> that's not necessary. In fact since it's a boolean you don't even need
>> to have any new function or variable at all for it: just use
>> telephony_init and telephony_exit.
>>
>>> --- a/src/adapter.c
>>> +++ b/src/adapter.c
>>> @@ -57,6 +57,7 @@
>>>  #include "glib-helper.h"
>>>  #include "agent.h"
>>>  #include "storage.h"
>>> +#include "../audio/telephony.h"
>>>
>>>  #define IO_CAPABILITY_DISPLAYONLY    0x00
>>>  #define IO_CAPABILITY_DISPLAYYESNO   0x01
>>> @@ -2404,6 +2405,8 @@ int adapter_start(struct btd_adapter *adapter)
>>>
>>>       err = adapter_up(adapter, mode);
>>>
>>> +     telephony_init();
>>> +
>>
>> This is just wrong. The core daemon should never have direct access to
>> the telephony driver. Instead, you should have the audio plugin
>> (probably audio/manager.c or audio/headset.c) register a adapter powered
>> callback and then call telehony_init/exit from that callback.
>
> I have an almost working version of this using adapter drivers and
> powered changes via callback registration, the tricky part here is how
> to detect when to do headset_init/headset_exit since those should be
> called only once. I didn't know there somebody working on this but
> anyway I gonna try to finish this asap.
>
> --
> Luiz Augusto von Dentz
> Computer Engineer
>

Hi Luiz,
please fell free to send it (no hard fillings :) ) Ive just getting to
know bluez so probably it would take me a while to get through whole
plugin/callback subsystem.

-- 
Pozdrowienia,
Bartosz Szatkowski

^ permalink raw reply

* [PATCH] Add a runtime option to set the BCSP communication rate
From: Wade Brown @ 2010-11-22 23:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Wade Brown

---
 tools/bccmd.c    |   45 ++++++++++++++++++++++++++++++++++++++++-----
 tools/csr.h      |    3 ++-
 tools/csr_bcsp.c |    4 ++--
 3 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/tools/bccmd.c b/tools/bccmd.c
index 686e858..5cb9255 100644
--- a/tools/bccmd.c
+++ b/tools/bccmd.c
@@ -59,7 +59,7 @@
 #define CSR_TYPE_ARRAY		CSR_TYPE_COMPLEX
 #define CSR_TYPE_BDADDR		CSR_TYPE_COMPLEX
 
-static inline int transport_open(int transport, char *device)
+static inline int transport_open(int transport, char *device, speed_t bcsp_rate)
 {
 	switch (transport) {
 	case CSR_TRANSPORT_HCI:
@@ -69,7 +69,7 @@ static inline int transport_open(int transport, char *device)
 		return csr_open_usb(device);
 #endif
 	case CSR_TRANSPORT_BCSP:
-		return csr_open_bcsp(device);
+		return csr_open_bcsp(device, bcsp_rate);
 	case CSR_TRANSPORT_H4:
 		return csr_open_h4(device);
 	case CSR_TRANSPORT_3WIRE:
@@ -1109,6 +1109,7 @@ static void usage(void)
 	printf("Options:\n"
 		"\t-t <transport>     Select the transport\n"
 		"\t-d <device>        Select the device\n"
+		"\t-b <bcsp rate>     Select the bcsp transfer rate\n"
 		"\t-h, --help         Display help\n"
 		"\n");
 
@@ -1137,6 +1138,7 @@ static void usage(void)
 static struct option main_options[] = {
 	{ "transport",	1, 0, 't' },
 	{ "device",	1, 0, 'd' },
+	{ "bcsprate", 1, 0, 'b'},
 	{ "help",	0, 0, 'h' },
 	{ 0, 0, 0, 0 }
 };
@@ -1145,8 +1147,9 @@ int main(int argc, char *argv[])
 {
 	char *device = NULL;
 	int i, err, opt, transport = CSR_TRANSPORT_HCI;
+	speed_t bcsp_rate = B38400;
 
-	while ((opt=getopt_long(argc, argv, "+t:d:i:h", main_options, NULL)) != EOF) {
+	while ((opt=getopt_long(argc, argv, "+t:d:i:b:h", main_options, NULL)) != EOF) {
 		switch (opt) {
 		case 't':
 			if (!strcasecmp(optarg, "hci"))
@@ -1171,7 +1174,39 @@ int main(int argc, char *argv[])
 		case 'i':
 			device = strdup(optarg);
 			break;
-
+		case 'b':
+			switch (atoi(optarg)) {
+			case 9600: bcsp_rate = B9600; break;
+			case 19200: bcsp_rate = B19200; break;
+			case 38400: bcsp_rate = B38400; break;
+			case 57600: bcsp_rate = B57600; break;
+			case 115200: bcsp_rate = B115200; break;
+			case 230400: bcsp_rate = B230400; break;
+			case 460800: bcsp_rate = B460800; break;
+			case 500000: bcsp_rate = B500000; break;
+			case 576000: bcsp_rate = B576000; break;
+			case 921600: bcsp_rate = B921600; break;
+			case 1000000: bcsp_rate = B1000000; break;
+			case 1152000: bcsp_rate = B1152000; break;
+			case 1500000: bcsp_rate = B1500000; break;
+			case 2000000: bcsp_rate = B2000000; break;
+#ifdef B2500000
+			case 2500000: bcsp_rate = B2500000; break;
+#endif
+#ifdef B3000000
+			case 3000000: bcsp_rate = B3000000; break;
+#endif
+#ifdef B3500000
+			case 3500000: bcsp_rate = B3500000; break;
+#endif
+#ifdef B4000000
+			case 4000000: bcsp_rate = B4000000; break;
+#endif
+			default:
+				printf("Unknown BCSP baud rate specified, defaulting to 38400bps\n");
+				bcsp_rate = B38400;
+			}
+			break;
 		case 'h':
 		default:
 			usage();
@@ -1188,7 +1223,7 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
-	if (transport_open(transport, device) < 0)
+	if (transport_open(transport, device, bcsp_rate) < 0)
 		exit(1);
 
 	if (device)
diff --git a/tools/csr.h b/tools/csr.h
index 1d70491..8b94d7b 100644
--- a/tools/csr.h
+++ b/tools/csr.h
@@ -22,6 +22,7 @@
  */
 
 #include <stdint.h>
+#include <termios.h>
 
 #define CSR_VARID_PS_CLR_ALL			0x000b	/* valueless */
 #define CSR_VARID_PS_FACTORY_SET		0x000c	/* valueless */
@@ -519,7 +520,7 @@ int csr_read_usb(uint16_t varid, uint8_t *value, uint16_t length);
 int csr_write_usb(uint16_t varid, uint8_t *value, uint16_t length);
 void csr_close_usb(void);
 
-int csr_open_bcsp(char *device);
+int csr_open_bcsp(char *device, speed_t bcsp_rate);
 int csr_read_bcsp(uint16_t varid, uint8_t *value, uint16_t length);
 int csr_write_bcsp(uint16_t varid, uint8_t *value, uint16_t length);
 void csr_close_bcsp(void);
diff --git a/tools/csr_bcsp.c b/tools/csr_bcsp.c
index e551311..df247a2 100644
--- a/tools/csr_bcsp.c
+++ b/tools/csr_bcsp.c
@@ -46,7 +46,7 @@ static uint8_t send_buffer[512];
 static struct ubcsp_packet receive_packet;
 static uint8_t receive_buffer[512];
 
-int csr_open_bcsp(char *device)
+int csr_open_bcsp(char *device, speed_t bcsp_rate)
 {
 	struct termios ti;
 	uint8_t delay, activity = 0x00;
@@ -84,7 +84,7 @@ int csr_open_bcsp(char *device)
 	ti.c_cc[VMIN] = 1;
 	ti.c_cc[VTIME] = 0;
 
-	cfsetospeed(&ti, B38400);
+	cfsetospeed(&ti, bcsp_rate);
 
 	if (tcsetattr(fd, TCSANOW, &ti) < 0) {
 		fprintf(stderr, "Can't change port settings: %s (%d)\n",
-- 
1.7.2.2


^ permalink raw reply related

* Re: [PATCH] Fix typo in adapter documentation
From: Johan Hedberg @ 2010-11-22 22:07 UTC (permalink / raw)
  To: Jose Antonio Santos Cadenas; +Cc: linux-bluetooth
In-Reply-To: <1290452756-7967-1-git-send-email-santoscadenas@gmail.com>

Hi Jose,

On Mon, Nov 22, 2010, Jose Antonio Santos Cadenas wrote:
> ---
>  doc/adapter-api.txt |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
> index 65e2887..f287f29 100644
> --- a/doc/adapter-api.txt
> +++ b/doc/adapter-api.txt
> @@ -148,7 +148,7 @@ Methods		dict GetProperties()
>  
>  			This registers the adapter wide agent.
>  
> -			The object path defines the path the of the agent
> +			The object path defines the path of the agent
>  			that will be called when user input is needed.
>  
>  			If an application disconnects from the bus all

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* Re: pull request: bluetooth-2.6 2010-11-22
From: Johan Hedberg @ 2010-11-22 22:03 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: John W. Linville, linux-wireless, linux-bluetooth
In-Reply-To: <20101122201330.GE23109@vigoh>

Hi,

On Mon, Nov 22, 2010, Gustavo F. Padovan wrote:
> > The other fixes are larger than I would like to see.  What is the
> > effect of the bug?  Does the Bluetooth controller stop completely?
> > Does it cause a crash?
> > 
> > Is this a newly-introduced bug?  Or one that has been around for
> > a while?
> 
> No, it is not serious like that. By not having this patch we won't have
> the remote name request command during connection setup, The remote name
> request was done by bluetoothd, but we already removed it from
> userspace. It is not a really big problem once we also cache the remote
> devices names in bluetoothd.
> So I'm seeing no way to convince you tou pull this patch (actually I'm
> now also covinced to queue this to bluetooth-next).  I'll sent a new
> pull request soon, after wait some time for new patches.

IIRC the symptom that prompted the initial investigation was the failure
to properly connect to one specific Bluetooth headset. After discussions
with Marcel the conculsion was to move more control of these commands to
the kernel side. OTOH, this is certainly not the first time a BT
controller chokes up when receiving too many commands at the same time
(I've seen this several times during the last 8 years or so that I've
been involved with Bluetooth). Anyway, I agree that this might be better
suited for bluetooth-next.

Johan

^ permalink raw reply

* Re: [PATCH 2/2] Bluetooth: Automate remote name requests
From: Johan Hedberg @ 2010-11-22 21:51 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Arun K. Singh, linux-bluetooth
In-Reply-To: <AANLkTikHPWyjS+m2NMrxcL0FP6WhX+APExNELRuw4=Pe@mail.gmail.com>

Hi Luiz,

On Mon, Nov 22, 2010, Luiz Augusto von Dentz wrote:
> >> Could you be bit more explicit about such user space versions that you
> >> recommend? Would latest bluez versions such as 4.80 qualify for your
> >> recommendation?
> >
> > The automated name requests upon "connect complete" events were removed
> > in 4.78 so any version from there onwards would qualify.
> 
> Maybe there is some way to detect that the kernel is not doing it, or
> at least force bluetoothd to resolve once to make sure it can be used
> with older kernel versions so it doesn't have to always update as it
> was used to be but if we are to authenticate or authorize a device it
> should have a name so the ui can display it to the user.

Regarding the kernel version detection, this was certainly considered
but there doesn't seem to be any simple way to do it. However, now that
you mention it, this can certainly be an inconvenient issue with
incoming connections for devices which we've never seen during a device
discovery. Therefore, some kind of a userspace workaround for this would
imho be desirable and I'd certainly be willing to accept a patch for it
as long as it doesn't get too complicated. I suppose it's sufficient if
the patch would be for hciops only since any system running mgmtops
would also have a kernel that does the name request.

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