* Re: [PATCH BlueZ 1/7] audio: Fix not freeing gateway agent data on exit
From: Mikel Astiz @ 2012-10-01 12:31 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Mon, Oct 1, 2012 at 1:37 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> 434 (168 direct, 266 indirect) bytes in 7 blocks are definitely lost in loss record 322 of 338
> at 0x4A06F18: calloc (vg_replace_malloc.c:566)
> by 0x4C802C6: g_malloc0 (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x126C0C: register_agent (gateway.c:673)
> by 0x122960: process_message.isra.0 (object.c:197)
> by 0x4F70684: ??? (in /usr/lib64/libdbus-1.so.3.5.6)
> by 0x4F6290C: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.5.6)
> by 0x120FA7: message_dispatch (mainloop.c:76)
> by 0x4C7B22A: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7A694: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7A9C7: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x4C7ADC1: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3200.4)
> by 0x120671: main (main.c:551)
> ---
> audio/gateway.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/audio/gateway.c b/audio/gateway.c
> index 45b25a1..3e606c9 100644
> --- a/audio/gateway.c
> +++ b/audio/gateway.c
> @@ -741,6 +741,9 @@ static void path_unregister(void *data)
>
> gateway_close(dev);
>
> + if (dev->gateway->agent)
> + agent_free(dev->gateway->agent);
> +
> g_free(dev->gateway);
> dev->gateway = NULL;
> }
> --
I also had this in my pipeline so ack from my side.
Cheers,
Mikel
^ permalink raw reply
* Re: [PATCH v2 07/15] thermometer: Reformat MeasurementReceived description
From: Santiago Carot @ 2012-10-01 12:08 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <50697F39.90008@tieto.com>
Hi Andrzej
>>
>> Mantissa values must not always be 2^23-1 on special cases.
>> Information provided here is required for upper profiles which are
>> implementing an 11073-20601 protocol layer because they have to
>> differentiate among these values. In my opinion, documentation about
>> passible values for the mantissa should remain as they are.
>
>
> HTS specification states (see quote below) that measurement value field may
> be NaN in case sensor is not able to provide valid measurement. So I assume
> here that either it has valid data or NaN otherwise and thus there's no need
> to specify other special values as they should not be received here.
>
> <quote>
> The Temperature Measurement Value field may contain special float value NaN
> (0x007FFFFF) defined in IEEE 11073-20601 [4] to report an invalid result
> from a computation step or missing data due to the hardware’s inability to
> provide a valid measurement.
> </quote>
>
IMHO that doesn't justify you to force all mantisse values to be
2^23-1, first of all because the value type for this characteristic is
a FLOAT type, so any value that a thermometer could send, it does it
using the format defined for FLOAT types which is explained in
IEEE-11073-20601,
[http://developer.bluetooth.org/gatt/Pages/FormatTypes.aspx]
On the other hand, I understand from this quote that thermometers MAY
set NaN in case sensor is not able to provide valid measuremen due to
an invalid result or missing data, but it doesn't say anything about
other values that a FLOAT types can take, so you are forcing to be NaN
other special cases that are defined for this kind of type.
If you had a look to that spec you could see wich other special values
a FLOAT type could take, if not, you could at least have a look to one
of the whitepapers defined in bluetooth sig for transcoders.
Regards
^ permalink raw reply
* Re: [PATCH 00/14] Thermometer watchers API change + fixes
From: Anderson Lizardo @ 2012-10-01 11:51 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <50698235.10804@tieto.com>
Hi Andrzej,
On Mon, Oct 1, 2012 at 7:44 AM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> By "dummy" thermometer you mean separate plugin (dummythermometer or sth)
> which, once enabled, will register service in GATT and send dummy
> measurements when configured by remote? Or perhaps develop it inside
> thermometer profile (implemented as described above) so it can be changed
> into full blown thermometer role with API etc. later?
I was thinking having it under profiles/thermometer (just like
proximity reporter is currently in profiles/proximity). The "dummy"
code could then be replaced later with the API. As long as nothing is
enabled until the CCC is written, I don't see any problem having it
running along HTP collector.
>> BTW, I definitely plan to test both your HRP implementation and the
>> HTP changes, but currently I'm working in other things... I'll let you
>> know once I have these tested (probably with patches if I find any
>> issues).
>
>
> I should have BLE PTS dongle this week so will test both implementations as
> well in case you won't manage to do this until then.
Great!
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCH 00/14] Thermometer watchers API change + fixes
From: Andrzej Kaczmarek @ 2012-10-01 11:44 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CAJdJm_NLz-rd1w59pBDP_QMWKVcZ3-N0FMNqy1UCisBzZL-VNQ@mail.gmail.com>
Hi Anderson,
On 09/27/2012 02:03 PM, Anderson Lizardo wrote:
> Hi Andrzej,
>
> On Thu, Sep 27, 2012 at 6:47 AM, Andrzej Kaczmarek
> <andrzej.kaczmarek@tieto.com> wrote:
>>> Maybe we should consider implementing a simple Thermometer role in
>>> BlueZ for testing purposes. It is a relatively simple profile.
>>
>>
>> So you mean something like optional org.bluez.ThermometerSensor interface on
>> adapter, similar to what is done for reporter role for Proximity?
>
> Yes. There has been some interest on the past on the mailing list from
> people willing to implement this role on BlueZ (although I have not
> heard anymore from them), so it would become not just a test plugin,
> but have an API that allows for BlueZ to expose some external
> thermometer measurements over LE. But for now a "dummy" thermometer
> which sends dummy measurements in various formats should be enough
> (probably enabled only with --enable-test so it is not installed in
> production).
>
> Do you have interest/time for working on something like this?
I could take a look on this in spare time, sure.
By "dummy" thermometer you mean separate plugin (dummythermometer or
sth) which, once enabled, will register service in GATT and send dummy
measurements when configured by remote? Or perhaps develop it inside
thermometer profile (implemented as described above) so it can be
changed into full blown thermometer role with API etc. later?
> BTW, I definitely plan to test both your HRP implementation and the
> HTP changes, but currently I'm working in other things... I'll let you
> know once I have these tested (probably with patches if I find any
> issues).
I should have BLE PTS dongle this week so will test both implementations
as well in case you won't manage to do this until then.
BR,
Andrzej
^ permalink raw reply
* [PATCH BlueZ 7/7] AVRCP: Don't respond with errors when no player is registered
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Some devices w.g. Sony MW600 will stop using certain commands if an
error happen, so the code now just fake a player and once a real
player is registered it takes place of the fake one.
---
audio/avrcp.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 63 insertions(+), 14 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 21d105a..6b426f5 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -477,6 +477,17 @@ void avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data)
return;
}
+static void *player_get_metadata(struct avrcp_player *player, uint32_t attr)
+{
+ if (player != NULL)
+ return player->cb->get_metadata(attr, player->user_data);
+
+ if (attr == AVRCP_MEDIA_ATTRIBUTE_TITLE)
+ return "";
+
+ return NULL;
+}
+
static uint16_t player_write_media_attribute(struct avrcp_player *player,
uint32_t id, uint8_t *buf,
uint16_t *pos,
@@ -489,7 +500,7 @@ static uint16_t player_write_media_attribute(struct avrcp_player *player,
DBG("%u", id);
- value = player->cb->get_metadata(id, player->user_data);
+ value = player_get_metadata(player, id);
if (value == NULL) {
*offset = 0;
return 0;
@@ -588,6 +599,9 @@ static int player_set_attribute(struct avrcp_player *player,
{
DBG("Change attribute: %u %u", attr, val);
+ if (player == NULL)
+ return -ENOENT;
+
return player->cb->set_setting(attr, val, player->user_data);
}
@@ -597,6 +611,9 @@ static int player_get_attribute(struct avrcp_player *player, uint8_t attr)
DBG("attr %u", attr);
+ if (player == NULL)
+ return -ENOENT;
+
value = player->cb->get_setting(attr, player->user_data);
if (value < 0)
DBG("attr %u not supported by player", attr);
@@ -653,7 +670,7 @@ static uint8_t avrcp_handle_list_player_attributes(struct avrcp *session,
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
- if (len != 0 || player == NULL) {
+ if (len != 0) {
pdu->params_len = htons(1);
pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
return AVC_CTYPE_REJECTED;
@@ -685,7 +702,7 @@ static uint8_t avrcp_handle_list_player_values(struct avrcp *session,
uint16_t len = ntohs(pdu->params_len);
unsigned int i;
- if (len != 1 || player == NULL)
+ if (len != 1)
goto err;
if (player_get_attribute(player, pdu->params[0]) < 0)
@@ -707,6 +724,15 @@ err:
return AVC_CTYPE_REJECTED;
}
+static GList *player_list_metadata(struct avrcp_player *player)
+{
+ if (player != NULL)
+ return player->cb->list_metadata(player->user_data);
+
+ return g_list_prepend(NULL,
+ GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
+}
+
static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
@@ -719,7 +745,7 @@ static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
GList *attr_ids;
uint16_t offset;
- if (len < 9 || identifier != 0 || player == NULL)
+ if (len < 9 || identifier != 0)
goto err;
nattr = pdu->params[8];
@@ -732,7 +758,7 @@ static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
* Return all available information, at least
* title must be returned if there's a track selected.
*/
- attr_ids = player->cb->list_metadata(player->user_data);
+ attr_ids = player_list_metadata(player);
len = g_list_length(attr_ids);
} else {
unsigned int i;
@@ -788,8 +814,7 @@ static uint8_t avrcp_handle_get_current_player_value(struct avrcp *session,
uint8_t *settings;
unsigned int i;
- if (player == NULL || len <= 1 || pdu->params[0] != len - 1 ||
- player == NULL)
+ if (len <= 1 || pdu->params[0] != len - 1)
goto err;
/*
@@ -922,6 +947,14 @@ err:
return AVC_CTYPE_REJECTED;
}
+static uint32_t player_get_position(struct avrcp_player *player)
+{
+ if (player == NULL)
+ return 0;
+
+ return player->cb->get_position(player->user_data);
+}
+
static uint8_t avrcp_handle_get_play_status(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
@@ -932,15 +965,15 @@ static uint8_t avrcp_handle_get_play_status(struct avrcp *session,
uint32_t duration;
void *pduration;
- if (len != 0 || player == NULL) {
+ if (len != 0) {
pdu->params_len = htons(1);
pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
return AVC_CTYPE_REJECTED;
}
- position = player->cb->get_position(player->user_data);
- pduration = player->cb->get_metadata(AVRCP_MEDIA_ATTRIBUTE_DURATION,
- player->user_data);
+ position = player_get_position(player);
+ pduration = player_get_metadata(player,
+ AVRCP_MEDIA_ATTRIBUTE_DURATION);
if (pduration != NULL)
duration = htonl(GPOINTER_TO_UINT(pduration));
else
@@ -957,6 +990,22 @@ static uint8_t avrcp_handle_get_play_status(struct avrcp *session,
return AVC_CTYPE_STABLE;
}
+static uint64_t player_get_uid(struct avrcp_player *player)
+{
+ if (player == NULL)
+ return UINT64_MAX;
+
+ return player->cb->get_status(player->user_data);
+}
+
+static uint8_t player_get_status(struct avrcp_player *player)
+{
+ if (player == NULL)
+ return AVRCP_PLAY_STATUS_STOPPED;
+
+ return player->cb->get_status(player->user_data);
+}
+
static uint8_t avrcp_handle_register_notification(struct avrcp *session,
struct avrcp_header *pdu,
uint8_t transaction)
@@ -970,18 +1019,18 @@ static uint8_t avrcp_handle_register_notification(struct avrcp *session,
* one is applicable only for EVENT_PLAYBACK_POS_CHANGED. See AVRCP
* 1.3 spec, section 5.4.2.
*/
- if (len != 5 || player == NULL)
+ if (len != 5)
goto err;
switch (pdu->params[0]) {
case AVRCP_EVENT_STATUS_CHANGED:
len = 2;
- pdu->params[1] = player->cb->get_status(player->user_data);
+ pdu->params[1] = player_get_status(player);
break;
case AVRCP_EVENT_TRACK_CHANGED:
len = 9;
- uid = player->cb->get_uid(player->user_data);
+ uid = player_get_uid(player);
memcpy(&pdu->params[1], &uid, sizeof(uint64_t));
break;
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 6/7] AVRCP: Register to AVCTP state changes without depending on player
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
It is not longer necessary to have a player to be able to register the
extra pdu handlers.
---
audio/avrcp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 2e36fb7..21d105a 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -1467,6 +1467,9 @@ int avrcp_register(const bdaddr_t *src, GKeyFile *config)
servers = g_slist_append(servers, server);
+ if (!avctp_id)
+ avctp_id = avctp_add_state_cb(state_changed, NULL);
+
return 0;
}
@@ -1527,9 +1530,6 @@ struct avrcp_player *avrcp_register_player(const bdaddr_t *src,
player->user_data = user_data;
player->destroy = destroy;
- if (!avctp_id)
- avctp_id = avctp_add_state_cb(state_changed, NULL);
-
server->players = g_slist_append(server->players, player);
/* Assign player to session without current player */
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 5/7] AVCTP: Allocate memory to hold incoming/outgoing PDUs
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This makes possible to the handler to respond asyncronous as the memory
remains valid after it returns.
In addition to that it uses the MTU to calculate the buffer size
necessary.
---
audio/avctp.c | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/audio/avctp.c b/audio/avctp.c
index dfc5601..baf5da0 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -134,7 +134,9 @@ struct avctp_rsp_handler {
struct avctp_channel {
GIOChannel *io;
guint watch;
- uint16_t mtu;
+ uint16_t imtu;
+ uint16_t omtu;
+ uint8_t *buffer;
};
struct avctp {
@@ -341,6 +343,7 @@ static void avctp_channel_destroy(struct avctp_channel *chan)
if (chan->watch)
g_source_remove(chan->watch);
+ g_free(chan->buffer);
g_free(chan);
}
@@ -447,7 +450,9 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
gpointer data)
{
struct avctp *session = data;
- uint8_t buf[1024], *operands;
+ struct avctp_channel *browsing = session->browsing;
+ uint8_t *buf = browsing->buffer;
+ uint8_t *operands;
struct avctp_header *avctp;
int sock, ret, packet_size, operand_count;
@@ -456,7 +461,7 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
sock = g_io_channel_unix_get_fd(chan);
- ret = read(sock, buf, sizeof(buf));
+ ret = read(sock, buf, sizeof(browsing->imtu));
if (ret <= 0)
goto failed;
@@ -497,7 +502,9 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
gpointer data)
{
struct avctp *session = data;
- uint8_t buf[1024], *operands, code, subunit;
+ struct avctp_channel *control = session->control;
+ uint8_t *buf = control->buffer;
+ uint8_t *operands, code, subunit;
struct avctp_header *avctp;
struct avc_header *avc;
int ret, packet_size, operand_count, sock;
@@ -508,7 +515,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
sock = g_io_channel_unix_get_fd(chan);
- ret = read(sock, buf, sizeof(buf));
+ ret = read(sock, buf, control->imtu);
if (ret <= 0)
goto failed;
@@ -689,7 +696,7 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
{
struct avctp *session = data;
char address[18];
- uint16_t imtu;
+ uint16_t imtu, omtu;
GError *gerr = NULL;
if (err) {
@@ -700,6 +707,7 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
bt_io_get(chan, &gerr,
BT_IO_OPT_DEST, &address,
BT_IO_OPT_IMTU, &imtu,
+ BT_IO_OPT_OMTU, &omtu,
BT_IO_OPT_INVALID);
if (gerr) {
error("%s", gerr->message);
@@ -714,7 +722,9 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
if (session->browsing == NULL)
session->browsing = avctp_channel_create(chan);
- session->browsing->mtu = imtu;
+ session->browsing->imtu = imtu;
+ session->browsing->omtu = omtu;
+ session->browsing->buffer = g_malloc0(MAX(imtu, omtu));
session->browsing->watch = g_io_add_watch(session->browsing->io,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) session_browsing_cb, session);
@@ -732,7 +742,7 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct avctp *session = data;
char address[18];
- uint16_t imtu;
+ uint16_t imtu, omtu;
GError *gerr = NULL;
if (err) {
@@ -744,6 +754,7 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
bt_io_get(chan, &gerr,
BT_IO_OPT_DEST, &address,
BT_IO_OPT_IMTU, &imtu,
+ BT_IO_OPT_IMTU, &omtu,
BT_IO_OPT_INVALID);
if (gerr) {
avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
@@ -757,7 +768,9 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
if (session->control == NULL)
session->control = avctp_channel_create(chan);
- session->control->mtu = imtu;
+ session->control->imtu = imtu;
+ session->control->omtu = omtu;
+ session->control->buffer = g_malloc0(MAX(imtu, omtu));
session->control->watch = g_io_add_watch(session->control->io,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) session_cb, session);
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 4/7] AVCTP: Simplify channel handling
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Make both control and browsing channels to use the same structure to
store its channel information.
---
audio/avctp.c | 159 +++++++++++++++++++++++++++++-----------------------------
1 file changed, 79 insertions(+), 80 deletions(-)
diff --git a/audio/avctp.c b/audio/avctp.c
index 6fd5491..dfc5601 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -131,6 +131,12 @@ struct avctp_rsp_handler {
void *user_data;
};
+struct avctp_channel {
+ GIOChannel *io;
+ guint watch;
+ uint16_t mtu;
+};
+
struct avctp {
struct avctp_server *server;
bdaddr_t dst;
@@ -139,13 +145,8 @@ struct avctp {
int uinput;
- GIOChannel *control_io;
- GIOChannel *browsing_io;
- guint control_io_id;
- guint browsing_io_id;
-
- uint16_t control_mtu;
- uint16_t browsing_mtu;
+ struct avctp_channel *control;
+ struct avctp_channel *browsing;
uint8_t key_quirks[256];
GSList *handlers;
@@ -332,6 +333,17 @@ static struct avctp_pdu_handler *find_handler(GSList *list, uint8_t opcode)
return NULL;
}
+static void avctp_channel_destroy(struct avctp_channel *chan)
+{
+ g_io_channel_shutdown(chan->io, TRUE, NULL);
+ g_io_channel_unref(chan->io);
+
+ if (chan->watch)
+ g_source_remove(chan->watch);
+
+ g_free(chan);
+}
+
static void avctp_disconnected(struct avctp *session)
{
struct avctp_server *server;
@@ -339,36 +351,11 @@ static void avctp_disconnected(struct avctp *session)
if (!session)
return;
- if (session->browsing_io) {
- g_io_channel_shutdown(session->browsing_io, TRUE, NULL);
- g_io_channel_unref(session->browsing_io);
- session->browsing_io = NULL;
- }
-
- if (session->browsing_io_id) {
- g_source_remove(session->browsing_io_id);
- session->browsing_io_id = 0;
- }
-
- if (session->control_io) {
- g_io_channel_shutdown(session->control_io, TRUE, NULL);
- g_io_channel_unref(session->control_io);
- session->control_io = NULL;
- }
-
- if (session->control_io_id) {
- g_source_remove(session->control_io_id);
- session->control_io_id = 0;
+ if (session->browsing)
+ avctp_channel_destroy(session->browsing);
- if (session->state == AVCTP_STATE_CONNECTING) {
- struct audio_device *dev;
-
- dev = manager_get_device(&session->server->src,
- &session->dst, FALSE);
- audio_device_cancel_authorization(dev, auth_cb,
- session);
- }
- }
+ if (session->control)
+ avctp_channel_destroy(session->control);
if (session->uinput >= 0) {
char address[18];
@@ -431,7 +418,7 @@ static void avctp_set_state(struct avctp *session, avctp_state_t new_state)
}
}
-static void handle_response(struct avctp *session, struct avctp_header *avctp,
+static void control_response(struct avctp *session, struct avctp_header *avctp,
struct avc_header *avc, uint8_t *operands,
size_t operand_count)
{
@@ -467,7 +454,7 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
goto failed;
- sock = g_io_channel_unix_get_fd(session->browsing_io);
+ sock = g_io_channel_unix_get_fd(chan);
ret = read(sock, buf, sizeof(buf));
if (ret <= 0)
@@ -519,7 +506,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
goto failed;
- sock = g_io_channel_unix_get_fd(session->control_io);
+ sock = g_io_channel_unix_get_fd(chan);
ret = read(sock, buf, sizeof(buf));
if (ret <= 0)
@@ -559,7 +546,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
avc->opcode, operand_count);
if (avctp->cr == AVCTP_RESPONSE) {
- handle_response(session, avctp, avc, operands, operand_count);
+ control_response(session, avctp, avc, operands, operand_count);
return TRUE;
}
@@ -687,6 +674,16 @@ static void init_uinput(struct avctp *session)
DBG("AVRCP: uinput initialized for %s", address);
}
+static struct avctp_channel *avctp_channel_create(GIOChannel *io)
+{
+ struct avctp_channel *chan;
+
+ chan = g_new0(struct avctp_channel, 1);
+ chan->io = g_io_channel_ref(io);
+
+ return chan;
+}
+
static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
gpointer data)
{
@@ -697,10 +694,7 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
if (err) {
error("Browsing: %s", err->message);
- g_io_channel_shutdown(chan, TRUE, NULL);
- g_io_channel_unref(chan);
- session->browsing_io = NULL;
- return;
+ goto fail;
}
bt_io_get(chan, &gerr,
@@ -711,20 +705,28 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
error("%s", gerr->message);
g_io_channel_shutdown(chan, TRUE, NULL);
g_io_channel_unref(chan);
- session->browsing_io = NULL;
g_error_free(gerr);
- return;
+ goto fail;
}
DBG("AVCTP Browsing: connected to %s", address);
- if (!session->browsing_io)
- session->browsing_io = g_io_channel_ref(chan);
+ if (session->browsing == NULL)
+ session->browsing = avctp_channel_create(chan);
- session->browsing_mtu = imtu;
- session->browsing_io_id = g_io_add_watch(chan,
+ session->browsing->mtu = imtu;
+ session->browsing->watch = g_io_add_watch(session->browsing->io,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_browsing_cb, session); }
+ (GIOFunc) session_browsing_cb, session);
+
+ return;
+
+fail:
+ if (session->browsing) {
+ avctp_channel_destroy(session->browsing);
+ session->browsing = NULL;
+ }
+}
static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
@@ -752,16 +754,17 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
DBG("AVCTP: connected to %s", address);
- if (!session->control_io)
- session->control_io = g_io_channel_ref(chan);
+ if (session->control == NULL)
+ session->control = avctp_channel_create(chan);
+
+ session->control->mtu = imtu;
+ session->control->watch = g_io_add_watch(session->control->io,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) session_cb, session);
init_uinput(session);
avctp_set_state(session, AVCTP_STATE_CONNECTED);
- session->control_mtu = imtu;
- session->control_io_id = g_io_add_watch(chan,
- G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_cb, session);
}
static void auth_cb(DBusError *derr, void *user_data)
@@ -769,9 +772,9 @@ static void auth_cb(DBusError *derr, void *user_data)
struct avctp *session = user_data;
GError *err = NULL;
- if (session->control_io_id) {
- g_source_remove(session->control_io_id);
- session->control_io_id = 0;
+ if (session->control->watch > 0) {
+ g_source_remove(session->control->watch);
+ session->control->watch = 0;
}
if (derr && dbus_error_is_set(derr)) {
@@ -780,7 +783,7 @@ static void auth_cb(DBusError *derr, void *user_data)
return;
}
- if (!bt_io_accept(session->control_io, avctp_connect_cb, session,
+ if (!bt_io_accept(session->control->io, avctp_connect_cb, session,
NULL, &err)) {
error("bt_io_accept: %s", err->message);
g_error_free(err);
@@ -845,20 +848,20 @@ static struct avctp *avctp_get_internal(const bdaddr_t *src,
static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
struct audio_device *dev)
{
- if (session->control_io) {
+ if (session->control != NULL) {
error("Control: Refusing unexpected connect");
g_io_channel_shutdown(chan, TRUE, NULL);
return;
}
avctp_set_state(session, AVCTP_STATE_CONNECTING);
- session->control_io = g_io_channel_ref(chan);
+ session->control = avctp_channel_create(chan);
if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
auth_cb, session) < 0)
goto drop;
- session->control_io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
+ session->control->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
G_IO_NVAL, session_cb, session);
return;
@@ -871,7 +874,7 @@ static void avctp_browsing_confirm(struct avctp *session, GIOChannel *chan,
{
GError *err = NULL;
- if (session->control_io == NULL || session->browsing_io) {
+ if (session->control == NULL || session->browsing != NULL) {
error("Browsing: Refusing unexpected connect");
g_io_channel_shutdown(chan, TRUE, NULL);
return;
@@ -918,8 +921,8 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
DBG("AVCTP: incoming connect from %s", address);
session = avctp_get_internal(&src, &dst);
- if (!session)
- goto drop;
+ if (session == NULL)
+ return;
dev = manager_get_device(&src, &dst, FALSE);
if (!dev) {
@@ -949,13 +952,7 @@ static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
return;
drop:
- if (session && session->browsing_io)
- g_io_channel_unref(session->browsing_io);
-
- if (session && session->control_io)
- g_io_channel_unref(session->control_io);
-
- if (session && psm == AVCTP_CONTROL_PSM)
+ if (psm == AVCTP_CONTROL_PSM)
avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
}
@@ -1093,7 +1090,7 @@ int avctp_send_passthrough(struct avctp *session, uint8_t op)
operands[0] = op & 0x7f;
operands[1] = 0;
- sk = g_io_channel_unix_get_fd(session->control_io);
+ sk = g_io_channel_unix_get_fd(session->control->io);
if (write(sk, buf, sizeof(buf)) < 0)
return -errno;
@@ -1122,7 +1119,7 @@ static int avctp_send(struct avctp *session, uint8_t transaction, uint8_t cr,
if (session->state != AVCTP_STATE_CONNECTED)
return -ENOTCONN;
- sk = g_io_channel_unix_get_fd(session->control_io);
+ sk = g_io_channel_unix_get_fd(session->control->io);
memset(buf, 0, sizeof(buf));
@@ -1306,7 +1303,8 @@ struct avctp *avctp_connect(const bdaddr_t *src, const bdaddr_t *dst)
return NULL;
}
- session->control_io = io;
+ session->control = avctp_channel_create(io);
+ g_io_channel_unref(io);
return session;
}
@@ -1319,7 +1317,7 @@ int avctp_connect_browsing(struct avctp *session)
if (session->state != AVCTP_STATE_CONNECTED)
return -ENOTCONN;
- if (session->browsing_io != NULL)
+ if (session->browsing != NULL)
return 0;
io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
@@ -1334,14 +1332,15 @@ int avctp_connect_browsing(struct avctp *session)
return -EIO;
}
- session->browsing_io = io;
+ session->browsing = avctp_channel_create(io);
+ g_io_channel_unref(io);
return 0;
}
void avctp_disconnect(struct avctp *session)
{
- if (!session->control_io)
+ if (session->state == AVCTP_STATE_DISCONNECTED)
return;
avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 3/7] AVRCP: Fix not removing session from player upon disconnect
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Invalid read of size 8
at 0x1310E3: avrcp_unregister_player (avrcp.c:1604)
by 0x13EB57: path_free (media.c:1834)
by 0x123208: remove_interface.isra.1 (object.c:558)
by 0x1238DD: g_dbus_unregister_interface (object.c:705)
by 0x124BB8: media_server_remove (manager.c:1077)
by 0x4E91C5C: g_slist_foreach (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x17B349: adapter_remove (adapter.c:2309)
by 0x176F39: manager_cleanup (manager.c:290)
by 0x120E65: main (main.c:555)
Address 0x6685058 is 24 bytes inside a block of size 80 free'd
at 0x4C279AE: free (vg_replace_malloc.c:427)
by 0x4E7C50E: g_free (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x12FC97: state_changed (avrcp.c:1380)
by 0x12D351: avctp_set_state (avctp.c:396)
by 0x12D7B4: session_cb (avctp.c:601)
by 0x4E76824: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4E76B57: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4E76F51: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x120E51: main (main.c:551)
---
audio/avrcp.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 49f1550..2e36fb7 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -1328,6 +1328,11 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
avctp_unregister_browsing_pdu_handler(
session->browsing_handler);
+ if (session->player != NULL)
+ session->player->sessions = g_slist_remove(
+ session->player->sessions,
+ session);
+
g_free(session);
break;
case AVCTP_STATE_CONNECTING:
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 2/7] AVRCP: Fix not freeing player session list on exit
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1349091471-17396-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
16 bytes in 1 blocks are definitely lost in loss record 111 of 359
at 0x4A0884D: malloc (vg_replace_malloc.c:263)
by 0x4C8026E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C94671: g_slice_alloc (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C959B2: g_slist_append (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x130FCC: avrcp_register_player (avrcp.c:1584)
by 0x13FA1F: register_player (media.c:1689)
by 0x123100: process_message.isra.0 (object.c:197)
by 0x4F70684: ??? (in /usr/lib64/libdbus-1.so.3.5.6)
by 0x4F6290C: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.5.6)
by 0x121747: message_dispatch (mainloop.c:76)
by 0x4C7B22A: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7A694: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
---
audio/avrcp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 376f4a1..49f1550 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -1472,6 +1472,7 @@ static void player_destroy(gpointer data)
if (player->destroy)
player->destroy(player->user_data);
+ g_slist_free(player->sessions);
g_free(player);
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 1/7] audio: Fix not freeing gateway agent data on exit
From: Luiz Augusto von Dentz @ 2012-10-01 11:37 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
434 (168 direct, 266 indirect) bytes in 7 blocks are definitely lost in loss record 322 of 338
at 0x4A06F18: calloc (vg_replace_malloc.c:566)
by 0x4C802C6: g_malloc0 (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x126C0C: register_agent (gateway.c:673)
by 0x122960: process_message.isra.0 (object.c:197)
by 0x4F70684: ??? (in /usr/lib64/libdbus-1.so.3.5.6)
by 0x4F6290C: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.5.6)
by 0x120FA7: message_dispatch (mainloop.c:76)
by 0x4C7B22A: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7A694: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7A9C7: ??? (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x4C7ADC1: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3200.4)
by 0x120671: main (main.c:551)
---
audio/gateway.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/audio/gateway.c b/audio/gateway.c
index 45b25a1..3e606c9 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -741,6 +741,9 @@ static void path_unregister(void *data)
gateway_close(dev);
+ if (dev->gateway->agent)
+ agent_free(dev->gateway->agent);
+
g_free(dev->gateway);
dev->gateway = NULL;
}
--
1.7.11.4
^ permalink raw reply related
* Re: [PATCH v2 07/15] thermometer: Reformat MeasurementReceived description
From: Andrzej Kaczmarek @ 2012-10-01 11:32 UTC (permalink / raw)
To: Santiago Carot; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CACLukzL99YF13_+V9wemKgWVQGC8Wcj_v+41A8DWrxnK2=cfoQ@mail.gmail.com>
Hi Santiago,
On 10/01/2012 11:43 AM, Santiago Carot wrote:
> Hi Andrzej
>
> 2012/10/1 Andrzej Kaczmarek <andrzej.kaczmarek@tieto.com>:
>> MeasurementReceived method description is reformatted to be more
>> readable and consistent with other API documents.
>>
>> Special values for Exponent and Mantissa fields specify now only NaN
>> value as this is only special value defined by HTS specification for
>> measurement.
>> ---
>> doc/thermometer-api.txt | 67 +++++++++++++++++++++++++++----------------------
>> 1 file changed, 37 insertions(+), 30 deletions(-)
>>
>> diff --git a/doc/thermometer-api.txt b/doc/thermometer-api.txt
>> index 1828811..0fb28f5 100644
>> --- a/doc/thermometer-api.txt
>> +++ b/doc/thermometer-api.txt
>> @@ -97,33 +97,40 @@ Service unique name
>> Interface org.bluez.ThermometerWatcher
>> Object path freely definable
>>
>> -Methods void MeasurementReceived(dict measure)
>> -
>> - This callback gets called when a measure has been
>> - scanned in the thermometer. The Time entry in the dict
>> - will be only present if the device supports storing of
>> - data. The time value is expressed in seconds since epoch.
>> - The value represented is (mantissa) x (10**exponent)
>> - See foot note for special values when treating with
>> - health devices. The Type entry is only present if the
>> - measurement type is known. Otherwise, it is undefined.
>> -
>> - Dict is defined as below:
>> - {
>> - "Exponent" : int8,
>> - "Mantissa" : int32,
>> - "Unit" : ("Celsius" or "Fahrenheit"),
>> - "Time" : uint64,
>> - "Type" : ("Armpit", "Body", "Ear", "Finger",
>> - "Intestines", "Mouth", "Rectum", "Toe",
>> - "Tympanum"),
>> - "Measurement" : ("Final" or "Intermediate"),
>> - }
>> -
>> - For special cases, the exponent shall always be zero and
>> - the mantissa should be one of following values:
>> -
>> - NRes = -(2**23)
>> - NaN = +(2**23-1)
>> - INFINITY = (2**23-2)
>> - -INFINITY = -(2**23-2)
>> +Methods void MeasurementReceived(dict measurement)
>> +
>> + This callback gets called when a measurement has been
>> + scanned in the thermometer.
>> +
>> + Measurement:
>> +
>> + int16 Exponent:
>> + int32 Mantissa:
>> +
>> + Measurement value is calculated as
>> + (Mantissa) x (10^Exponent)
>> +
>> + In case of invalid or missing data,
>> + Exponent is set to 0 and Mantissa is
>> + set to 2^23-1 (0x7FFFFF hexadecimal).
>
> Mantissa values must not always be 2^23-1 on special cases.
> Information provided here is required for upper profiles which are
> implementing an 11073-20601 protocol layer because they have to
> differentiate among these values. In my opinion, documentation about
> passible values for the mantissa should remain as they are.
HTS specification states (see quote below) that measurement value field
may be NaN in case sensor is not able to provide valid measurement. So I
assume here that either it has valid data or NaN otherwise and thus
there's no need to specify other special values as they should not be
received here.
<quote>
The Temperature Measurement Value field may contain special float value
NaN (0x007FFFFF) defined in IEEE 11073-20601 [4] to report an invalid
result from a computation step or missing data due to the hardware’s
inability to provide a valid measurement.
</quote>
BR,
Andrzej
^ permalink raw reply
* Re: [PATCH BlueZ] build: Fix out-of-tree builds
From: Anderson Lizardo @ 2012-10-01 10:50 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1349073517.13371.43.camel@aeonflux>
Hi Marcel,
On Mon, Oct 1, 2012 at 2:38 AM, Marcel Holtmann <marcel@holtmann.org> wrote:
>> profiles/sap/sap.c: profiles/sap/@SAP_DRIVER@
>> - $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
>> + $(AM_V_GEN)$(LN_S) $(abs_top_builddir)/$< $@
>>
>> profiles/input/suspend.c: profiles/input/@HOG_SUSPEND_DRIVER@
>> $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
>
> personally I am no longer a big fan of these selection of a specific
> driver. We should be able to build all of them and make the selection at
> runtime. So there is more work needed here.
I agree, this could also help on testing as well (actually, all
drivers are built, regardless of which one was selected by configure,
but only the selected object is linked).
What do you propose? a config file option, e.g. "sap_driver=u8500" ,
"hog_suspend_driver=dummy" , etc (this could fit of the INI config
format proposal).
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [RFCv1 03/20] Bluetooth: Add L2CAP create channel request handling
From: Andrei Emeltchenko @ 2012-10-01 10:16 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth, gustavo, sunnyk
In-Reply-To: <1347387691-5285-4-git-send-email-mathewm@codeaurora.org>
Hi Mat,
On Tue, Sep 11, 2012 at 11:21:14AM -0700, Mat Martineau wrote:
> The L2CAP create channel request is very similar to an L2CAP connect
> request, but it has an additional parameter for the controller ID. If
> the controller id is 0, the channel is set up on the BR/EDR controller
> (just like a connect request). Using a valid high speed controller ID
> will cause the channel to be initially created on that high speed
> controller. While the L2CAP data will be initially routed over the
> AMP controller, the L2CAP fixed signaling channel only uses BR/EDR.
>
> When a create channel request is received for a high speed controller,
> a pending response is always sent first. After the high speed
> physical and logical links are complete a success response will be
> sent.
>
> Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
> ---
> net/bluetooth/l2cap_core.c | 70 +++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 54 insertions(+), 16 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 166382c..17e02d9 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -3362,8 +3362,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
> return 0;
> }
>
> -static void __l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
> - u8 *data, u8 rsp_code, u8 amp_id)
> +static struct l2cap_chan *__l2cap_connect(struct l2cap_conn *conn,
> + struct l2cap_cmd_hdr *cmd,
> + u8 *data, u8 rsp_code, u8 amp_id)
> {
> struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
> struct l2cap_conn_rsp rsp;
> @@ -3390,7 +3391,7 @@ static void __l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
>
> /* Check if the ACL is secure enough (if not SDP) */
> if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
> - !hci_conn_check_link_mode(conn->hcon)) {
> + !hci_conn_check_link_mode(conn->hcon)) {
> conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
> result = L2CAP_CR_SEC_BLOCK;
> goto response;
> @@ -3414,6 +3415,7 @@ static void __l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
> bacpy(&bt_sk(sk)->dst, conn->dst);
> chan->psm = psm;
> chan->dcid = scid;
> + chan->local_amp_id = amp_id;
>
> bt_accept_enqueue(parent, sk);
>
> @@ -3433,8 +3435,16 @@ static void __l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
> status = L2CAP_CS_AUTHOR_PEND;
> parent->sk_data_ready(parent, 0);
> } else {
> - __l2cap_state_change(chan, BT_CONFIG);
> - result = L2CAP_CR_SUCCESS;
> + /* Force pending result for AMP controllers.
> + * The connection will succeed after the
> + * physical link is up. */
> + if (amp_id) {
> + __l2cap_state_change(chan, BT_CONNECT2);
> + result = L2CAP_CR_PEND;
> + } else {
> + __l2cap_state_change(chan, BT_CONFIG);
> + result = L2CAP_CR_SUCCESS;
> + }
> status = L2CAP_CS_NO_INFO;
> }
> } else {
> @@ -3480,6 +3490,8 @@ sendresp:
> l2cap_build_conf_req(chan, buf), buf);
> chan->num_conf_req++;
> }
> +
> + return chan;
> }
>
> static int l2cap_connect_req(struct l2cap_conn *conn,
> @@ -3970,12 +3982,12 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
> return 0;
> }
>
> -static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
> - struct l2cap_cmd_hdr *cmd, u16 cmd_len,
> - void *data)
> +static int l2cap_create_channel_req(struct l2cap_conn *conn,
> + struct l2cap_cmd_hdr *cmd, u16 cmd_len,
> + void *data)
> {
> struct l2cap_create_chan_req *req = data;
> - struct l2cap_create_chan_rsp rsp;
> + struct l2cap_chan *chan;
> u16 psm, scid;
>
> if (cmd_len != sizeof(*req))
> @@ -3989,14 +4001,40 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
>
> BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
>
> - /* Placeholder: Always reject */
> - rsp.dcid = 0;
> - rsp.scid = cpu_to_le16(scid);
> - rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
> - rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
> + if (req->amp_id) {
> + struct hci_dev *hdev;
>
> - l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
> - sizeof(rsp), &rsp);
> + /* Validate AMP controller id */
> + hdev = hci_dev_get(req->amp_id);
> + if (!hdev || hdev->dev_type != HCI_AMP ||
> + !test_bit(HCI_UP, &hdev->flags)) {
> + struct l2cap_create_chan_rsp rsp;
> +
> + rsp.dcid = 0;
> + rsp.scid = cpu_to_le16(scid);
> + rsp.result = L2CAP_CR_BAD_AMP;
> + rsp.status = L2CAP_CS_NO_INFO;
> +
> + l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
> + sizeof(rsp), &rsp);
> +
> + if (hdev)
> + hci_dev_put(hdev);
> +
> + return 0;
> + }
> +
> + hci_dev_put(hdev);
> + }
> +
> + chan = __l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
> + req->amp_id);
> +
> + /* Placeholder - uncomment when amp functions are available
> + if (chan && req->amp_id &&
> + (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
> + amp_accept_physical(conn, req->amp_id, chan);
> + */
I believe this comment shall be deleted, we accept physical link long time
ago before this sequence.
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH] client: Add Message.MarkAsRead and Message.MarkAsDeleted implementation and documentation.
From: Luiz Augusto von Dentz @ 2012-10-01 10:04 UTC (permalink / raw)
To: Venkateswaran, Srinivasa Ragavan; +Cc: linux-bluetooth
In-Reply-To: <CAEd0BX-FANQzvTCL8WrW+YMMQNobPPMEhq1HVZrXs+r6c3k9Ng@mail.gmail.com>
Hi,
On Mon, Oct 1, 2012 at 12:05 PM, Venkateswaran, Srinivasa Ragavan
<srinivasa.ragavan.venkateswaran@intel.com> wrote:
>> 1. Use properties, so for setting delete/read the application should
>> use SetProperty method and it can get the values with GetProperties
>> and PropertyChanged to signal when the values has changed. (Note this
>> may change if we add support to standard D-Bus Properties interface
>> but the idea is the same just the interface change)
>
> I'll do it as SetProperty ("read/deleted", true/false) . But I don't
> see a support in MAP ('s spec) for getting a message status or being
> notified for message update. If you can point me, I could do this also
> and give a complete patch the Message object.
Yep, it is not in the spec, but it doesn't mean we should not have
support for getting updates asynchronously as signals because
different processes can change the properties and in future if this is
added in the spec we already have support for them, besides it is
consistent with overall use of properties.
>> 2. What is this filler byte and lseek for?
>
> lseek was because, after just we write to the file, the read always
> failed and I thought the position was the end of the file. I just seek
> to the beginning of the file, it worked. I hope I didn't overlook
> something.
Yep, it is actually a bug so could you please have it in a separate patch?
>> 3. We probably need to add support for non-body/apparam only PUT so we
>> can pass NULL to filename. (maybe this is the reason for 2?)
>
> For SetMessageStatus the spec mentioned that Body/End of Body,
> specifying the filler byte 0x30 is mandatory. Quoting from the spec
> below:
> "To avoid PUT with empty Body leading to a 'delete' of the related message these
> headers shall contain a filler byte. The value of this byte shall be
> set to 0x30 (="0")."
>
> If it wasn't for this, I would have updated PUT with support to empty
> body. I assume, this is fine.
Yep, very strange requirement to be honest but I guess the author was
afraid the OBEX parser would trigger delete of the message if no body
was found, anyway sending 0x30 is mandatory so we should include as
you did. Still I think the proper way to support this is to have
obc_transfer_put supporting NULL filename, in that case the caller
need to provide the contents which should be stored in a temporary
which is automatically removed (transfer_open already takes care of
this).
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH BlueZ] gatt: Remove offset parameter from gatt_read_char
From: Johan Hedberg @ 2012-10-01 9:55 UTC (permalink / raw)
To: Jefferson Delfes; +Cc: linux-bluetooth
In-Reply-To: <1348864484-30206-1-git-send-email-jefferson.delfes@openbossa.org>
Hi Jefferson,
On Fri, Sep 28, 2012, Jefferson Delfes wrote:
> The Core spec allows to implement Read Long Characteristic Value as a
> Read Request, followed by zero or more Read Blob Requests, therefore the
> offset parameter is unnecessary and is always 0 for normal use.
> ---
> attrib/client.c | 12 ++++++------
> attrib/gatt.c | 15 ++++-----------
> attrib/gatt.h | 4 ++--
> attrib/gatttool.c | 5 +----
> attrib/interactive.c | 16 ++--------------
> profiles/deviceinfo/deviceinfo.c | 2 +-
> profiles/heartrate/heartrate.c | 2 +-
> profiles/input/hog_device.c | 12 ++++++------
> profiles/proximity/monitor.c | 4 ++--
> profiles/thermometer/thermometer.c | 8 ++++----
> 10 files changed, 29 insertions(+), 51 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [RFC BlueZ v0 0/4] Remove profile specific storage
From: Johan Hedberg @ 2012-10-01 9:54 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1348862494-16911-1-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Fri, Sep 28, 2012, Claudio Takahasi wrote:
> There is also a TODO file item: "Convert storage to user per-remote
> device directories and ini-file format". What is the idea? Should the
> core remove everything under the remote device address directory?
I hadn't thought of that previously (i.e. it's not the reason for the
proposed layout) but now that you mention it I think that'd be a nicer
way of handling this. I.e. let's let the core remove the per-device
directory and everything stored inside it so that the drivers themselves
do not need to differentiate between bluetoothd exit and device removal.
Johan
^ permalink raw reply
* Re: [PATCH v2 07/15] thermometer: Reformat MeasurementReceived description
From: Santiago Carot @ 2012-10-01 9:43 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1349083437-23528-8-git-send-email-andrzej.kaczmarek@tieto.com>
Hi Andrzej
2012/10/1 Andrzej Kaczmarek <andrzej.kaczmarek@tieto.com>:
> MeasurementReceived method description is reformatted to be more
> readable and consistent with other API documents.
>
> Special values for Exponent and Mantissa fields specify now only NaN
> value as this is only special value defined by HTS specification for
> measurement.
> ---
> doc/thermometer-api.txt | 67 +++++++++++++++++++++++++++----------------------
> 1 file changed, 37 insertions(+), 30 deletions(-)
>
> diff --git a/doc/thermometer-api.txt b/doc/thermometer-api.txt
> index 1828811..0fb28f5 100644
> --- a/doc/thermometer-api.txt
> +++ b/doc/thermometer-api.txt
> @@ -97,33 +97,40 @@ Service unique name
> Interface org.bluez.ThermometerWatcher
> Object path freely definable
>
> -Methods void MeasurementReceived(dict measure)
> -
> - This callback gets called when a measure has been
> - scanned in the thermometer. The Time entry in the dict
> - will be only present if the device supports storing of
> - data. The time value is expressed in seconds since epoch.
> - The value represented is (mantissa) x (10**exponent)
> - See foot note for special values when treating with
> - health devices. The Type entry is only present if the
> - measurement type is known. Otherwise, it is undefined.
> -
> - Dict is defined as below:
> - {
> - "Exponent" : int8,
> - "Mantissa" : int32,
> - "Unit" : ("Celsius" or "Fahrenheit"),
> - "Time" : uint64,
> - "Type" : ("Armpit", "Body", "Ear", "Finger",
> - "Intestines", "Mouth", "Rectum", "Toe",
> - "Tympanum"),
> - "Measurement" : ("Final" or "Intermediate"),
> - }
> -
> - For special cases, the exponent shall always be zero and
> - the mantissa should be one of following values:
> -
> - NRes = -(2**23)
> - NaN = +(2**23-1)
> - INFINITY = (2**23-2)
> - -INFINITY = -(2**23-2)
> +Methods void MeasurementReceived(dict measurement)
> +
> + This callback gets called when a measurement has been
> + scanned in the thermometer.
> +
> + Measurement:
> +
> + int16 Exponent:
> + int32 Mantissa:
> +
> + Measurement value is calculated as
> + (Mantissa) x (10^Exponent)
> +
> + In case of invalid or missing data,
> + Exponent is set to 0 and Mantissa is
> + set to 2^23-1 (0x7FFFFF hexadecimal).
Mantissa values must not always be 2^23-1 on special cases.
Information provided here is required for upper profiles which are
implementing an 11073-20601 protocol layer because they have to
differentiate among these values. In my opinion, documentation about
passible values for the mantissa should remain as they are.
Regards
^ permalink raw reply
* [PATCH v3] Cycling Speed and Cadence profile (CSCP) API
From: Andrzej Kaczmarek @ 2012-10-01 9:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1349084621-25284-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
doc/cycling-api.txt | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
create mode 100644 doc/cycling-api.txt
diff --git a/doc/cycling-api.txt b/doc/cycling-api.txt
new file mode 100644
index 0000000..5b3cfc2
--- /dev/null
+++ b/doc/cycling-api.txt
@@ -0,0 +1,118 @@
+Cycling Speed and Cadence API description
+*****************************************
+
+Copyright (C) 2012 Tieto Poland
+
+Cycling Speed and Cadence Manager hierarchy
+===========================================
+
+Service org.bluez
+Interface org.bluez.CyclingSpeedManager
+Object path [variable prefix]/{hci0,hci1,...}
+
+Methods RegisterWatcher(object agent)
+
+ Registers a watcher to monitor cycling speed and cadence
+ measurements.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ UnregisterWatcher(object agent)
+
+ Unregisters a watcher.
+
+Cycling Speed and Cadence Profile hierarchy
+===========================================
+
+Service org.bluez
+Interface org.bluez.CyclingSpeed
+Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Methods void SetProperty(string name, variant value)
+
+ Changes the value of the specified property. Only
+ read-write properties can be changed. On success
+ this will emit a PropertyChanged signal.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ dict GetProperties()
+
+ Returns all properties for the interface. See the
+ Properties section for the available properties.
+
+ SetCumulativeWheelRevolutions(uint32 value)
+
+ Sets cumulative wheel revolutions value if
+ Cumulative Wheel Revolutions feature is supported.
+
+ Possible Errors: org.bluez.Error.NotSupported
+
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
+Properties string Location (optional) [readwrite]
+
+ Current sensor location, if supported.
+ If Multiple Sensor Locations feature is supported,
+ this property can be set to one of values read from
+ SupportedLocations property.
+
+ Possible values: "other", "top-of-shoe", "in-shoe",
+ "hip", "front-wheel", "left-crank",
+ "right-crank", "left-pedal",
+ "right-pedal", "front-hub",
+ "rear-dropout", "chainstay",
+ "rear-wheel", "rear-hub"
+
+ array{string} SupportedLocations (optional) [readonly]
+
+ List of locations supported by sensor, only present
+ if Multiple Sensor Locations feature is supported.
+
+ boolean WheelRevolutionDataSupported [readonly]
+
+ true if sensor can read and set Cumulative Wheel
+ Revolutions value, false otherwise.
+
+ boolean MultipleSensorLocationsSupported [readonly]
+
+ true if sensor supports Multiple Sensor Locations
+ feature and can set Location, false otherwise.
+
+Cycling Speed and Cadence Watcher hierarchy
+===========================================
+
+Service unique name
+Interface org.bluez.CyclingSpeedWatcher
+Object path freely definable
+
+Methods void MeasurementReceived(object device, dict measurement)
+
+ This callback is called whenever wheel and/or crank
+ revolutions measurement is received from sensor.
+
+ Measurement:
+
+ uint32 WheelRevolutions (optional):
+
+ Cumulative number of wheel revolutions.
+
+ uint16 LastWheelEventTime (optional):
+
+ Time of last event from wheel sensor.
+ Value is expressed in 1/1024 second
+ units and can roll over during a ride.
+
+ uint16 CrankRevolutions (optional):
+
+ Cumulative number of crank revolutions.
+ This value can occasionally roll over.
+
+ uint16 LastCrankEventTime (optional):
+
+ Time of last event from crank sensor.
+ Value is expressed in 1/1024 second
+ units and can roll over during a ride.
--
1.7.11.3
^ permalink raw reply related
* [RFC v3] Cycling Speed and Cadence profile (CSCP) API
From: Andrzej Kaczmarek @ 2012-10-01 9:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
Hi,
Changes since v2:
- changed string properties to lower-case
- fixed some formatting inconsistencies
Comments are welcome.
Andrzej Kaczmarek (1):
Cycling Speed and Cadence profile (CSCP) API
doc/cycling-api.txt | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
create mode 100644 doc/cycling-api.txt
--
1.7.11.3
^ permalink raw reply
* [PATCH v2 15/15] thermometer: Fix missing braces
From: Andrzej Kaczmarek @ 2012-10-01 9:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1349083437-23528-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 9028fa1..edcd42d 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -335,8 +335,9 @@ static void change_property(struct thermometer *t, const char *name,
emit_property_changed(device_get_path(t->dev),
THERMOMETER_INTERFACE, name,
DBUS_TYPE_UINT16, &t->min);
- } else
+ } else {
DBG("%s is not a thermometer property", name);
+ }
}
static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
@@ -421,8 +422,9 @@ static void process_thermometer_desc(struct descriptor *desc)
val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
msg = g_strdup("Enable Measurement Interval "
"indication");
- } else
+ } else {
goto done;
+ }
att_put_u16(val, atval);
gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
@@ -548,12 +550,13 @@ static void process_thermometer_char(struct characteristic *ch)
gboolean intermediate = TRUE;
change_property(ch->t, "Intermediate", &intermediate);
return;
- } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
+ } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0) {
gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
read_temp_type_cb, ch);
- else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+ } else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0) {
gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
read_interval_cb, ch);
+ }
}
static void configure_thermometer_cb(GSList *characteristics, guint8 status,
@@ -591,10 +594,11 @@ static void configure_thermometer_cb(GSList *characteristics, guint8 status,
if (start == c->handle)
continue;
end = c->handle - 1;
- } else if (c->value_handle != t->svc_range->end)
+ } else if (c->value_handle != t->svc_range->end) {
end = t->svc_range->end;
- else
+ } else {
continue;
+ }
gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
}
--
1.7.11.3
^ permalink raw reply related
* [PATCH v2 14/15] thermometer: Fix indentation
From: Andrzej Kaczmarek @ 2012-10-01 9:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1349083437-23528-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 71c6567..9028fa1 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -83,7 +83,7 @@ struct thermometer {
};
struct characteristic {
- struct gatt_char attr; /* Characteristic */
+ struct gatt_char attr; /* Characteristic */
GSList *desc; /* Descriptors */
struct thermometer *t; /* Thermometer where the char belongs */
};
--
1.7.11.3
^ permalink raw reply related
* [PATCH v2 13/15] thermometer: Fix whitespace
From: Andrzej Kaczmarek @ 2012-10-01 9:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1349083437-23528-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
profiles/thermometer/thermometer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 3ec413b..71c6567 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -634,7 +634,7 @@ static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
return reply;
}
-static void write_interval_cb (guint8 status, const guint8 *pdu, guint16 len,
+static void write_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
struct tmp_interval_data *data = user_data;
--
1.7.11.3
^ permalink raw reply related
* [PATCH v2 12/15] thermometer: Refactor processing of measurement characteristic value
From: Andrzej Kaczmarek @ 2012-10-01 9:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1349083437-23528-1-git-send-email-andrzej.kaczmarek@tieto.com>
Data buffer is read by simply moving buffer pointer instead of calculating
indexes of consecutive fields. This makes function flow easier to follow
as there's no need to care about presence of fields prior to current when
reading data.
---
profiles/thermometer/thermometer.c | 66 +++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 29 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 43c14b0..3ec413b 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1021,27 +1021,37 @@ static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
uint16_t len, gboolean final)
{
struct measurement m;
- const char *type;
+ const char *type = NULL;
uint8_t flags;
uint32_t raw;
- if (len < 4) {
+ /* skip opcode and handle */
+ pdu += 3;
+ len -= 3;
+
+ if (len < 1) {
DBG("Mandatory flags are not provided");
return;
}
- flags = pdu[3];
+ flags = *pdu;
+
if (flags & TEMP_UNITS)
m.unit = "fahrenheit";
else
m.unit = "celsius";
- if (len < 8) {
- DBG("Temperature measurement value is not provided");
+ pdu++;
+ len--;
+
+ if (len < 4) {
+ DBG("Mandatory temperature measurement value is not provided");
return;
}
- raw = att_get_u32(&pdu[4]);
+ memset(&m, 0, sizeof(m));
+
+ raw = att_get_u32(pdu);
m.mant = raw & 0x00FFFFFF;
m.exp = ((int32_t) raw) >> 24;
@@ -1050,48 +1060,46 @@ static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
m.mant = m.mant - FLOAT_MAX_MANTISSA;
}
+ pdu += 4;
+ len -= 4;
+
if (flags & TEMP_TIME_STAMP) {
struct tm ts;
time_t time;
- if (len < 15) {
- DBG("Can't get time stamp value");
+ if (len < 7) {
+ DBG("Time stamp is not provided");
return;
}
- ts.tm_year = att_get_u16(&pdu[8]) - 1900;
- ts.tm_mon = pdu[10] - 1;
- ts.tm_mday = pdu[11];
- ts.tm_hour = pdu[12];
- ts.tm_min = pdu[13];
- ts.tm_sec = pdu[14];
+ ts.tm_year = att_get_u16(pdu) - 1900;
+ ts.tm_mon = *(pdu + 2) - 1;
+ ts.tm_mday = *(pdu + 3);
+ ts.tm_hour = *(pdu + 4);
+ ts.tm_min = *(pdu + 5);
+ ts.tm_sec = *(pdu + 6);
ts.tm_isdst = -1;
time = mktime(&ts);
m.time = (uint64_t) time;
m.suptime = TRUE;
- } else
- m.suptime = FALSE;
+
+ pdu += 7;
+ len -= 7;
+ }
if (flags & TEMP_TYPE) {
- uint8_t index;
-
- if (m.suptime && len >= 16)
- index = 15;
- else if (!m.suptime && len >= 9)
- index = 9;
- else {
- DBG("Can't get temperature type");
+ if (len < 1) {
+ DBG("Temperature type is not provided");
return;
}
- type = temptype2str(pdu[index]);
- } else if (t->has_type)
+ type = temptype2str(*pdu);
+ } else if (t->has_type) {
type = temptype2str(t->type);
- else
- type = NULL;
+ }
- m.type = type ? g_strdup(type) : NULL;
+ m.type = g_strdup(type);
m.value = final ? "final" : "intermediate";
recv_measurement(t, &m);
--
1.7.11.3
^ permalink raw reply related
* [PATCH v2 11/15] thermometer: Add common function to write characteristics CCC
From: Andrzej Kaczmarek @ 2012-10-01 9:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1349083437-23528-1-git-send-email-andrzej.kaczmarek@tieto.com>
There are now few separate functions to write CCC for measurement
characteristics which looks similar. This patch adds common function
to write given value into CCC for given characteristics and leaves
dedicated functions to act only as simple wrappers.
---
profiles/thermometer/thermometer.c | 108 ++++++++-----------------------------
1 file changed, 23 insertions(+), 85 deletions(-)
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 27effc3..43c14b0 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -376,7 +376,7 @@ static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
change_property(desc->ch->t, "Minimum", &min);
}
-static void measurement_cb(guint8 status, const guint8 *pdu,
+static void write_ccc_cb(guint8 status, const guint8 *pdu,
guint16 len, gpointer user_data)
{
char *msg = user_data;
@@ -426,7 +426,7 @@ static void process_thermometer_desc(struct descriptor *desc)
att_put_u16(val, atval);
gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
- measurement_cb, msg);
+ write_ccc_cb, msg);
return;
}
@@ -720,9 +720,8 @@ static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
return write_attr_interval(t, msg, value);
}
-static void enable_final_measurement(gpointer data, gpointer user_data)
+static void write_ccc(struct thermometer *t, const char *uuid, uint16_t value)
{
- struct thermometer *t = data;
struct characteristic *ch;
struct descriptor *desc;
bt_uuid_t btuuid;
@@ -732,116 +731,55 @@ static void enable_final_measurement(gpointer data, gpointer user_data)
if (t->attrib == NULL)
return;
- ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+ ch = get_characteristic(t, uuid);
if (ch == NULL) {
- DBG("Temperature measurement characteristic not found");
+ DBG("Characteristic %s not found", uuid);
return;
}
bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
desc = get_descriptor(ch, &btuuid);
if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
+ DBG("CCC descriptor for %s not found", uuid);
return;
}
- atval[0] = 0x02;
- atval[1] = 0x00;
- msg = g_strdup("Enable final measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ att_put_u16(value, atval);
+
+ msg = g_strdup_printf("Write CCC: %04x for %s", value, uuid);
+
+ gatt_write_char(t->attrib, desc->handle, atval, sizeof(atval),
+ write_ccc_cb, msg);
}
-static void enable_intermediate_measurement(gpointer data, gpointer user_data)
+static void enable_final_measurement(gpointer data, gpointer user_data)
{
struct thermometer *t = data;
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL || !t->intermediate)
- return;
- ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
- if (ch == NULL) {
- DBG("Intermediate measurement characteristic not found");
- return;
- }
+ write_ccc(t, TEMPERATURE_MEASUREMENT_UUID,
+ GATT_CLIENT_CHARAC_CFG_IND_BIT);
+}
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
+static void enable_intermediate_measurement(gpointer data, gpointer user_data)
+{
+ struct thermometer *t = data;
- atval[0] = 0x01;
- atval[1] = 0x00;
- msg = g_strdup("Enable intermediate measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ write_ccc(t, INTERMEDIATE_TEMPERATURE_UUID,
+ GATT_CLIENT_CHARAC_CFG_NOTIF_BIT);
}
static void disable_final_measurement(gpointer data, gpointer user_data)
{
struct thermometer *t = data;
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
- if (ch == NULL) {
- DBG("Temperature measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
-
- atval[0] = 0x00;
- atval[1] = 0x00;
- msg = g_strdup("Disable final measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ write_ccc(t, TEMPERATURE_MEASUREMENT_UUID, 0x0000);
}
static void disable_intermediate_measurement(gpointer data, gpointer user_data)
{
struct thermometer *t = data;
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
- if (ch == NULL) {
- DBG("Intermediate measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
- atval[0] = 0x00;
- atval[1] = 0x00;
- msg = g_strdup("Disable intermediate measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+ write_ccc(t, INTERMEDIATE_TEMPERATURE_UUID, 0x0000);
}
static void remove_int_watcher(struct thermometer_adapter *tadapter,
--
1.7.11.3
^ 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