2010-11-23 10:53:05

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 0/7] Support for out of band association model

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



2010-11-30 21:26:36

by Mike Tsai

[permalink] [raw]
Subject: RE: [PATCHv4 0/7] Support for out of band association model

Hi Szymon,

Correction on my comments below,

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Mike Tsai
Sent: Tuesday, November 30, 2010 8:02 AM
To: Szymon Janc; [email protected]
Subject: RE: [PATCHv4 0/7] Support for out of band association model

Hi Szymon,

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Szymon Janc
Sent: Tuesday, November 23, 2010 2:53 AM
To: [email protected]
Cc: Szymon Janc
Subject: [PATCHv4 0/7] Support for out of band association model

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)..

[MTsai]7.7.44 Remote OOB Data Request Event.
If host has received remote peer's OOB data before pairing, the host shall set the "OOB present" flag of the peer device. This "OOB present" flag will be sent over the air as part of pairing process with lmp_ioCap_Req or lmp_iocap_rsp.
If either one of the devices have OOB data, then OOB shall be used to do the pairing.
The event "Remote OOB Data Request Event" shall be sent to host before calculating the commitment value.
The LM state machine shall call "device_request_oob_data" when either local or remote peer has "OOB data present". I think this part of the code is not present.

[Mtsai correction]
The local OOB data present is set when host send HCI command "Read Local OOB Data". And this "OOB data present" flag is sent over the air to peer device during pairing.

The LM state machine is inside the controller firmware, so there is no issue on the stack code you submitted.

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

2010-11-30 16:02:06

by Mike Tsai

[permalink] [raw]
Subject: RE: [PATCHv4 0/7] Support for out of band association model

Hi Szymon,

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Szymon Janc
Sent: Tuesday, November 23, 2010 2:53 AM
To: [email protected]
Cc: Szymon Janc
Subject: [PATCHv4 0/7] Support for out of band association model

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)..

[MTsai]7.7.44 Remote OOB Data Request Event.
If host has received remote peer's OOB data before pairing, the host shall set the "OOB present" flag of the peer device. This "OOB present" flag will be sent over the air as part of pairing process with lmp_ioCap_Req or lmp_iocap_rsp.
If either one of the devices have OOB data, then OOB shall be used to do the pairing.
The event "Remote OOB Data Request Event" shall be sent to host before calculating the commitment value.
The LM state machine shall call "device_request_oob_data" when either local or remote peer has "OOB data present". I think this part of the code is not present.

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

2010-11-23 11:05:19

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCHv4 6/7] Update D-Bus OOB API with RequestPairing method

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

2010-11-23 10:53:12

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 7/7] Add RequestPairing method in simple-agent for accepting incoming OOB pairing requests

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


2010-11-23 10:53:11

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 6/7] Update D-Bus OOB API with RequestPairing method

---
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 <[email protected]> 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


2010-11-23 10:53:10

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 5/7] Add request for accepting incoming pairing requests with OOB mechanism

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


2010-11-23 10:53:09

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 4/7] Add simple-oobprovider for testing

---
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 <[email protected]> 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


2010-11-23 10:53:08

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 3/7] Add D-Bus OOB API documentation

---
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 <[email protected]> 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


2010-11-23 10:53:07

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 2/7] Add D-Bus OOB plugin

---
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 <[email protected]> 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


2010-11-23 10:53:06

by Szymon Janc

[permalink] [raw]
Subject: [PATCHv4 1/7] Add support for Out of Band (OOB) association model

---
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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]> 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 <[email protected]> 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


2010-12-06 09:46:09

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCHv4 0/7] Support for out of band association model

Hi,

> [Mtsai correction]
> The local OOB data present is set when host send HCI command "Read Local OOB
> Data". And this "OOB data present" flag is sent over the air to peer device
> during pairing.

I think you confused local and remote OOB data.
This flag is about "OOB authentication data from remote device present".
Please see Vol.2 Part E. 7.1.29 "IO Capability Request Reply Command".

--
Szymon Janc
on behalf of ST-Ericsson