* [PATCH v1 2/4] adapter: Use authorization id for cancelling
From: Mikel Astiz @ 2012-09-24 15:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348501338-29639-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Return a request id in btd_request_authorization() in order to be used
when the request needs to be cancelled. This id alone will be enough to
use btd_cancel_authorization().
---
audio/device.c | 12 ++++++++--
plugins/service.c | 18 ++++++++++------
profiles/input/server.c | 2 +-
src/adapter.c | 51 +++++++++++++++++++++++++++++-----------------
src/adapter.h | 2 +-
5 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/audio/device.c b/audio/device.c
index 99d6512..454bbb9 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -83,6 +83,7 @@ struct dev_priv {
sink_state_t sink_state;
avctp_state_t avctp_state;
GSList *auths;
+ int auth_id;
DBusMessage *conn_req;
DBusMessage *dc_req;
@@ -737,6 +738,8 @@ static void auth_cb(DBusError *derr, void *user_data)
struct audio_device *dev = user_data;
struct dev_priv *priv = dev->priv;
+ priv->auth_id = 0;
+
if (derr == NULL)
priv->authorized = TRUE;
@@ -820,7 +823,8 @@ int audio_device_request_authorization(struct audio_device *dev,
if (err < 0) {
priv->auths = g_slist_remove(priv->auths, auth);
g_free(auth);
- }
+ } else
+ priv->auth_id = err;
return err;
}
@@ -850,8 +854,10 @@ int audio_device_cancel_authorization(struct audio_device *dev,
if (priv->auth_idle_id > 0) {
g_source_remove(priv->auth_idle_id);
priv->auth_idle_id = 0;
- } else
- btd_cancel_authorization(&dev->src, &dev->dst);
+ } else {
+ btd_cancel_authorization(priv->auth_id);
+ priv->auth_id = 0;
+ }
}
return 0;
diff --git a/plugins/service.c b/plugins/service.c
index e02a673..fca559d 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -65,6 +65,7 @@ struct pending_auth {
char *sender;
bdaddr_t dst;
char uuid[MAX_LEN_UUID_STR];
+ int id;
};
struct service_adapter {
@@ -557,8 +558,9 @@ done:
else
bacpy(&src, BDADDR_ANY);
- btd_request_authorization(&src, &auth->dst,
- auth->uuid, auth_cb, serv_adapter);
+ auth->id = btd_request_authorization(&src, &auth->dst,
+ auth->uuid, auth_cb,
+ serv_adapter);
}
static DBusMessage *request_authorization(DBusConnection *conn,
@@ -633,8 +635,9 @@ static DBusMessage *request_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
- serv_adapter) < 0) {
+ auth->id = btd_request_authorization(&src, &auth->dst, auth->uuid,
+ auth_cb, serv_adapter);
+ if (auth->id < 0) {
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
auth);
g_free(auth);
@@ -664,7 +667,7 @@ static DBusMessage *cancel_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- btd_cancel_authorization(&src, &auth->dst);
+ btd_cancel_authorization(auth->id);
reply = btd_error_not_authorized(auth->msg);
dbus_message_unref(auth->msg);
@@ -683,8 +686,9 @@ static DBusMessage *cancel_authorization(DBusConnection *conn,
else
bacpy(&src, BDADDR_ANY);
- btd_request_authorization(&src, &auth->dst,
- auth->uuid, auth_cb, serv_adapter);
+ auth->id = btd_request_authorization(&src, &auth->dst,
+ auth->uuid, auth_cb,
+ serv_adapter);
done:
return dbus_message_new_method_return(msg);
diff --git a/profiles/input/server.c b/profiles/input/server.c
index 0464c4a..0385012 100644
--- a/profiles/input/server.c
+++ b/profiles/input/server.c
@@ -175,7 +175,7 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
ret = btd_request_authorization(&src, &dst, HID_UUID,
auth_callback, server);
- if (ret == 0)
+ if (ret >= 0)
return;
ba2str(&src, addr);
diff --git a/src/adapter.c b/src/adapter.c
index 366a99f..dcf58f2 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -85,6 +85,7 @@
#define OFF_TIMER 3
static GSList *adapter_drivers = NULL;
+static int service_auth_id = 0;
struct session_req {
struct btd_adapter *adapter;
@@ -97,6 +98,7 @@ struct session_req {
};
struct service_auth {
+ int id;
service_auth_cb cb;
void *user_data;
struct btd_device *device;
@@ -3205,6 +3207,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->user_data = user_data;
auth->device = device;
auth->adapter = adapter;
+ auth->id = service_auth_id++;
if (device_is_trusted(device) == TRUE) {
adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
@@ -3229,7 +3232,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
done:
adapter->auth = auth;
- return 0;
+ return auth->id;
}
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
@@ -3248,49 +3251,59 @@ int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
}
for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
- int err;
+ int auth_id;
adapter = l->data;
- err = adapter_authorize(adapter, dst, uuid, cb, user_data);
- if (err == 0)
- return 0;
+ auth_id = adapter_authorize(adapter, dst, uuid, cb, user_data);
+ if (auth_id >= 0)
+ return auth_id;
}
return -EPERM;
}
-int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
+static struct btd_adapter *find_authorization(int auth_id)
{
- struct btd_adapter *adapter = manager_find_adapter(src);
- struct btd_device *device;
+ GSList *l;
+
+ for (l = manager_get_adapters(); l != NULL; l = g_slist_next(l)) {
+ struct btd_adapter *adapter = l->data;
+
+ if (adapter->auth == NULL)
+ continue;
+
+ if (adapter->auth->id == auth_id)
+ return adapter;
+ }
+
+ return NULL;
+}
+
+int btd_cancel_authorization(int auth_id)
+{
+ struct btd_adapter *adapter;
struct agent *agent;
- char address[18];
int err;
- if (!adapter)
- return -EPERM;
-
- ba2str(dst, address);
- device = adapter_find_device(adapter, address);
- if (!device)
+ adapter = find_authorization(auth_id);
+ if (adapter == NULL)
return -EPERM;
if (adapter->auth_idle_id) {
g_source_remove(adapter->auth_idle_id);
adapter->auth_idle_id = 0;
+ g_free(adapter->auth);
+ adapter->auth = NULL;
return 0;
}
- if (!adapter->auth || adapter->auth->device != device)
- return -EPERM;
-
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.
*/
- agent = device_get_agent(device);
+ agent = device_get_agent(adapter->auth->device);
if (!agent)
return -EPERM;
diff --git a/src/adapter.h b/src/adapter.h
index eece6f5..2bdd912 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -149,7 +149,7 @@ int btd_register_adapter_driver(struct btd_adapter_driver *driver);
void btd_unregister_adapter_driver(struct btd_adapter_driver *driver);
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
const char *uuid, service_auth_cb cb, void *user_data);
-int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst);
+int btd_cancel_authorization(int auth_id);
const char *adapter_any_get_path(void);
--
1.7.7.6
^ permalink raw reply related
* [PATCH v1 1/4] adapter: Replace device authorizing flag
From: Mikel Astiz @ 2012-09-24 15:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
In-Reply-To: <1348501338-29639-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Refactor code to drop the device authorizing flag by replacing it with a
private authorization pointer in btd_adapter. After all, no more than
one authorization can be ongoing, so the code is easier to follow if
this is made explicit.
---
src/adapter.c | 55 +++++++++++++++++++++++++++++++++++++------------------
src/device.c | 11 -----------
src/device.h | 2 --
3 files changed, 37 insertions(+), 31 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index f9acbd5..366a99f 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -127,7 +127,8 @@ struct btd_adapter {
GSList *found_devices;
GSList *oor_devices; /* out of range device list */
struct agent *agent; /* For the new API */
- guint auth_idle_id; /* Ongoing authorization */
+ guint auth_idle_id; /* Ongoing authorization (trusted) */
+ struct service_auth *auth; /* Ongoing authorization */
GSList *connections; /* Connected devices */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
@@ -967,8 +968,11 @@ void adapter_remove_device(struct btd_adapter *adapter,
agent = device_get_agent(device);
- if (agent && device_is_authorizing(device))
+ if (agent && adapter->auth && adapter->auth->device == device) {
+ g_free(adapter->auth);
+ adapter->auth = NULL;
agent_cancel(agent);
+ }
device_remove(device, remove_storage);
}
@@ -2408,6 +2412,9 @@ static void adapter_free(gpointer user_data)
if (adapter->auth_idle_id)
g_source_remove(adapter->auth_idle_id);
+ if (adapter->auth)
+ g_free(adapter->auth);
+
if (adapter->off_timer)
off_timer_remove(adapter);
@@ -3142,22 +3149,28 @@ void btd_unregister_adapter_driver(struct btd_adapter_driver *driver)
static void agent_auth_cb(struct agent *agent, DBusError *derr,
void *user_data)
{
- struct service_auth *auth = user_data;
+ struct btd_adapter *adapter = user_data;
+ struct service_auth *auth = adapter->auth;
- device_set_authorizing(auth->device, FALSE);
+ adapter->auth = NULL;
auth->cb(derr, auth->user_data);
+
+ g_free(auth);
}
static gboolean auth_idle_cb(gpointer user_data)
{
- struct service_auth *auth = user_data;
- struct btd_adapter *adapter = auth->adapter;
+ struct btd_adapter *adapter = user_data;
+ struct service_auth *auth = adapter->auth;
+ adapter->auth = NULL;
adapter->auth_idle_id = 0;
auth->cb(NULL, auth->user_data);
+ g_free(auth);
+
return FALSE;
}
@@ -3181,7 +3194,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
if (!g_slist_find(adapter->connections, device))
error("Authorization request for non-connected device!?");
- if (adapter->auth_idle_id)
+ if (adapter->auth != NULL)
return -EBUSY;
auth = g_try_new0(struct service_auth, 1);
@@ -3194,10 +3207,8 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
auth->adapter = adapter;
if (device_is_trusted(device) == TRUE) {
- adapter->auth_idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
- auth_idle_cb, auth,
- g_free);
- return 0;
+ adapter->auth_idle_id = g_idle_add(auth_idle_cb, adapter);
+ goto done;
}
agent = device_get_agent(device);
@@ -3209,13 +3220,16 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst,
dev_path = device_get_path(device);
- err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, auth, g_free);
- if (err < 0)
+ err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, adapter,
+ NULL);
+ if (err < 0) {
g_free(auth);
- else
- device_set_authorizing(device, TRUE);
+ return err;
+ }
- return err;
+done:
+ adapter->auth = auth;
+ return 0;
}
int btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst,
@@ -3268,6 +3282,9 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
return 0;
}
+ if (!adapter->auth || adapter->auth->device != device)
+ return -EPERM;
+
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.
@@ -3279,8 +3296,10 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
err = agent_cancel(agent);
- if (err == 0)
- device_set_authorizing(device, FALSE);
+ if (err == 0) {
+ g_free(adapter->auth);
+ adapter->auth = NULL;
+ }
return err;
}
diff --git a/src/device.c b/src/device.c
index aa3a607..a19e98d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -161,7 +161,6 @@ struct btd_device {
gboolean bonded;
gboolean auto_connect;
- gboolean authorizing;
gint ref;
GIOChannel *att_io;
@@ -2916,16 +2915,6 @@ gboolean device_is_authenticating(struct btd_device *device)
return (device->authr != NULL);
}
-gboolean device_is_authorizing(struct btd_device *device)
-{
- return device->authorizing;
-}
-
-void device_set_authorizing(struct btd_device *device, gboolean auth)
-{
- device->authorizing = auth;
-}
-
void device_register_services(struct btd_device *device,
GSList *prim_list, int psm)
{
diff --git a/src/device.h b/src/device.h
index aee6d13..b704a4c 100644
--- a/src/device.h
+++ b/src/device.h
@@ -98,8 +98,6 @@ int device_notify_pincode(struct btd_device *device, gboolean secure,
const char *pincode, void *cb);
void device_cancel_authentication(struct btd_device *device, gboolean aborted);
gboolean device_is_authenticating(struct btd_device *device);
-gboolean device_is_authorizing(struct btd_device *device);
-void device_set_authorizing(struct btd_device *device, gboolean auth);
void device_add_connection(struct btd_device *device);
void device_remove_connection(struct btd_device *device);
void device_request_disconnect(struct btd_device *device, DBusMessage *msg);
--
1.7.7.6
^ permalink raw reply related
* [PATCH v1 0/4] Audio profile authorization
From: Mikel Astiz @ 2012-09-24 15:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
v1 of this patchset includes the modifications suggested by Luiz, most significantly the removal of the authorization hashmap in favor of code simplicity.
Additionally, a bug in v0 has been fixed affecting adapter_remove_device().
>From original cover-letter:
The agent-based profile authorization makes a special consideration for audio profiles: they are processed as if they all belonged to one single profile. This includes several internal policies that are inconvenient for IVI use-cases.
This patchset removes this exception by making use of the conventional authorization mechanism also for audio profiles.
The new approach is not straightforward since devices might send several connection requets in parallel (i.e. HFP, A2DP, AVRCP). This cannot be neither automatically rejected (EBUSY) nor forwarded in parallel to the agent, so a queue was added to store the pending authorization requests. These will be sent to the agent sequentially.
Mikel Astiz (4):
adapter: Replace device authorizing flag
adapter: Use authorization id for cancelling
adapter: Queue parallel authorization requests
audio: Drop audio-specific authorization mechanism
audio/avctp.c | 29 +++----
audio/avdtp.c | 25 ++++--
audio/device.c | 144 -----------------------------------
audio/device.h | 12 +---
audio/manager.c | 18 +++--
plugins/service.c | 18 +++--
profiles/input/server.c | 2 +-
src/adapter.c | 194 ++++++++++++++++++++++++++++++----------------
src/adapter.h | 2 +-
src/device.c | 11 ---
src/device.h | 2 -
11 files changed, 179 insertions(+), 278 deletions(-)
--
1.7.7.6
^ permalink raw reply
* [PATCH v0] audio: Fix crash on gateway close
From: Mikel Astiz @ 2012-09-24 15:34 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
gateway_close() can be called multiple times and thus the code must
handle the case where device->gateway is already NULL.
This issue can be easily reproduced if a device is removed (unpaired)
while HFP gateway is connected.
---
audio/gateway.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/audio/gateway.c b/audio/gateway.c
index 45b25a1..93a70ba 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -566,6 +566,9 @@ int gateway_close(struct audio_device *device)
struct gateway *gw = device->gateway;
int sock;
+ if (gw == NULL)
+ return 0;
+
if (gw->rfcomm) {
sock = g_io_channel_unix_get_fd(gw->rfcomm);
shutdown(sock, SHUT_RDWR);
--
1.7.7.6
^ permalink raw reply related
* Re: LE thermometer on Ubuntu 12.10
From: Anderson Lizardo @ 2012-09-24 15:11 UTC (permalink / raw)
To: jonsmirl@gmail.com; +Cc: linux-bluetooth
In-Reply-To: <CAKON4OwW4_4KoseeQqa4_JW5nY0UCLdSAZzU36RrOAtuiA151g@mail.gmail.com>
Hi Jon,
On Mon, Sep 24, 2012 at 8:55 AM, jonsmirl@gmail.com <jonsmirl@gmail.com> wrote:
> Ubuntu 12.10 has 4.101 and kernel 3.5. I'm trying to get the sample
> CC2540 thermometer application from TI working. The 4.101 package
> build has --enable-thermometer set.
There is no "--enable-thermometer" since 4.100. Please enable GATT
with "--enable-gatt". This will enable all supported GATT profiles at
once.
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH v3 07/18] neard: Implement PushOOB function
From: Szymon Janc @ 2012-09-24 14:38 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <20120924090941.GA20042@x220>
On Monday 24 of September 2012 12:09:41 Johan Hedberg wrote:
> Hi Szymon,
Hi Johan,
> On Fri, Sep 21, 2012, Szymon Janc wrote:
> > +static struct btd_adapter *pending_adapter = NULL;
> > +static DBusMessage *pending_msg = NULL;
>
> I'm not really a fan of these global variables. Any chance of moving
> them to a non-global temporary context that gets passed around.
The idea is to keep this plugin simple so only one request at time is to be
supported. mgmt code doesn't allow to pass any 'key-like' data to identify
command<->event so this would require some general (?) solution.
I don't think this is needed.
Actually, pending_adapter might not be needed if it is guaranteed that default
adapter will not change before callback is called (I guess it is).
> In
> general I find it hard to get the big picture on the life-time of these
> variables as it seems you don't actually explicitly initiate the pairing
> process from your code but are relying on some external entity to do
> that? Or did I miss something? The whole thing just looks quite brittle
> right now.
pending_* pointers are used to store data until read local or pairing callback
is called. Pairing is initiate in PushOOB method (adapter_create_bonding is
called from process_eir).
But yeah, I guess I should have been more descriptive in cover letter. So here
is few words of overview.
Currently handover agent API consists of 2 methods RequestOOB and PushOOB.
PushOOB is used to provide data and start pairing if needed to prepare
alternative carrier (BT). From NFC side this corresponds to receiving Handover
Select frame.
RequestOOB is used to request local data from BT to pass them to remote. This
method also allows to pass remote oob data without triggering pairing (to be
used when remote starts it) - this will minimize number of D-Bus calls
needed. From NFC side this corresponds to receiving (pass remote data and
request local data) or sending (only request local data) Handover Request
frame.
Basically there are 3 possible scenarios:
- neard received Handover Select message (aka static handover):
neard calls PushOOB(data)
bluez pairs if needed and reply
- neard received Handover Request and needs to reply with Handover Select:
neard calls RequestOOB(data) and pass remote oob data received
bluez stores received data, reads local OOB data and reply to neard
neard sends HS frame based on bluez reply
[in that case remote is responsible to initialize pairing if needed]
- neard sends Handover Request and later receives Handover Select from remote:
neard calls RequestOOB(NULL)
bluez reads local OOB data and reply to neard
neard sends Handover Request base on bluez reply
neard receives Handover Select frame
neard calls PushOOB(data)
bluez pairs if needed and reply
Hope this clarify things a bit:)
> Johan
--
BR
Szymon Janc
^ permalink raw reply
* Re: [PATCH BlueZ v0] gatt: Exchange MTU needs to be executed first
From: Claudio Takahasi @ 2012-09-24 14:30 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1346963860-25094-1-git-send-email-claudio.takahasi@openbossa.org>
Hi Johan:
On Thu, Sep 6, 2012 at 5:37 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> According to Bluetooth SPEC the ATT Exchange MTU sub-procedure needs to
> be execute before any ATT command. This patch moves the Exchange MTU
> sub-procedure from GATT plugin to device ATTIO core.
> ---
>
> *** Apply after "LE General Connection Establishment procedure" patches
Please ignore this patch. Indications sent from the keyboard (during
the MTU sub-procedure) are being lost.
Regards,
Claudio
^ permalink raw reply
* Re: [RFC, PATCH] hid-ps3remote: handle multiple keypresses for joypad buttons
From: David Dillow @ 2012-09-24 13:56 UTC (permalink / raw)
To: Antonio Ospite
Cc: linux-bluetooth, David Herrmann, Luiz Augusto von Dentz,
Bastien Nocera, linux-input, jkosina
In-Reply-To: <1348485938-20510-1-git-send-email-ospite@studenti.unina.it>
On Mon, 2012-09-24 at 13:25 +0200, Antonio Ospite wrote:
> In order to make this work I have to put joypad buttons only in one of
> the key maps, I don't know if that is compatible with the Harmony
> adapter.
I suspect it is, but I'll try to test later tonight. Feel free to merge
my patch and yours and push it upstream under your name/copyright; I'm
not attached to it.
> diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
> index 11a6c1f..fa2e50d 100644
> --- a/drivers/hid/hid-ps3remote.c
> +++ b/drivers/hid/hid-ps3remote.c
> @@ -49,6 +49,26 @@
> * The keymap is generally ordered by the physical location of the buttons,
> * as this makes it easier to verify a correct mapping during testing.
> */
You'd have caught this in cleanup, I'm sure, but the above comment no
longer makes sense.
> +static const unsigned int ps3remote_keymap_1[] = {
Probably want a better name -- again, something I'm sure you would have
done during cleanup of this proof-of-concept.
> static const unsigned int ps3remote_keymap[] = {
This map probably should now be ordered per David H. since we're no
longer following the physical layout.
Thanks,
Dave
^ permalink raw reply
* LE thermometer on Ubuntu 12.10
From: jonsmirl @ 2012-09-24 12:55 UTC (permalink / raw)
To: linux-bluetooth
Ubuntu 12.10 has 4.101 and kernel 3.5. I'm trying to get the sample
CC2540 thermometer application from TI working. The 4.101 package
build has --enable-thermometer set.
I can see my TI device under dbus. It shows the expect four services
and sixteen characteristics.
I have EnableGatt = true in /etc/bluetooth/main.conf
The test script, test-thermometer, is looking for
org.bluez.Thermometer which isn't there. Using d-feet to browse dbus
confirms that it is not there.
Is this profile plugin not registered somehow? How can I query the LE
profiles supported by my Bluez installation?
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: [RFC, PATCH] hid-ps3remote: handle multiple keypresses for joypad buttons
From: Bastien Nocera @ 2012-09-24 11:32 UTC (permalink / raw)
To: Antonio Ospite
Cc: David Dillow, linux-bluetooth, David Herrmann,
Luiz Augusto von Dentz, linux-input, jkosina
In-Reply-To: <1348485938-20510-1-git-send-email-ospite@studenti.unina.it>
Em Mon, 2012-09-24 às 13:25 +0200, Antonio Ospite escreveu:
> + //[0x5c] = KEY_OPTION, /* options/triangle */
I don't think that C++ will be liked here.
Cheers
^ permalink raw reply
* Re: [RFC v0] device: Add DiscoveryComplete signal
From: Chen Ganir @ 2012-09-24 11:32 UTC (permalink / raw)
To: Mikel Astiz; +Cc: linux-bluetooth, Mikel Astiz
In-Reply-To: <1348485571-17397-1-git-send-email-mikel.astiz.oss@gmail.com>
Mikel,
On 09/24/2012 01:19 PM, Mikel Astiz wrote:
> From: Mikel Astiz <mikel.astiz@bmw-carit.de>
>
> The D-Bus API has to report when the UUID property has been fully
> populated, once the service discovery has been finished as part of the
> pairing process. This allows UIs to show the device only after its
> services are known, avoiding transitional states.
> ---
We have the PropertyChanged signal, which is triggered wach time the
search_cb is called (device.c). Why do you need to create a new signal,
instead of using this already existing event, and send PropertyChanged
on UUIDS with the peer device list of UUID's only when the list is
complete and not on every SDP record found ? This way, you can keep the
existing implementations working, and you can also add new functionality
based on the fact that you only receive one instance of this event ?
> We want to have a pairing UI that will let the user choose which profiles he wants to use with a specific device. We listen to DeviceCreated and then gather all device properties, but there is no way to know when the UUIDs have reached a stable state after the first discovery.
>
> doc/device-api.txt | 12 ++++++++++++
> src/device.c | 8 +++++++-
> 2 files changed, 19 insertions(+), 1 deletions(-)
>
> diff --git a/doc/device-api.txt b/doc/device-api.txt
> index 1f0dc96..1d64ac2 100644
> --- a/doc/device-api.txt
> +++ b/doc/device-api.txt
> @@ -82,6 +82,13 @@ Signals PropertyChanged(string name, variant value)
> disconnection to a remote device has been requested.
> The actual disconnection will happen 2 seconds later.
>
> + DiscoveryComplete()
> +
> + This signal will be sent when the service discovery
> + of a recently paired device has completed. This means
> + the UUIDs property has been populated with the
> + discovered remote services.
> +
> Properties string Address [readonly]
>
> The Bluetooth device address of the remote device.
> @@ -125,6 +132,11 @@ Properties string Address [readonly]
> List of 128-bit UUIDs that represents the available
> remote services.
>
> + Note that this value can change over time, specially
> + during the pairing process. See the above described
> + DiscoveryComplete signal in order to know when the
> + list has been populated with the discovered services.
> +
> array{object} Services [readonly]
>
> List of characteristics based services.
> diff --git a/src/device.c b/src/device.c
> index aa3a607..6bac826 100644
> --- a/src/device.c
> +++ b/src/device.c
> @@ -887,6 +887,7 @@ static const GDBusSignalTable device_signals[] = {
> { GDBUS_SIGNAL("PropertyChanged",
> GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
> { GDBUS_SIGNAL("DisconnectRequested", NULL) },
> + { GDBUS_SIGNAL("DiscoveryComplete", NULL) },
> { }
> };
>
> @@ -1649,8 +1650,13 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
> uuids_changed(req->device);
>
> send_reply:
> - if (!req->msg)
> + if (!req->msg) {
> + g_dbus_emit_signal(btd_get_dbus_connection(),
> + device->path,
> + DEVICE_INTERFACE, "DiscoveryComplete",
> + DBUS_TYPE_INVALID);
> goto cleanup;
> + }
>
> if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
> "DiscoverServices"))
>
--
BR,
Chen Ganir
^ permalink raw reply
* Re: [PATCH v3 05/18] oob: Allow to register pairing complete callback
From: Szymon Janc @ 2012-09-24 11:28 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <20120924090626.GB19184@x220>
On Monday 24 of September 2012 12:06:26 Johan Hedberg wrote:
> Hi Szymon,
Hi Johan,
> On Fri, Sep 21, 2012, Szymon Janc wrote:
> > --- a/src/mgmt.c
> > +++ b/src/mgmt.c
> > @@ -1193,6 +1193,7 @@ static void pair_device_complete(int sk, uint16_t index, uint8_t status,
> > info = &controllers[index];
> >
> > bonding_complete(info, &rp->addr.bdaddr, status);
> > + oob_pairing_complete(&info->bdaddr, &rp->addr.bdaddr, status);
> > }
>
> Can't we be a bit smarter than always notifying the oob code. Don't we
> e.g. have the possibility to look at the IO capabilities used in the
> pairing process or some other means from which we can conclude that this
> was an OOB-based pairing that completed?
Hash and randomizer are optional tags (only address is mandatory) so there
might be only OOB discovery and in-band pairing (OOB data present flag not
set in iocapa).
I could try to make OOB callbacks registering mechanism a bit more runtime
aware (register/unregister on-demand basis) or bit-more compile time aware
(hide after a macro and enable only if one of oob plugin is build).
Not sure if this would not over-complicate that code to much... opinions?
>
> Johan
--
BR
Szymon Janc
^ permalink raw reply
* [RFC, PATCH] hid-ps3remote: handle multiple keypresses for joypad buttons
From: Antonio Ospite @ 2012-09-24 11:25 UTC (permalink / raw)
To: David Dillow
Cc: Antonio Ospite, linux-bluetooth, David Herrmann,
Luiz Augusto von Dentz, Bastien Nocera, linux-input, jkosina
In-Reply-To: <20120921220659.1e257048fed597061efb07f9@studenti.unina.it>
---
drivers/hid/hid-ps3remote.c | 153 +++++++++++++++++++++++++++----------------
1 file changed, 96 insertions(+), 57 deletions(-)
Hey David D., I was able to improve the situation with the patch below,
basically that's what I am doing:
- In the descriptor have two collections, one for "joypad buttons"
which allow multiple keypresses, and one for the remote buttons
which do not allow multiple keypresses.
- Have two key maps, one for each collection.
In order to make this work I have to put joypad buttons only in one of
the key maps, I don't know if that is compatible with the Harmony
adapter.
BTW to deal with HID descriptors I am using this gHID tool which
provides a "smart language" that ease things a little bit:
http://code.google.com/p/ghid/
The code spacing and naming of variables can be improved in the patch
below but I wanted to get it out ASAP to avoid duplicate work.
Regards,
Antonio
diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
index 11a6c1f..fa2e50d 100644
--- a/drivers/hid/hid-ps3remote.c
+++ b/drivers/hid/hid-ps3remote.c
@@ -49,6 +49,26 @@
* The keymap is generally ordered by the physical location of the buttons,
* as this makes it easier to verify a correct mapping during testing.
*/
+static const unsigned int ps3remote_keymap_1[] = {
+ [0x01] = KEY_SELECT,
+ [0x02] = BTN_THUMBL, /* L3 */
+ [0x03] = BTN_THUMBR, /* R3 */
+ [0x04] = BTN_START,
+ [0x05] = KEY_UP,
+ [0x06] = KEY_RIGHT,
+ [0x07] = KEY_DOWN,
+ [0x08] = KEY_LEFT,
+ [0x09] = BTN_TL2, /* L2 */
+ [0x0a] = BTN_TR2, /* R2 */
+ [0x0b] = BTN_TL, /* L1 */
+ [0x0c] = BTN_TR, /* R1 */
+ [0x0d] = KEY_OPTION, /* options/triangle */
+ [0x0e] = KEY_BACK, /* back/circle */
+ [0x0f] = BTN_0, /* cross */
+ [0x10] = KEY_SCREEN, /* view/square */
+ [0x11] = KEY_HOMEPAGE, /* PS button */
+ [0x14] = KEY_ENTER,
+};
static const unsigned int ps3remote_keymap[] = {
[0x16] = KEY_EJECTCD,
[0x64] = KEY_AUDIO,
@@ -74,24 +94,24 @@ static const unsigned int ps3remote_keymap[] = {
[0x1a] = KEY_MENU, /* top menu */
[0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
[0x0e] = KEY_ESC, /* return */
- [0x5c] = KEY_OPTION, /* options/triangle */
- [0x5d] = KEY_BACK, /* back/circle */
- [0x5f] = KEY_SCREEN, /* view/square */
- [0x5e] = BTN_0, /* cross */
- [0x54] = KEY_UP,
- [0x56] = KEY_DOWN,
- [0x57] = KEY_LEFT,
- [0x55] = KEY_RIGHT,
- [0x0b] = KEY_ENTER,
- [0x5a] = BTN_TL, /* L1 */
- [0x58] = BTN_TL2, /* L2 */
- [0x51] = BTN_THUMBL, /* L3 */
- [0x5b] = BTN_TR, /* R1 */
- [0x59] = BTN_TR2, /* R2 */
- [0x52] = BTN_THUMBR, /* R3 */
- [0x43] = KEY_HOMEPAGE, /* PS button */
- [0x50] = KEY_SELECT,
- [0x53] = BTN_START,
+ //[0x5c] = KEY_OPTION, /* options/triangle */
+ //[0x5d] = KEY_BACK, /* back/circle */
+ //[0x5f] = KEY_SCREEN, /* view/square */
+ //[0x5e] = BTN_0, /* cross */
+ //[0x54] = KEY_UP,
+ //[0x56] = KEY_DOWN,
+ //[0x57] = KEY_LEFT,
+ //[0x55] = KEY_RIGHT,
+ //[0x0b] = KEY_ENTER,
+ //[0x5a] = BTN_TL, /* L1 */
+ //[0x58] = BTN_TL2, /* L2 */
+ //[0x51] = BTN_THUMBL, /* L3 */
+ //[0x5b] = BTN_TR, /* R1 */
+ //[0x59] = BTN_TR2, /* R2 */
+ //[0x52] = BTN_THUMBR, /* R3 */
+ //[0x43] = KEY_HOMEPAGE, /* PS button */
+ //[0x50] = KEY_SELECT,
+ //[0x53] = BTN_START,
[0x33] = KEY_REWIND, /* scan back */
[0x32] = KEY_PLAY,
[0x34] = KEY_FORWARD, /* scan forward */
@@ -104,42 +124,54 @@ static const unsigned int ps3remote_keymap[] = {
};
static __u8 ps3remote_rdesc[] = {
- 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */
- 0x09, 0x05, /* USAGE (Game Pad) */
- 0xa1, 0x01, /* COLLECTION (Application) */
-
- /* First four bytes contain a bitmask for some of the buttons, and
- * possibly a controller number. We don't need this information,
- * as the keys will be reported in the next field as well.
- */
- 0x75, 0x20, /* REPORT SIZE (32) */
- 0x95, 0x01, /* REPORT COUNT (1) */
- 0x81, 0x01, /* INPUT (Constant) */
-
- /* All key presses are reported in this field */
- 0x05, 0x09, /* USAGE PAGE (Button) */
- 0x19, 0x00, /* USAGE MINIMUM (0) */
- 0x29, 0xfe, /* USAGE MAXIMUM (254) */
- 0x15, 0x00, /* LOGICAL MINIMUM (0) */
- 0x25, 0xfe, /* LOGICAL MAXIMUM (254) */
- 0x75, 0x08, /* REPORT SIZE (8) */
- 0x95, 0x06, /* REPORT COUNT (6) */
- 0x81, 0x00, /* INPUT (Array, Absolute) */
-
- /* Ignore press indication */
- 0x75, 0x08, /* REPORT SIZE (8) */
- 0x95, 0x01, /* REPORT COUNT (1) */
- 0x81, 0x01, /* INPUT (Constant) */
-
- /* Report the battery level */
- 0x05, 0x06, /* USAGE PAGE (Generic Device) */
- 0x09, 0x20, /* USAGE (Battery Strength) */
- 0x15, 0x00, /* LOGICAL MINIMUM (0) */
- 0x25, 0x05, /* LOGICAL MAXIMUM (5) */
- 0x75, 0x08, /* REPORT SIZE (8) */
- 0x95, 0x01, /* REPORT COUNT (1) */
- 0x81, 0x02, /* INPUT (Variable, Absolute) */
- 0xc0, /* END_COLLECTION */
+ 0x05, 0x01, // GUsagePage Generic Desktop
+ 0x09, 0x05, // LUsage 0x05 [Game Pad]
+ 0xA1, 0x01, // MCollection Application (mouse, keyboard)
+ 0xA1, 0x02, // MCollection Logical (interrelated data)
+ 0x75, 0x08, // GReportSize 0x08 [8]
+ 0x95, 0x01, // GReportCount 0x01 [1]
+ 0x81, 0x00, // MInput 0x03
+ // Const[0] Var[1] Abs[2]
+
+ 0x05, 0x09, // GUsagePage Button
+ 0x19, 0x01, // LUsageMinimum 0x01 [Button 1 (primary/trigger)]
+ 0x29, 0x18, // LUsageMaximum 0x18 [Button 18]
+ 0x14, // GLogicalMinimum [0]
+ 0x25, 0x01, // GLogicalMaximum 0x01 [1]
+ 0x75, 0x01, // GReportSize 0x01 [1]
+ 0x95, 0x18, // GReportCount 0x18 [24]
+ 0x81, 0x02, // MInput 0x02
+ 0xC0, // MEndCollection [Game Pad]
+ // Data[0] Var[1] Abs[2]
+
+ 0xA1, 0x02, // MCollection Logical (interrelated data)
+ 0x05, 0x09, // GUsagePage Button
+ 0x18, // LUsageMinimum [No button pressed]
+ 0x29, 0xFE, // LUsageMaximum 0xFE [Button FE]
+ 0x14, // GLogicalMinimum [0]
+ 0x26, 0xFE, 0x00, // GLogicalMaximum 0x00FE [254]
+ 0x75, 0x08, // GReportSize 0x08 [8]
+ 0x95, 0x06, // GReportCount 0x06 [6]
+ 0x80, // MInput
+ //
+
+ 0x75, 0x08, // GReportSize 0x08 [8]
+ 0x95, 0x01, // GReportCount 0x01 [1]
+ 0x81, 0x01, // MInput 0x01
+ // Const[0] Arr[1] Abs[2]
+
+ 0x05, 0x06, // GUsagePage Generic Device Controls
+ 0x09, 0x20, // LUsage 0x20 [Battery Strength]
+ 0x14, // GLogicalMinimum [0]
+ 0x25, 0x05, // GLogicalMaximum 0x05 [5]
+ 0x75, 0x08, // GReportSize 0x08 [8]
+ 0x95, 0x01, // GReportCount 0x01 [1]
+ 0x81, 0x02, // MInput 0x02
+ // Data[0] Var[1] Abs[2]
+
+ 0xC0, // MEndCollection [Game Pad]
+
+ 0xC0 // MEndCollection [Game Pad]
};
static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -159,9 +191,16 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
key >= ARRAY_SIZE(ps3remote_keymap))
return -1;
- key = ps3remote_keymap[key];
- if (!key)
- return -1;
+ if (usage->collection_index == 1) {
+ key = ps3remote_keymap_1[key];
+ if (!key)
+ return -1;
+ }
+ if (usage->collection_index == 2) {
+ key = ps3remote_keymap[key];
+ if (!key)
+ return -1;
+ }
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
return 1;
--
1.7.10.4
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply related
* [RFC v0] device: Add DiscoveryComplete signal
From: Mikel Astiz @ 2012-09-24 11:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
The D-Bus API has to report when the UUID property has been fully
populated, once the service discovery has been finished as part of the
pairing process. This allows UIs to show the device only after its
services are known, avoiding transitional states.
---
We want to have a pairing UI that will let the user choose which profiles he wants to use with a specific device. We listen to DeviceCreated and then gather all device properties, but there is no way to know when the UUIDs have reached a stable state after the first discovery.
doc/device-api.txt | 12 ++++++++++++
src/device.c | 8 +++++++-
2 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/doc/device-api.txt b/doc/device-api.txt
index 1f0dc96..1d64ac2 100644
--- a/doc/device-api.txt
+++ b/doc/device-api.txt
@@ -82,6 +82,13 @@ Signals PropertyChanged(string name, variant value)
disconnection to a remote device has been requested.
The actual disconnection will happen 2 seconds later.
+ DiscoveryComplete()
+
+ This signal will be sent when the service discovery
+ of a recently paired device has completed. This means
+ the UUIDs property has been populated with the
+ discovered remote services.
+
Properties string Address [readonly]
The Bluetooth device address of the remote device.
@@ -125,6 +132,11 @@ Properties string Address [readonly]
List of 128-bit UUIDs that represents the available
remote services.
+ Note that this value can change over time, specially
+ during the pairing process. See the above described
+ DiscoveryComplete signal in order to know when the
+ list has been populated with the discovered services.
+
array{object} Services [readonly]
List of characteristics based services.
diff --git a/src/device.c b/src/device.c
index aa3a607..6bac826 100644
--- a/src/device.c
+++ b/src/device.c
@@ -887,6 +887,7 @@ static const GDBusSignalTable device_signals[] = {
{ GDBUS_SIGNAL("PropertyChanged",
GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
{ GDBUS_SIGNAL("DisconnectRequested", NULL) },
+ { GDBUS_SIGNAL("DiscoveryComplete", NULL) },
{ }
};
@@ -1649,8 +1650,13 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
uuids_changed(req->device);
send_reply:
- if (!req->msg)
+ if (!req->msg) {
+ g_dbus_emit_signal(btd_get_dbus_connection(),
+ device->path,
+ DEVICE_INTERFACE, "DiscoveryComplete",
+ DBUS_TYPE_INVALID);
goto cleanup;
+ }
if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
"DiscoverServices"))
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH v3 02/18] eir: Add support for parsing SSP hash and randomizer
From: Szymon Janc @ 2012-09-24 10:20 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <20120924080845.GA19184@x220>
On Monday 24 of September 2012 11:08:45 Johan Hedberg wrote:
> Hi Szymon,
Hi Johan,
> On Fri, Sep 21, 2012, Szymon Janc wrote:
> > + case EIR_SSP_HASH:
> > + if (data_len < 16)
> > + break;
> > + eir->hash = g_malloc(16);
> > + memcpy(eir->hash, data, 16);
> > + break;
> > +
> > + case EIR_SSP_RANDOMIZER:
> > + if (data_len < 16)
> > + break;
> > + eir->randomizer = g_malloc(16);
> > + memcpy(eir->randomizer, data, 16);
> > + break;
>
> I suppose using g_memdup would be simpler than g_malloc + memcpy.
Yeap that looks simpler, will use g_memdup in next version.
--
BR
Szymon Janc
^ permalink raw reply
* Re: [PATCH v3 07/18] neard: Implement PushOOB function
From: Johan Hedberg @ 2012-09-24 9:09 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1348230995-8967-8-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Fri, Sep 21, 2012, Szymon Janc wrote:
> +static struct btd_adapter *pending_adapter = NULL;
> +static DBusMessage *pending_msg = NULL;
I'm not really a fan of these global variables. Any chance of moving
them to a non-global temporary context that gets passed around. In
general I find it hard to get the big picture on the life-time of these
variables as it seems you don't actually explicitly initiate the pairing
process from your code but are relying on some external entity to do
that? Or did I miss something? The whole thing just looks quite brittle
right now.
Johan
^ permalink raw reply
* [PATCH v3] gatt: Delay D-Bus reply on char discovery
From: chen.ganir @ 2012-09-24 9:08 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chen.ganir
From: Chen Ganir <chen.ganir@ti.com>
Delay sending the D-Bus reply for the discover_characteristics
command. The D-Bus reply for characteristics is sent before all
the relevant characteristic information is gathered. This can
cause problems, when trying to get characteristic information too
soon. This patch moves the D-Bus reply to the end of the char
discovery process. Only after all descriptors are discovered and
read, the D-Bus reply is sent.
---
attrib/client.c | 92 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 50 insertions(+), 42 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index 2423fad..6015a7d 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -330,6 +330,43 @@ static void update_watchers(gpointer data, gpointer user_data)
g_dbus_send_message(btd_get_dbus_connection(), msg);
}
+static DBusMessage *create_discover_char_reply(DBusMessage *msg, GSList *chars)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ GSList *l;
+
+ reply = dbus_message_new_method_return(msg);
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);
+
+ for (l = chars; l; l = l->next) {
+ struct characteristic *chr = l->data;
+
+ dbus_message_iter_append_basic(&array_iter,
+ DBUS_TYPE_OBJECT_PATH, &chr->path);
+ }
+
+ dbus_message_iter_close_container(&iter, &array_iter);
+
+ return reply;
+}
+
+static void send_chr_discovery_complete(struct gatt_service *gatt)
+{
+ DBusMessage *reply;
+
+ reply = create_discover_char_reply(gatt->query->msg, gatt->chars);
+
+ dbus_message_unref(gatt->query->msg);
+ gatt->query->msg = NULL;
+
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+}
+
static void events_handler(const uint8_t *pdu, uint16_t len,
gpointer user_data)
{
@@ -746,6 +783,7 @@ static void query_list_remove(struct gatt_service *gatt, struct query_data *data
if (query->list != NULL)
return;
+ send_chr_discovery_complete(gatt);
g_free(query);
gatt->query = NULL;
@@ -916,15 +954,6 @@ static void update_all_chars(gpointer data, gpointer user_data)
struct characteristic *chr = data;
struct gatt_service *gatt = user_data;
- qdesc = g_new0(struct query_data, 1);
- qdesc->gatt = gatt;
- qdesc->chr = chr;
-
- query_list_append(gatt, qdesc);
-
- gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb,
- qdesc);
-
qvalue = g_new0(struct query_data, 1);
qvalue->gatt = gatt;
qvalue->chr = chr;
@@ -932,37 +961,20 @@ static void update_all_chars(gpointer data, gpointer user_data)
query_list_append(gatt, qvalue);
gatt_read_char(gatt->attrib, chr->handle, 0, update_char_value, qvalue);
-}
-
-static DBusMessage *create_discover_char_reply(DBusMessage *msg, GSList *chars)
-{
- DBusMessage *reply;
- DBusMessageIter iter, array_iter;
- GSList *l;
-
- reply = dbus_message_new_method_return(msg);
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);
-
- for (l = chars; l; l = l->next) {
- struct characteristic *chr = l->data;
-
- dbus_message_iter_append_basic(&array_iter,
- DBUS_TYPE_OBJECT_PATH, &chr->path);
- }
+ qdesc = g_new0(struct query_data, 1);
+ qdesc->gatt = gatt;
+ qdesc->chr = chr;
- dbus_message_iter_close_container(&iter, &array_iter);
+ query_list_append(gatt, qdesc);
- return reply;
+ gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb,
+ qdesc);
}
static void char_discovered_cb(GSList *characteristics, guint8 status,
gpointer user_data)
{
- DBusMessage *reply;
struct query_data *current = user_data;
struct gatt_service *gatt = current->gatt;
struct gatt_primary *prim = gatt->prim;
@@ -973,10 +985,13 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
if (status != 0) {
const char *str = att_ecode2str(status);
+ DBusMessage *reply = btd_error_failed(gatt->query->msg, str);
DBG("Discover all characteristics failed: %s", str);
- reply = btd_error_failed(gatt->query->msg, str);
- goto fail;
+ dbus_message_unref(gatt->query->msg);
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+
+ goto done;
}
for (l = characteristics; l; l = l->next) {
@@ -1011,16 +1026,9 @@ static void char_discovered_cb(GSList *characteristics, guint8 status,
gatt_get_address(gatt, &sba, &dba, &bdaddr_type);
store_characteristics(&sba, &dba, bdaddr_type, prim->range.start,
gatt->chars);
-
g_slist_foreach(gatt->chars, update_all_chars, gatt);
- reply = create_discover_char_reply(gatt->query->msg, gatt->chars);
-
-fail:
- dbus_message_unref(gatt->query->msg);
- gatt->query->msg = NULL;
-
- g_dbus_send_message(btd_get_dbus_connection(), reply);
+done:
query_list_remove(gatt, current);
g_free(current);
}
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH v3 05/18] oob: Allow to register pairing complete callback
From: Johan Hedberg @ 2012-09-24 9:06 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1348230995-8967-6-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Fri, Sep 21, 2012, Szymon Janc wrote:
> --- a/src/mgmt.c
> +++ b/src/mgmt.c
> @@ -1193,6 +1193,7 @@ static void pair_device_complete(int sk, uint16_t index, uint8_t status,
> info = &controllers[index];
>
> bonding_complete(info, &rp->addr.bdaddr, status);
> + oob_pairing_complete(&info->bdaddr, &rp->addr.bdaddr, status);
> }
Can't we be a bit smarter than always notifying the oob code. Don't we
e.g. have the possibility to look at the IO capabilities used in the
pairing process or some other means from which we can conclude that this
was an OOB-based pairing that completed?
Johan
^ permalink raw reply
* Re: [PATCH v3 02/18] eir: Add support for parsing SSP hash and randomizer
From: Johan Hedberg @ 2012-09-24 8:08 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1348230995-8967-3-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Fri, Sep 21, 2012, Szymon Janc wrote:
> + case EIR_SSP_HASH:
> + if (data_len < 16)
> + break;
> + eir->hash = g_malloc(16);
> + memcpy(eir->hash, data, 16);
> + break;
> +
> + case EIR_SSP_RANDOMIZER:
> + if (data_len < 16)
> + break;
> + eir->randomizer = g_malloc(16);
> + memcpy(eir->randomizer, data, 16);
> + break;
I suppose using g_memdup would be simpler than g_malloc + memcpy.
Johan
^ permalink raw reply
* Re: [PATCH] Cycling Speed and Cadence profile (CSCP) API
From: Andrzej Kaczmarek @ 2012-09-24 8:02 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CAJdJm_PyC22Les5_=+z+MjnbFzGGZ7CepQNEo9QRdV0z_SaUKA@mail.gmail.com>
Hi Anderson,
On 09/21/2012 05:51 PM, Anderson Lizardo wrote:
> Hi Andrzej,
>
> On Fri, Sep 21, 2012 at 5:09 AM, Andrzej Kaczmarek
> <andrzej.kaczmarek@tieto.com> wrote:
>> +Cycling Speed and Cadence API description
>> +****************************************
>> +
>> +Copyright (C) 2012 Tieto Poland
>> +
>> +Cycling Manager hierarchy
>> +============================
>> +
>> +Service org.bluez
>> +Interface org.bluez.CyclingManager
>
> I don't have much to comment on the API as I haven't had time to read
> the CSCP spec yet, but about the name prefix, what about
> "CyclingSpeed" (and "RunningSpeed" for the future RSCP) ? Too long?
Ok for me. Not too long for sure, Thermometer is just 1 letter shorter.
> The "Cycling" name is slightly uncommon, but still not that bad IMHO.
In spec there's also SC used as shortcut for 'Speed and Cadence' but I
think CyclingSC does not work well with camel-case in interface name. Or
actually is CyclingScManager ok? But plugin name (cyclingsc) will look a
bit weird if derived from this name, cyclingspeed sounds better.
>> +Properties String Location (optional) [readwrite]
>
> String -> string
>
>> + uint16 LastWheelEventTime (optional):
>> +
>> + Value of Last Wheel Event time
>
> Better specify that this is in "1/1024 second units" (just checked on
> developer.bluetooth.org).
>
>> +
>> + uint16 CrankRevolutions (optional):
>> +
>> + Cumulative number of crank revolutions
>> +
>> + uint16 LastCrankEventTime (optional):
>> +
>> + Value of Last Crank Event time
>
> Same here.
Sure, I'll fix above issues.
BR,
Andrzej
^ permalink raw reply
* [PATCH v4 10/10] battery: Support persistent battery level
From: chen.ganir @ 2012-09-24 7:15 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chen.ganir
In-Reply-To: <1348470919-25567-1-git-send-email-chen.ganir@ti.com>
From: Chen Ganir <chen.ganir@ti.com>
Store battery level when read, and use the level from storage
when connecting, to reduce GATT traffic.
---
profiles/battery/battery.c | 106 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 2 deletions(-)
diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index ac0e706..4a95337 100644
--- a/profiles/battery/battery.c
+++ b/profiles/battery/battery.c
@@ -27,6 +27,8 @@
#include <glib.h>
#include <bluetooth/uuid.h>
#include <stdbool.h>
+#include <sys/file.h>
+#include <stdlib.h>
#include "adapter.h"
#include "device.h"
@@ -37,6 +39,10 @@
#include "gatt.h"
#include "battery.h"
#include "log.h"
+#include "storage.h"
+
+#define BATTERY_KEY_FORMAT "%17s#%04X"
+#define BATTERY_LEVEL_FORMAT "%03d"
struct battery {
struct btd_device *dev; /* Device reference */
@@ -77,10 +83,103 @@ static gint cmp_device(gconstpointer a, gconstpointer b)
return -1;
}
+static inline int create_filename(char *buf, size_t size,
+ const bdaddr_t *bdaddr, const char *name)
+{
+ char addr[18];
+
+ ba2str(bdaddr, addr);
+
+ return create_name(buf, size, STORAGEDIR, addr, name);
+}
+
+static int store_battery_char(struct characteristic *chr)
+{
+ char filename[PATH_MAX + 1], addr[18], key[23];
+ bdaddr_t sba, dba;
+ char level[4];
+
+ adapter_get_address(device_get_adapter(chr->batt->dev), &sba);
+ device_get_address(chr->batt->dev, &dba, NULL);
+
+ create_filename(filename, PATH_MAX, &sba, "battery_gatt_client");
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ ba2str(&dba, addr);
+
+ snprintf(key, sizeof(key), BATTERY_KEY_FORMAT, addr, chr->attr.handle);
+ snprintf(level, sizeof(level), BATTERY_LEVEL_FORMAT, chr->level);
+
+ return textfile_caseput(filename, key, level);
+}
+
+static char *read_battery_char(struct characteristic *chr)
+{
+ char filename[PATH_MAX + 1], addr[18], key[23];
+ char *str, *strnew;
+ bdaddr_t sba, dba;
+
+ adapter_get_address(device_get_adapter(chr->batt->dev), &sba);
+ device_get_address(chr->batt->dev, &dba, NULL);
+
+ create_filename(filename, PATH_MAX, &sba, "battery_gatt_client");
+
+ ba2str(&dba, addr);
+ snprintf(key, sizeof(key), BATTERY_KEY_FORMAT, addr, chr->attr.handle);
+
+ str = textfile_caseget(filename, key);
+ if (str == NULL)
+ return NULL;
+
+ strnew = g_strdup(str);
+ g_free(str);
+
+ return strnew;
+}
+
+static void del_battery_char(struct characteristic *chr)
+{
+ char filename[PATH_MAX + 1], addr[18], key[23];
+ bdaddr_t sba, dba;
+
+ adapter_get_address(device_get_adapter(chr->batt->dev), &sba);
+ device_get_address(chr->batt->dev, &dba, NULL);
+
+ create_filename(filename, PATH_MAX, &sba, "battery_gatt_client");
+
+ ba2str(&dba, addr);
+ snprintf(key, sizeof(key), BATTERY_KEY_FORMAT, addr, chr->attr.handle);
+
+ textfile_casedel(filename, key);
+}
+
+static gboolean read_battery_level_value(struct characteristic *chr)
+{
+ char *str;
+
+ if (!chr)
+ return FALSE;
+
+ str = read_battery_char(chr);
+ if (!str)
+ return FALSE;
+
+ chr->level = atoi(str);
+
+ btd_device_set_battery_opt(chr->devbatt, BATTERY_OPT_LEVEL, chr->level,
+ BATTERY_OPT_INVALID);
+
+ g_free(str);
+ return TRUE;
+}
+
static void char_free(gpointer user_data)
{
struct characteristic *c = user_data;
+ del_battery_char(c);
+
g_slist_free_full(c->desc, g_free);
btd_device_remove_battery(c->devbatt);
@@ -146,6 +245,8 @@ static void read_batterylevel_cb(guint8 status, const guint8 *pdu, guint16 len,
ch->level = value[0];
btd_device_set_battery_opt(ch->devbatt, BATTERY_OPT_LEVEL, ch->level,
BATTERY_OPT_INVALID);
+
+ store_battery_char(ch);
}
static void process_batteryservice_char(struct characteristic *ch)
@@ -344,7 +445,8 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
start = c->value_handle + 1;
- process_batteryservice_char(ch);
+ if (!read_battery_level_value(ch))
+ process_batteryservice_char(ch);
ch->devbatt = btd_device_add_battery(ch->batt->dev);
@@ -423,7 +525,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
GSList *l;
for (l = batt->chars; l; l = l->next) {
struct characteristic *c = l->data;
- if (!c->can_notify)
+ if (!read_battery_level_value(c) && !c->can_notify)
process_batteryservice_char(c);
}
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 09/10] battery: Add support for notifications
From: chen.ganir @ 2012-09-24 7:15 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chen.ganir
In-Reply-To: <1348470919-25567-1-git-send-email-chen.ganir@ti.com>
From: Chen Ganir <chen.ganir@ti.com>
Add support for emitting PropertyChanged when a battery level
characteristic notification is sent from the peer device.
---
profiles/battery/battery.c | 100 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 2 deletions(-)
diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index f733ff6..ac0e706 100644
--- a/profiles/battery/battery.c
+++ b/profiles/battery/battery.c
@@ -43,6 +43,7 @@ struct battery {
GAttrib *attrib; /* GATT connection */
guint attioid; /* Att watcher id */
struct att_range *svc_range; /* Battery range */
+ guint attnotid; /* Att notifications id */
GSList *chars; /* Characteristics */
};
@@ -56,6 +57,7 @@ struct characteristic {
uint8_t ns; /* Battery Namespace */
uint16_t description; /* Battery description */
uint8_t level; /* Battery level */
+ gboolean can_notify; /* Char can notify flag */
};
struct descriptor {
@@ -86,6 +88,14 @@ static void char_free(gpointer user_data)
g_free(c);
}
+static gint cmp_char_val_handle(gconstpointer a, gconstpointer b)
+{
+ const struct characteristic *ch = a;
+ const uint16_t *handle = b;
+
+ return ch->attr.value_handle - *handle;
+}
+
static void battery_free(gpointer user_data)
{
struct battery *batt = user_data;
@@ -96,8 +106,14 @@ static void battery_free(gpointer user_data)
if (batt->attioid > 0)
btd_device_remove_attio_callback(batt->dev, batt->attioid);
- if (batt->attrib != NULL)
+ if (batt->attrib != NULL) {
+ if (batt->attnotid) {
+ g_attrib_unregister(batt->attrib, batt->attnotid);
+ batt->attnotid = 0;
+ }
+
g_attrib_unref(batt->attrib);
+ }
btd_device_unref(batt->dev);
g_free(batt->svc_range);
@@ -140,6 +156,18 @@ static void process_batteryservice_char(struct characteristic *ch)
}
}
+static void batterylevel_enable_notify_cb(guint8 status, const guint8 *pdu,
+ guint16 len, gpointer user_data)
+{
+ struct characteristic *ch = user_data;
+
+ if (status != 0) {
+ error("Could not enable batt level notification.");
+ ch->can_notify = FALSE;
+ process_batteryservice_char(ch);
+ }
+}
+
static gint device_battery_cmp(gconstpointer a, gconstpointer b)
{
const struct characteristic *ch = a;
@@ -176,6 +204,21 @@ static void batterylevel_refresh_cb(struct btd_battery *batt)
process_batteryservice_char(ch);
}
+static void enable_battery_notification(struct characteristic *ch,
+ uint16_t handle)
+{
+ uint8_t atval[2];
+ uint16_t val;
+
+ val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
+
+ ch->can_notify = TRUE;
+
+ att_put_u16(val, atval);
+ gatt_write_char(ch->batt->attrib, handle, atval, 2,
+ batterylevel_enable_notify_cb, ch);
+}
+
static void batterylevel_presentation_format_desc_cb(guint8 status,
const guint8 *pdu, guint16 len,
gpointer user_data)
@@ -211,6 +254,14 @@ static void process_batterylevel_desc(struct descriptor *desc)
char uuidstr[MAX_LEN_UUID_STR];
bt_uuid_t btuuid;
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0 && g_strcmp0(ch->attr.uuid,
+ BATTERY_LEVEL_UUID) == 0) {
+ enable_battery_notification(ch, desc->handle);
+ return;
+ }
+
bt_uuid16_create(&btuuid, GATT_CHARAC_FMT_UUID);
if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
@@ -316,12 +367,54 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
}
}
+static void proc_batterylevel(struct characteristic *c, const uint8_t *pdu,
+ uint16_t len, gboolean final)
+{
+ if (!pdu) {
+ error("Battery level notification: Invalid pdu length");
+ return;
+ }
+
+ c->level = pdu[1];
+
+ btd_device_set_battery_opt(c->devbatt, BATTERY_OPT_LEVEL, c->level,
+ BATTERY_OPT_INVALID);
+}
+
+static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+ struct battery *batt = user_data;
+ struct characteristic *ch;
+ uint16_t handle;
+ GSList *l;
+
+ if (len < 3) {
+ error("notif_handler: Bad pdu received");
+ return;
+ }
+
+ handle = att_get_u16(&pdu[1]);
+ l = g_slist_find_custom(batt->chars, &handle, cmp_char_val_handle);
+ if (l == NULL) {
+ error("notif_handler: Unexpected handle 0x%04x", handle);
+ return;
+ }
+
+ ch = l->data;
+ if (g_strcmp0(ch->attr.uuid, BATTERY_LEVEL_UUID) == 0) {
+ proc_batterylevel(ch, pdu, len, FALSE);
+ }
+}
+
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
struct battery *batt = user_data;
batt->attrib = g_attrib_ref(attrib);
+ batt->attnotid = g_attrib_register(batt->attrib, ATT_OP_HANDLE_NOTIFY,
+ notif_handler, batt, NULL);
+
if (batt->chars == NULL) {
gatt_discover_char(batt->attrib, batt->svc_range->start,
batt->svc_range->end, NULL,
@@ -330,7 +423,8 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
GSList *l;
for (l = batt->chars; l; l = l->next) {
struct characteristic *c = l->data;
- process_batteryservice_char(c);
+ if (!c->can_notify)
+ process_batteryservice_char(c);
}
}
}
@@ -339,6 +433,8 @@ static void attio_disconnected_cb(gpointer user_data)
{
struct battery *batt = user_data;
+ g_attrib_unregister(batt->attrib, batt->attnotid);
+ batt->attnotid = 0;
g_attrib_unref(batt->attrib);
batt->attrib = NULL;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 08/10] battery: Read Battery level characteristic
From: chen.ganir @ 2012-09-24 7:15 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chen.ganir
In-Reply-To: <1348470919-25567-1-git-send-email-chen.ganir@ti.com>
From: Chen Ganir <chen.ganir@ti.com>
Implement support for reading the battery level characteristic on
connection establishment.
---
profiles/battery/battery.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index 892e42a..f733ff6 100644
--- a/profiles/battery/battery.c
+++ b/profiles/battery/battery.c
@@ -55,6 +55,7 @@ struct characteristic {
GSList *desc; /* Descriptors */
uint8_t ns; /* Battery Namespace */
uint16_t description; /* Battery description */
+ uint8_t level; /* Battery level */
};
struct descriptor {
@@ -103,6 +104,78 @@ static void battery_free(gpointer user_data)
g_free(batt);
}
+static void read_batterylevel_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct characteristic *ch = user_data;
+ uint8_t value[ATT_MAX_MTU];
+ int vlen;
+
+ if (status != 0) {
+ error("Failed to read Battery Level:%s", att_ecode2str(status));
+ return;
+ }
+
+ vlen = dec_read_resp(pdu, len, value, sizeof(value));
+ if (vlen < 0) {
+ error("Failed to read Battery Level: Protocol error");
+ return;
+ }
+
+ if (vlen != 1) {
+ error("Failed to read Battery Level: Wrong pdu len");
+ return;
+ }
+
+ ch->level = value[0];
+ btd_device_set_battery_opt(ch->devbatt, BATTERY_OPT_LEVEL, ch->level,
+ BATTERY_OPT_INVALID);
+}
+
+static void process_batteryservice_char(struct characteristic *ch)
+{
+ if (g_strcmp0(ch->attr.uuid, BATTERY_LEVEL_UUID) == 0) {
+ gatt_read_char(ch->batt->attrib, ch->attr.value_handle, 0,
+ read_batterylevel_cb, ch);
+ }
+}
+
+static gint device_battery_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct characteristic *ch = a;
+ const struct btd_battery *batt = b;
+
+ if (batt == ch->devbatt)
+ return 0;
+
+ return -1;
+}
+
+static struct characteristic *find_battery_char(struct btd_battery *db)
+{
+ GSList *l, *b;
+
+ for (l = servers; l != NULL; l = g_slist_next(l)) {
+ struct battery *batt = l->data;
+
+ b = g_slist_find_custom(batt->chars, db, device_battery_cmp);
+ if (b)
+ return b->data;
+ }
+
+ return NULL;
+}
+
+static void batterylevel_refresh_cb(struct btd_battery *batt)
+{
+ struct characteristic *ch;
+
+ ch = find_battery_char(batt);
+
+ if (ch)
+ process_batteryservice_char(ch);
+}
+
static void batterylevel_presentation_format_desc_cb(guint8 status,
const guint8 *pdu, guint16 len,
gpointer user_data)
@@ -220,8 +293,15 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
start = c->value_handle + 1;
+ process_batteryservice_char(ch);
+
ch->devbatt = btd_device_add_battery(ch->batt->dev);
+ btd_device_set_battery_opt(ch->devbatt,
+ BATTERY_OPT_REFRESH_FUNC,
+ batterylevel_refresh_cb,
+ BATTERY_OPT_INVALID);
+
if (l->next != NULL) {
struct gatt_char *c = l->next->data;
if (start == c->handle)
@@ -246,6 +326,12 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
gatt_discover_char(batt->attrib, batt->svc_range->start,
batt->svc_range->end, NULL,
configure_battery_cb, batt);
+ } else {
+ GSList *l;
+ for (l = batt->chars; l; l = l->next) {
+ struct characteristic *c = l->data;
+ process_batteryservice_char(c);
+ }
}
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 07/10] battery: Add Battery to device
From: chen.ganir @ 2012-09-24 7:15 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chen.ganir
In-Reply-To: <1348470919-25567-1-git-send-email-chen.ganir@ti.com>
From: Chen Ganir <chen.ganir@ti.com>
Add/Remove battery from device
---
profiles/battery/battery.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index 2fbf26e..892e42a 100644
--- a/profiles/battery/battery.c
+++ b/profiles/battery/battery.c
@@ -49,6 +49,7 @@ struct battery {
static GSList *servers;
struct characteristic {
+ struct btd_battery *devbatt; /* device_battery pointer */
struct gatt_char attr; /* Characteristic */
struct battery *batt; /* Parent Battery Service */
GSList *desc; /* Descriptors */
@@ -79,6 +80,8 @@ static void char_free(gpointer user_data)
g_slist_free_full(c->desc, g_free);
+ btd_device_remove_battery(c->devbatt);
+
g_free(c);
}
@@ -217,6 +220,8 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
start = c->value_handle + 1;
+ ch->devbatt = btd_device_add_battery(ch->batt->dev);
+
if (l->next != NULL) {
struct gatt_char *c = l->next->data;
if (start == c->handle)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 06/10] battery: Get Battery ID
From: chen.ganir @ 2012-09-24 7:15 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chen.ganir
In-Reply-To: <1348470919-25567-1-git-send-email-chen.ganir@ti.com>
From: Chen Ganir <chen.ganir@ti.com>
Read the battery level format characteristic descriptor to get the
unique namespace and description values.
---
lib/uuid.h | 1 +
profiles/battery/battery.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/lib/uuid.h b/lib/uuid.h
index 58ad0b3..5c1b3ff 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -57,6 +57,7 @@ extern "C" {
#define DEVICE_INFORMATION_UUID "0000180a-0000-1000-8000-00805f9b34fb"
#define BATTERY_SERVICE_UUID "0000180f-0000-1000-8000-00805f9b34fb"
+#define BATTERY_LEVEL_UUID "00002a19-0000-1000-8000-00805f9b34fb"
#define GATT_UUID "00001801-0000-1000-8000-00805f9b34fb"
#define IMMEDIATE_ALERT_UUID "00001802-0000-1000-8000-00805f9b34fb"
diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index dada15b..2fbf26e 100644
--- a/profiles/battery/battery.c
+++ b/profiles/battery/battery.c
@@ -52,6 +52,8 @@ struct characteristic {
struct gatt_char attr; /* Characteristic */
struct battery *batt; /* Parent Battery Service */
GSList *desc; /* Descriptors */
+ uint8_t ns; /* Battery Namespace */
+ uint16_t description; /* Battery description */
};
struct descriptor {
@@ -98,6 +100,53 @@ static void battery_free(gpointer user_data)
g_free(batt);
}
+static void batterylevel_presentation_format_desc_cb(guint8 status,
+ const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct descriptor *desc = user_data;
+ uint8_t value[ATT_MAX_MTU];
+ int vlen;
+
+ if (status != 0) {
+ error("Presentation Format desc read failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ vlen = dec_read_resp(pdu, len, value, sizeof(value));
+ if (vlen < 0) {
+ error("Presentation Format desc read failed: Protocol error");
+ return;
+ }
+
+ if (vlen < 7) {
+ error("Presentation Format desc read failed: Invalid range");
+ return;
+ }
+
+ desc->ch->ns = value[4];
+ desc->ch->description = att_get_u16(&value[5]);
+}
+
+static void process_batterylevel_desc(struct descriptor *desc)
+{
+ struct characteristic *ch = desc->ch;
+ char uuidstr[MAX_LEN_UUID_STR];
+ bt_uuid_t btuuid;
+
+ bt_uuid16_create(&btuuid, GATT_CHARAC_FMT_UUID);
+
+ if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
+ gatt_read_char(ch->batt->attrib, desc->handle, 0,
+ batterylevel_presentation_format_desc_cb, desc);
+ return;
+ }
+
+ bt_uuid_to_string(&desc->uuid, uuidstr, MAX_LEN_UUID_STR);
+ DBG("Ignored descriptor %s characteristic %s", uuidstr, ch->attr.uuid);
+}
+
static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
@@ -131,6 +180,7 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
desc->uuid = att_get_uuid128(&value[2]);
ch->desc = g_slist_append(ch->desc, desc);
+ process_batterylevel_desc(desc);
}
att_data_list_free(list);
@@ -153,6 +203,9 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
struct characteristic *ch;
uint16_t start, end;
+ if (g_strcmp0(c->uuid, BATTERY_LEVEL_UUID) != 0)
+ continue;
+
ch = g_new0(struct characteristic, 1);
ch->attr.handle = c->handle;
ch->attr.properties = c->properties;
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox