* Re: [PATCH v2 0/6] Audio profile authorization
From: Luiz Augusto von Dentz @ 2012-09-27 8:00 UTC (permalink / raw)
To: Mikel Astiz; +Cc: linux-bluetooth, Mikel Astiz
In-Reply-To: <1348584946-13895-1-git-send-email-mikel.astiz.oss@gmail.com>
Hi Mikel,
On Tue, Sep 25, 2012 at 5:55 PM, Mikel Astiz <mikel.astiz.oss@gmail.com> wrote:
> From: Mikel Astiz <mikel.astiz@bmw-carit.de>
>
> v2 includes the modification suggested by Luiz:
> - Variable renaming from auth_id to id
> - Use of g_queue_free_full, requiring a dependency update to glib 2.32
>
> 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 (6):
> build: Update glib dependency to 2.32
> audio: Fix crash on gateway close
> adapter: Replace device authorizing flag
> adapter: Use authorization id for cancelling
> adapter: Queue parallel authorization requests
> audio: Drop audio-specific authorization mechanism
>
> acinclude.m4 | 4 +-
> audio/avctp.c | 29 +++-----
> audio/avdtp.c | 25 +++++--
> audio/device.c | 144 ------------------------------------
> audio/device.h | 12 +--
> audio/gateway.c | 3 +
> audio/manager.c | 18 +++--
> plugins/service.c | 18 +++--
> profiles/input/server.c | 2 +-
> src/adapter.c | 193 +++++++++++++++++++++++++++++++-----------------
> src/adapter.h | 2 +-
> src/device.c | 11 ---
> src/device.h | 2 -
> 13 files changed, 183 insertions(+), 280 deletions(-)
>
> --
> 1.7.11.4
Apparently this patches don't apply anymore, please update them.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH v2 2/6] audio: Fix crash on gateway close
From: Luiz Augusto von Dentz @ 2012-09-27 8:00 UTC (permalink / raw)
To: Mikel Astiz; +Cc: linux-bluetooth, Mikel Astiz
In-Reply-To: <1348584946-13895-3-git-send-email-mikel.astiz.oss@gmail.com>
Hi Mikel,
On Tue, Sep 25, 2012 at 5:55 PM, Mikel Astiz <mikel.astiz.oss@gmail.com> wrote:
> 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 file changed, 3 insertions(+)
>
> 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.11.4
There is something wrong if this is being called multiple times, so we
need to find the root cause of this happening and fix there.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCHv1 3/3] Bluetooth: btmrvl: Fix skb buffer overflow
From: Andrei Emeltchenko @ 2012-09-27 7:51 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1348732308-29348-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add extra check to avoid skb buffer overflow. Fixes crash below:
[ 101.030427] ------------[ cut here ]------------
[ 101.030459] kernel BUG at net/core/skbuff.c:127!
[ 101.030486] invalid opcode: 0000 [#1] SMP
...
[ 101.030806] Pid: 2010, comm: btmrvl_main_ser Not tainted 3.5.0+ #80 Laptop
[ 101.030859] EIP: 0060:[<c14f2ba9>] EFLAGS: 00010282 CPU: 0
[ 101.030894] EIP is at skb_put+0x99/0xa0
[ 101.030919] EAX: 00000080 EBX: f129380b ECX: ef923540 EDX: 00000001
[ 101.030956] ESI: f00a4000 EDI: 00001003 EBP: ed4a5efc ESP: ed4a5ecc
[ 101.030992] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 101.031024] CR0: 8005003b CR2: 08fca014 CR3: 30960000 CR4: 000407f0
[ 101.031062] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 101.031100] DR6: ffff0ff0 DR7: 00000400
[ 101.031125] Process btmrvl_main_ser (pid: 2010, ti=ed4a4000 task=ef923540 task.ti=ed4a4000)
[ 101.031174] Stack:
[ 101.031188] c18126f8 c1651938 f853f8d2 00001003 00001003 f1292800 f1292808 f129380b
[ 101.031250] f1292940 f00a4000 eddb1280 efc0f9c0 ed4a5f44 f853f8d2 00000040 00000000
[ 101.031312] ef923540 c15ee096 ef923540 eddb12d4 00000004 f00a4000 00000040 00000000
[ 101.031376] Call Trace:
[ 101.031396] [<f853f8d2>] ? btmrvl_sdio_process_int_status+0x272/0x3d0 [btmrvl_sdio]
[ 101.031444] [<f853f8d2>] btmrvl_sdio_process_int_status+0x272/0x3d0 [btmrvl_sdio]
[ 101.031488] [<c15ee096>] ? _raw_spin_unlock_irqrestore+0x36/0x70
[ 101.031526] [<f85a46e4>] btmrvl_service_main_thread+0x244/0x300 [btmrvl]
[ 101.031568] [<f853fb50>] ? btmrvl_sdio_poll_card_status.isra.6.constprop.7+0x90/0x90 [btmrvl_sdio]
[ 101.031619] [<c107eda0>] ? try_to_wake_up+0x270/0x270
[ 101.031648] [<f85a44a0>] ? btmrvl_process_event+0x3b0/0x3b0 [btmrvl]
[ 101.031686] [<c106d19d>] kthread+0x7d/0x90
[ 101.031713] [<c106d120>] ? flush_kthread_work+0x150/0x150
[ 101.031745] [<c15f5a82>] kernel_thread_helper+0x6/0x10
...
[ 101.032008] EIP: [<c14f2ba9>] skb_put+0x99/0xa0 SS:ESP 0068:ed4a5ecc
[ 101.056125] ---[ end trace a0bd01d1a9a796c8 ]---
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
drivers/bluetooth/btmrvl_sdio.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 1457f25..b3b3680 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -554,7 +554,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
*/
buf_len = payload[0];
- buf_len |= (u16) payload[1] << 8;
+ buf_len |= payload[1] << 8;
+ buf_len |= payload[2] << 16;
+
+ if (buf_len > blksz * num_blocks) {
+ BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
+ buf_len, blksz * num_blocks);
+ ret = -EIO;
+ goto exit;
+ }
+
type = payload[3];
BT_DBG("%s len %zu type %d", hdev->name, buf_len, type);
--
1.7.9.5
^ permalink raw reply related
* [PATCHv1 2/3] Bluetooth: btmrvl: Use DIV_ROUND_UP macro
From: Andrei Emeltchenko @ 2012-09-27 7:51 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1348732308-29348-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
The kernel.h macro DIV_ROUND_UP performs the computation
(((n) + (d) - 1) / (d))
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
drivers/bluetooth/btmrvl_sdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 25dc53b..1457f25 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -516,7 +516,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
BT_DBG("%s buf_len %zu", hdev->name, buf_len);
blksz = SDIO_BLOCK_SIZE;
- num_blocks = (buf_len + blksz - 1) / blksz;
+ num_blocks = DIV_ROUND_UP(buf_len, blksz);
if (buf_len <= SDIO_HEADER_LEN
|| (num_blocks * blksz) > ALLOC_BUF_SIZE) {
--
1.7.9.5
^ permalink raw reply related
* [PATCHv1 1/3] Bluetooth: btmrvl: Correct num_block name
From: Andrei Emeltchenko @ 2012-09-27 7:51 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Make code readable by correcting name from buf_block_len to num_blocks
since it represent number of blocks; NOT a length of a block buffer.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
drivers/bluetooth/btmrvl_sdio.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index da4df9c..25dc53b 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -492,7 +492,7 @@ done:
static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
{
u16 buf_len = 0;
- int ret, buf_block_len, blksz;
+ int ret, num_blocks, blksz;
struct sk_buff *skb = NULL;
u32 type;
u8 *payload = NULL;
@@ -516,18 +516,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
BT_DBG("%s buf_len %zu", hdev->name, buf_len);
blksz = SDIO_BLOCK_SIZE;
- buf_block_len = (buf_len + blksz - 1) / blksz;
+ num_blocks = (buf_len + blksz - 1) / blksz;
if (buf_len <= SDIO_HEADER_LEN
- || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+ || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
BT_ERR("invalid packet length: %d", buf_len);
ret = -EINVAL;
goto exit;
}
/* Allocate buffer */
- skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
- GFP_ATOMIC);
+ skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
if (skb == NULL) {
BT_ERR("No free skb");
goto exit;
@@ -543,7 +542,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
payload = skb->data;
ret = sdio_readsb(card->func, payload, card->ioport,
- buf_block_len * blksz);
+ num_blocks * blksz);
if (ret < 0) {
BT_ERR("readsb failed: %d", ret);
ret = -EIO;
@@ -594,7 +593,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
default:
BT_ERR("Unknown packet type:%d", type);
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
- blksz * buf_block_len);
+ blksz * num_blocks);
kfree_skb(skb);
skb = NULL;
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH BlueZ v7 2/9] mgmt: Add LE scanning callback
From: Johan Hedberg @ 2012-09-27 7:43 UTC (permalink / raw)
To: João Paulo Rechi Vita; +Cc: linux-bluetooth, Claudio Takahasi
In-Reply-To: <1348594686-26221-2-git-send-email-jprvita@openbossa.org>
Hi,
On Tue, Sep 25, 2012, João Paulo Rechi Vita wrote:
> +int mgmt_start_scanning(int index)
Firstly I don't think the name is good since BR/EDR also has the concept
of scanning (page scan & inquiry scan). Secondly, maybe it'd be simpler
to reuse mgmt_start_discovery and simply add a new parameter which
provides the value for info->discov_type?
Johan
^ permalink raw reply
* Re: [PATCH BlueZ v7 1/9] core: Mutually exclude concurrent connections
From: Johan Hedberg @ 2012-09-27 7:42 UTC (permalink / raw)
To: João Paulo Rechi Vita; +Cc: linux-bluetooth
In-Reply-To: <1348594686-26221-1-git-send-email-jprvita@openbossa.org>
Hi,
On Tue, Sep 25, 2012, João Paulo Rechi Vita wrote:
> Since controllers don't support more than one ongoing connection
> procedure at the same time, new connection attempts needs to yield if
> there is an ongoing connection procedure already.
Simply based on this description the first question that comes to mind
is wouldn't this be better handled on the kernel side? After all other
processes besides bluetoothd (like obexd) are also capable of initiating
connections and we can't control that within bluetoothd.
Johan
^ permalink raw reply
* Re: [PATCH BlueZ v7 7/9] core: Re-connect for ECONNRESET or ECONNABORTED
From: Johan Hedberg @ 2012-09-27 7:41 UTC (permalink / raw)
To: João Paulo Rechi Vita; +Cc: linux-bluetooth, Claudio Takahasi
In-Reply-To: <1348594686-26221-7-git-send-email-jprvita@openbossa.org>
Hi,
On Tue, Sep 25, 2012, João Paulo Rechi Vita wrote:
> + /*
> + * Keep scanning/re-connection active if disconnection reason
> + * is page timeout, remote user terminated connection or local
> + * initiated disconnection.
> + */
> + if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
> + adapter_connect_list_add(device_get_adapter(device), device);
Page timeouts have always been reported through EHOSTDOWN so either the
comment or the code is wrong here.
Johan
^ permalink raw reply
* Re: [PATCH BlueZ v7 5/9] core: Queue discovery if scanning is active
From: Vinicius Costa Gomes @ 2012-09-27 3:16 UTC (permalink / raw)
To: João Paulo Rechi Vita; +Cc: linux-bluetooth, Claudio Takahasi
In-Reply-To: <1348594686-26221-5-git-send-email-jprvita@openbossa.org>
Hi João, Claudio,
On 14:38 Tue 25 Sep, João Paulo Rechi Vita wrote:
> From: Claudio Takahasi <claudio.takahasi@openbossa.org>
>
> This patch manages BR/EDR inquiry and BLE scanning discovery sessions.
> A scanning session is added in the discovery session list when there is
> a bonded device which requires re-connection.
>
> bluetoothd decides if interleaved or scanning needs to be executed based
> on the queued discovery sessions. Interleaved discovery has higher
> priority, scanning only is executed when there is only a scanning
> session active.
> ---
> src/adapter.c | 65 ++++++++++++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 46 insertions(+), 19 deletions(-)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index 201e6a0..0a0ac8f 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -132,6 +132,7 @@ struct btd_adapter {
> GSList *devices; /* Devices structure pointers */
> GSList *mode_sessions; /* Request Mode sessions */
> GSList *disc_sessions; /* Discovery sessions */
> + struct session_req *scanning_session;
> GSList *connect_list; /* Devices to connect when found */
> guint discov_id; /* Discovery timer */
> gboolean discovering; /* Discovery active */
> @@ -221,17 +222,18 @@ static struct session_req *create_session(struct btd_adapter *adapter,
> DBusMessage *msg, uint8_t mode,
> GDBusWatchFunction cb)
> {
> - const char *sender = dbus_message_get_sender(msg);
> + const char *sender;
> struct session_req *req;
>
> req = g_new0(struct session_req, 1);
> req->adapter = adapter;
> - req->msg = dbus_message_ref(msg);
> req->mode = mode;
>
> - if (cb == NULL)
> + if (cb == NULL || msg == NULL)
> return session_ref(req);
Sorry for taking so long to notice this, but there is a problem here.
'req->msg' is needed in 'set_mode_complete()' (around adapter.c:2329) even
when 'cb' is NULL: when setting the "Powered" or "Discoverable" property,
the session created doesn't have a 'cb' but it has a 'msg'.
[snip]
Cheers,
--
Vinicius
^ permalink raw reply
* Re: Agenda (v2) for Linux Wireless (802.11/Bluetooth/NFC) Mini-Summit 2012 (Barcelona!)
From: John W. Linville @ 2012-09-26 19:58 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-wireless, linux-bluetooth, alexander.smirnov
In-Reply-To: <1348147820.13371.2.camel@aeonflux>
On Thu, Sep 20, 2012 at 03:30:20PM +0200, Marcel Holtmann wrote:
> Hi John,
>
> > OK, making progress...still, we need some more discussion topics...
> >
> > We have one room on the first day, and three rooms on the second day.
> > I figure that the Bluetooth and 802.11 groups should each get a
> > break-out room for their own in-depth discussons on the second day and
> > the third room can be used for more general topics and presentations.
> >
> > Below is my strawman agenda proposal. Please make suggestions for
> > improvements!
>
> I think this looks pretty good. Lets see if we can find some volunteers
> for the empty slots. Should be make sure that this schedule so far gets
> published on the LinuxCon website?
OK, I have transferred the existing schedule to wireless.kernel.org:
http://wireless.kernel.org/en/developers/Summits/Barcelona-2012
Please note that this is a wiki, so anyone can edit it. If you
(i.e. anyone) have suggestions for organizational/schedule changes or
(even better) _more_ or different discussions topics, then please
feel free to add them!
Also, I would appreciate it if everyone planning to attend could add
their name to the list of attendees.
Thanks,
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: [PATCH BlueZ] build: Fix make distcheck for src/profile.c
From: Johan Hedberg @ 2012-09-26 18:36 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1348683762-28057-1-git-send-email-anderson.lizardo@openbossa.org>
Hi Lizardo,
On Wed, Sep 26, 2012, Anderson Lizardo wrote:
> Fix this "make distcheck" error:
>
> ../src/profile.c:39:18: fatal error: uuid.h: No such file or directory
> ---
> src/profile.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Good catch, thanks! The patch is now upstream.
Johan
^ permalink raw reply
* [PATCH BlueZ] build: Fix make distcheck for src/profile.c
From: Anderson Lizardo @ 2012-09-26 18:22 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
Fix this "make distcheck" error:
../src/profile.c:39:18: fatal error: uuid.h: No such file or directory
---
src/profile.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/profile.c b/src/profile.c
index 4e84d19..ad2ad4a 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -34,9 +34,9 @@
#include <gdbus.h>
#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
#include "btio.h"
-#include "uuid.h"
#include "log.h"
#include "error.h"
#include "dbus-common.h"
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH BlueZ V7 1/5] AVRCP: Add TG Record to support AVRCP Browsing
From: Luiz Augusto von Dentz @ 2012-09-26 17:24 UTC (permalink / raw)
To: Joohi RASTOGI; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZJPxL3TgD6NA69Q-QCSCxgssM2E5xULnvTPntUAWLc_kw@mail.gmail.com>
Hi Joohi,
On Fri, Sep 21, 2012 at 12:23 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Joohi,
>
> On Fri, Sep 21, 2012 at 8:22 AM, Joohi RASTOGI
> <joohi.rastogi@stericsson.com> wrote:
>> From 7348afc3401746a1890763ac5b689fca164fd934 Mon Sep 17 00:00:00 2001
>> From: Joohi Rastogi <joohi.rastogi@stericsson.com>
>> Date: Thu, 20 Sep 2012 14:21:37 +0530
>> Subject: [PATCH BlueZ V7 1/5] Adds SDP record to support browsing
>>
>> ---
>> audio/avctp.c | 4 ++--
>> audio/avctp.h | 3 ++-
>> audio/avrcp.c | 30 +++++++++++++++++++++++++-----
>> 3 files changed, 29 insertions(+), 8 deletions(-)
>>
>> diff --git a/audio/avctp.c b/audio/avctp.c
>> index 4e0e8dc..20aed66 100644
>> --- a/audio/avctp.c
>> +++ b/audio/avctp.c
>> @@ -803,7 +803,7 @@ static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master)
>> io = bt_io_listen(NULL, avctp_confirm_cb, NULL,
>> NULL, &err,
>> BT_IO_OPT_SOURCE_BDADDR, src,
>> - BT_IO_OPT_PSM, AVCTP_PSM,
>> + BT_IO_OPT_PSM, AVCTP_CONTROL_PSM,
>> BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
>> BT_IO_OPT_MASTER, master,
>> BT_IO_OPT_INVALID);
>> @@ -1091,7 +1091,7 @@ struct avctp *avctp_connect(const bdaddr_t *src, const bdaddr_t *dst)
>> io = bt_io_connect(avctp_connect_cb, session, NULL, &err,
>> BT_IO_OPT_SOURCE_BDADDR, &session->server->src,
>> BT_IO_OPT_DEST_BDADDR, &session->dst,
>> - BT_IO_OPT_PSM, AVCTP_PSM,
>> + BT_IO_OPT_PSM, AVCTP_CONTROL_PSM,
>> BT_IO_OPT_INVALID);
>> if (err) {
>> avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
>> diff --git a/audio/avctp.h b/audio/avctp.h
>> index d0cbd97..9d19b5d 100644
>> --- a/audio/avctp.h
>> +++ b/audio/avctp.h
>> @@ -22,7 +22,8 @@
>> *
>> */
>>
>> -#define AVCTP_PSM 23
>> +#define AVCTP_CONTROL_PSM 23
>> +#define AVCTP_BROWSING_PSM 27
>>
>> #define AVC_MTU 512
>> #define AVC_HEADER_LENGTH 3
>> diff --git a/audio/avrcp.c b/audio/avrcp.c
>> index 27be7e8..206d8fa 100644
>> --- a/audio/avrcp.c
>> +++ b/audio/avrcp.c
>> @@ -106,6 +106,7 @@
>> #define AVRCP_FEATURE_CATEGORY_3 0x0004
>> #define AVRCP_FEATURE_CATEGORY_4 0x0008
>> #define AVRCP_FEATURE_PLAYER_SETTINGS 0x0010
>> +#define AVRCP_FEATURE_BROWSING 0x0040
>>
>> #define AVRCP_BATTERY_STATUS_NORMAL 0
>> #define AVRCP_BATTERY_STATUS_WARNING 1
>> @@ -191,7 +192,7 @@ static sdp_record_t *avrcp_ct_record(void)
>> sdp_list_t *aproto, *proto[2];
>> sdp_record_t *record;
>> sdp_data_t *psm, *version, *features;
>> - uint16_t lp = AVCTP_PSM;
>> + uint16_t lp = AVCTP_CONTROL_PSM;
>> uint16_t avrcp_ver = 0x0100, avctp_ver = 0x0103;
>> uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
>> AVRCP_FEATURE_CATEGORY_2 |
>> @@ -253,18 +254,20 @@ static sdp_record_t *avrcp_ct_record(void)
>>
>> static sdp_record_t *avrcp_tg_record(void)
>> {
>> - sdp_list_t *svclass_id, *pfseq, *apseq, *root;
>> + sdp_list_t *svclass_id, *pfseq, *apseq, *root, *apseq_browsing;
>> uuid_t root_uuid, l2cap, avctp, avrtg;
>> sdp_profile_desc_t profile[1];
>> sdp_list_t *aproto, *proto[2];
>> - sdp_record_t *record;
>> - sdp_data_t *psm, *version, *features;
>> - uint16_t lp = AVCTP_PSM;
>> + sdp_record_t *record;sdp_data_t *psm, *version, *features, *psm_browsing;
>> + sdp_list_t *aproto_browsing, *proto_browsing[2] = {0};
>> + uint16_t lp = AVCTP_CONTROL_PSM;
>> + uint16_t lp_browsing = AVCTP_BROWSING_PSM;
>> uint16_t avrcp_ver = 0x0104, avctp_ver = 0x0103;
>> uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
>> AVRCP_FEATURE_CATEGORY_2 |
>> AVRCP_FEATURE_CATEGORY_3 |
>> AVRCP_FEATURE_CATEGORY_4 |
>> + AVRCP_FEATURE_BROWSING |
>> AVRCP_FEATURE_PLAYER_SETTINGS );
>>
>> record = sdp_record_alloc();
>> @@ -295,6 +298,17 @@ static sdp_record_t *avrcp_tg_record(void)
>>
>> aproto = sdp_list_append(0, apseq);
>> sdp_set_access_protos(record, aproto);
>> + proto_browsing[0] = sdp_list_append(0, &l2cap);
>> + psm_browsing = sdp_data_alloc(SDP_UINT16, &lp_browsing);
>> + proto_browsing[0] = sdp_list_append(proto_browsing[0], psm_browsing);
>> + apseq_browsing = sdp_list_append(0, proto_browsing[0]);
>> +
>> + proto_browsing[1] = sdp_list_append(0, &avctp);
>> + proto_browsing[1] = sdp_list_append(proto_browsing[1], version);
>> + apseq_browsing = sdp_list_append(apseq_browsing, proto_browsing[1]);
>> +
>> + aproto_browsing = sdp_list_append(0, apseq_browsing);
>> + sdp_set_add_access_protos(record, aproto_browsing);
>>
>> /* Bluetooth Profile Descriptor List */
>> sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
>> @@ -307,6 +321,12 @@ static sdp_record_t *avrcp_tg_record(void)
>>
>> sdp_set_info_attr(record, "AVRCP TG", 0, 0);
>>
>> + free(psm_browsing);
>> + sdp_list_free(proto_browsing[0], 0);
>> + sdp_list_free(proto_browsing[1], 0);
>> + sdp_list_free(apseq_browsing, 0);
>> + sdp_list_free(aproto_browsing, 0);
>> +
>> free(psm);
>> free(version);
>> sdp_list_free(proto[0], 0);
>> --
>> 1.7.5.4
These patches are now upstream, but I had to spend quite sometimes
fixes things that apparently wasn't tested properly. Im also working
on redesigning some pieces to makes things saner again, I hope next
time I don't have to spend so much time fixing so many things again.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH BlueZ v2 2/2] gdbus: Refactor filter_data_find()
From: Lucas De Marchi @ 2012-09-26 13:39 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1348666787-2510-1-git-send-email-lucas.demarchi@profusion.mobi>
Now this function is only used for searching the listeners of a
connection and the other parameters are not needed anymore.
---
gdbus/watch.c | 43 +++++--------------------------------------
1 file changed, 5 insertions(+), 38 deletions(-)
diff --git a/gdbus/watch.c b/gdbus/watch.c
index 2661928..a402ca9 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -119,13 +119,7 @@ static struct filter_data *filter_data_find_match(DBusConnection *connection,
return NULL;
}
-static struct filter_data *filter_data_find(DBusConnection *connection,
- const char *name,
- const char *owner,
- const char *path,
- const char *interface,
- const char *member,
- const char *argument)
+static struct filter_data *filter_data_find(DBusConnection *connection)
{
GSList *current;
@@ -136,30 +130,6 @@ static struct filter_data *filter_data_find(DBusConnection *connection,
if (connection != data->connection)
continue;
- if (name && data->name &&
- g_str_equal(name, data->name) == FALSE)
- continue;
-
- if (owner && data->owner &&
- g_str_equal(owner, data->owner) == FALSE)
- continue;
-
- if (path && data->path &&
- g_str_equal(path, data->path) == FALSE)
- continue;
-
- if (interface && data->interface &&
- g_str_equal(interface, data->interface) == FALSE)
- continue;
-
- if (member && data->member &&
- g_str_equal(member, data->member) == FALSE)
- continue;
-
- if (argument && data->argument &&
- g_str_equal(argument, data->argument) == FALSE)
- continue;
-
return data;
}
@@ -245,7 +215,7 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
struct filter_data *data;
const char *name = NULL, *owner = NULL;
- if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, NULL) == NULL) {
+ if (filter_data_find(connection) == NULL) {
if (!dbus_connection_add_filter(connection,
message_filter, NULL, NULL)) {
error("dbus_connection_add_filter() failed");
@@ -419,8 +389,7 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
listeners = g_slist_remove(listeners, data);
/* Remove filter if there are no listeners left for the connection */
- if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
- NULL) == NULL)
+ if (filter_data_find(connection) == NULL)
dbus_connection_remove_filter(connection, message_filter,
NULL);
@@ -613,8 +582,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
g_slist_free(delete_listener);
/* Remove filter if there are no listeners left for the connection */
- if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
- NULL) == NULL)
+ if (filter_data_find(connection) == NULL)
dbus_connection_remove_filter(connection, message_filter,
NULL);
@@ -810,8 +778,7 @@ void g_dbus_remove_all_watches(DBusConnection *connection)
{
struct filter_data *data;
- while ((data = filter_data_find(connection, NULL, NULL, NULL, NULL,
- NULL, NULL))) {
+ while ((data = filter_data_find(connection))) {
listeners = g_slist_remove(listeners, data);
filter_data_call_and_free(data);
}
--
1.7.12.1
^ permalink raw reply related
* [PATCH BlueZ v2 1/2] gdbus: Fix wrong signal handler match
From: Lucas De Marchi @ 2012-09-26 13:39 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lucas De Marchi
When we add a signal handler with g_dbus_add_signal_watch(), this
function tries to multiplex the matches added in libdbus by checking
if there's a previous filter_data with the same fields. However, if the
field is NULL it accepts as being the same. The result is that the
following watches will use the same filter data:
watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
cb1, data1, NULL);
watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
cb2, data2, NULL);
watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
cb3, data3, NULL);
The result is that when a signal arrives with path == "/path2", all 3
callbacks above will be called, with the same signal delivered to all of
them.
Another problem is that, if we invert the calls like below, only signals
to cb1 will never be trigerred, nonetheless it used path == NULL.
watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
cb2, data2, NULL);
watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
cb1, data1, NULL);
watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
cb3, data3, NULL);
This is fixed by not multiplexing the matchs with filter data if any of
the fields are different, including being NULL. When a signal arrives,
if a field is NULL we accept it as a match, but not when adding the
signal handler.
---
gdbus/watch.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 94 insertions(+), 21 deletions(-)
diff --git a/gdbus/watch.c b/gdbus/watch.c
index d749176..2661928 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -78,6 +78,47 @@ struct filter_data {
gboolean registered;
};
+static struct filter_data *filter_data_find_match(DBusConnection *connection,
+ const char *name,
+ const char *owner,
+ const char *path,
+ const char *interface,
+ const char *member,
+ const char *argument)
+{
+ GSList *current;
+
+ for (current = listeners;
+ current != NULL; current = current->next) {
+ struct filter_data *data = current->data;
+
+ if (connection != data->connection)
+ continue;
+
+ if (g_strcmp0(name, data->name) != 0)
+ continue;
+
+ if (g_strcmp0(owner, data->owner) != 0)
+ continue;
+
+ if (g_strcmp0(path, data->path) != 0)
+ continue;
+
+ if (g_strcmp0(interface, data->interface) != 0)
+ continue;
+
+ if (g_strcmp0(member, data->member) != 0)
+ continue;
+
+ if (g_strcmp0(argument, data->argument) != 0)
+ continue;
+
+ return data;
+ }
+
+ return NULL;
+}
+
static struct filter_data *filter_data_find(DBusConnection *connection,
const char *name,
const char *owner,
@@ -221,8 +262,8 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
name = sender;
proceed:
- data = filter_data_find(connection, name, owner, path, interface,
- member, argument);
+ data = filter_data_find_match(connection, name, owner, path,
+ interface, member, argument);
if (data)
return data;
@@ -501,6 +542,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
{
struct filter_data *data;
const char *sender, *path, *iface, *member, *arg = NULL;
+ GSList *current, *delete_listener = NULL;
/* Only filter signals */
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
@@ -512,30 +554,63 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
member = dbus_message_get_member(message);
dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
- /* Sender is always bus name */
- data = filter_data_find(connection, NULL, sender, path, iface, member,
- arg);
- if (data == NULL) {
- error("Got %s.%s signal which has no listeners", iface, member);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
+ /* Sender is always the owner */
+
+ for (current = listeners; current != NULL; current = current->next) {
+ data = current->data;
+
+ if (connection != data->connection)
+ continue;
+
+ if (data->owner && g_str_equal(sender, data->owner) == FALSE)
+ continue;
- if (data->handle_func) {
- data->lock = TRUE;
+ if (data->path && g_str_equal(path, data->path) == FALSE)
+ continue;
+
+ if (data->interface && g_str_equal(iface,
+ data->interface) == FALSE)
+ continue;
- data->handle_func(connection, message, data);
+ if (data->member && g_str_equal(member, data->member) == FALSE)
+ continue;
- data->callbacks = data->processed;
- data->processed = NULL;
- data->lock = FALSE;
+ if (data->argument && g_str_equal(arg,
+ data->argument) == FALSE)
+ continue;
+
+ if (data->handle_func) {
+ data->lock = TRUE;
+
+ data->handle_func(connection, message, data);
+
+ data->callbacks = data->processed;
+ data->processed = NULL;
+ data->lock = FALSE;
+ }
+
+ if (!data->callbacks)
+ delete_listener = g_slist_prepend(delete_listener,
+ current);
}
- if (data->callbacks)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ for (current = delete_listener; current != NULL;
+ current = delete_listener->next) {
+ GSList *l = current->data;
- remove_match(data);
+ data = l->data;
- listeners = g_slist_remove(listeners, data);
+ /* Has any other callback added callbacks back to this data? */
+ if (data->callbacks != NULL)
+ continue;
+
+ remove_match(data);
+ listeners = g_slist_remove_link(listeners, l);
+
+ filter_data_free(data);
+ }
+
+ g_slist_free(delete_listener);
/* Remove filter if there are no listeners left for the connection */
if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
@@ -543,8 +618,6 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
dbus_connection_remove_filter(connection, message_filter,
NULL);
- filter_data_free(data);
-
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
--
1.7.12.1
^ permalink raw reply related
* Re: [PATCH BlueZ 2/2] gdbus: Refactor filter_data_find()
From: Luiz Augusto von Dentz @ 2012-09-26 10:21 UTC (permalink / raw)
To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <1348601288-18975-2-git-send-email-lucas.demarchi@profusion.mobi>
Hi Lucas,
On Tue, Sep 25, 2012 at 10:28 PM, Lucas De Marchi
<lucas.demarchi@profusion.mobi> wrote:
> Now this function is only used for searching the listeners of a
> connection and the other parameters are not needed anymore.
> ---
> gdbus/watch.c | 43 +++++--------------------------------------
> 1 file changed, 5 insertions(+), 38 deletions(-)
>
> diff --git a/gdbus/watch.c b/gdbus/watch.c
> index 33c12ed..c4066c0 100644
> --- a/gdbus/watch.c
> +++ b/gdbus/watch.c
> @@ -119,13 +119,7 @@ static struct filter_data *filter_data_find_nonnull(DBusConnection *connection,
> return NULL;
> }
>
> -static struct filter_data *filter_data_find(DBusConnection *connection,
> - const char *name,
> - const char *owner,
> - const char *path,
> - const char *interface,
> - const char *member,
> - const char *argument)
> +static struct filter_data *filter_data_find(DBusConnection *connection)
> {
> GSList *current;
>
> @@ -136,30 +130,6 @@ static struct filter_data *filter_data_find(DBusConnection *connection,
> if (connection != data->connection)
> continue;
>
> - if (name && data->name &&
> - g_str_equal(name, data->name) == FALSE)
> - continue;
> -
> - if (owner && data->owner &&
> - g_str_equal(owner, data->owner) == FALSE)
> - continue;
> -
> - if (path && data->path &&
> - g_str_equal(path, data->path) == FALSE)
> - continue;
> -
> - if (interface && data->interface &&
> - g_str_equal(interface, data->interface) == FALSE)
> - continue;
> -
> - if (member && data->member &&
> - g_str_equal(member, data->member) == FALSE)
> - continue;
> -
> - if (argument && data->argument &&
> - g_str_equal(argument, data->argument) == FALSE)
> - continue;
> -
> return data;
> }
>
> @@ -245,7 +215,7 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
> struct filter_data *data;
> const char *name = NULL, *owner = NULL;
>
> - if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, NULL) == NULL) {
> + if (filter_data_find(connection) == NULL) {
> if (!dbus_connection_add_filter(connection,
> message_filter, NULL, NULL)) {
> error("dbus_connection_add_filter() failed");
> @@ -419,8 +389,7 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
> listeners = g_slist_remove(listeners, data);
>
> /* Remove filter if there are no listeners left for the connection */
> - if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
> - NULL) == NULL)
> + if (filter_data_find(connection) == NULL)
> dbus_connection_remove_filter(connection, message_filter,
> NULL);
>
> @@ -613,8 +582,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> g_slist_free(delete_listener);
>
> /* Remove filter if there are no listeners left for the connection */
> - if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
> - NULL) == NULL)
> + if (filter_data_find(connection) == NULL)
> dbus_connection_remove_filter(connection, message_filter,
> NULL);
>
> @@ -810,8 +778,7 @@ void g_dbus_remove_all_watches(DBusConnection *connection)
> {
> struct filter_data *data;
>
> - while ((data = filter_data_find(connection, NULL, NULL, NULL, NULL,
> - NULL, NULL))) {
> + while ((data = filter_data_find(connection))) {
> listeners = g_slist_remove(listeners, data);
> filter_data_call_and_free(data);
> }
> --
> 1.7.12.1
Ack.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH BlueZ 1/2] gdbus: Fix wrong signal handler match
From: Luiz Augusto von Dentz @ 2012-09-26 10:20 UTC (permalink / raw)
To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <1348601288-18975-1-git-send-email-lucas.demarchi@profusion.mobi>
HI Lucas,
On Tue, Sep 25, 2012 at 10:28 PM, Lucas De Marchi
<lucas.demarchi@profusion.mobi> wrote:
> When we add a signal handler with g_dbus_add_signal_watch(), this
> function tries to multiplex the matches added in libdbus by checking
> if there's a previous filter_data with the same fields. However, if the
> field is NULL it accepts as being the same. The result is that the
> following watches will use the same filter data:
>
> watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
> cb1, data1, NULL);
> watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
> cb2, data2, NULL);
> watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
> cb3, data3, NULL);
>
> The result is that when a signal arrives with path == "/path2", all 3
> callbacks above will be called, with the same signal delivered to all of
> them.
>
> Another problem is that, if we invert the calls like below, only signals
> to cb1 will never be trigerred, nonetheless it used path == NULL.
>
> watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
> cb2, data2, NULL);
> watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
> cb1, data1, NULL);
> watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
> cb3, data3, NULL);
>
> This is fixed by not multiplexing the matchs with filter data if any of
> the fields are different, including being NULL. When a signal arrives,
> if a field is NULL we accept it as a match, but not when adding the
> signal handler.
> ---
> gdbus/watch.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 94 insertions(+), 21 deletions(-)
>
> diff --git a/gdbus/watch.c b/gdbus/watch.c
> index d749176..33c12ed 100644
> --- a/gdbus/watch.c
> +++ b/gdbus/watch.c
> @@ -78,6 +78,47 @@ struct filter_data {
> gboolean registered;
> };
>
> +static struct filter_data *filter_data_find_nonnull(DBusConnection *connection,
> + const char *name,
> + const char *owner,
> + const char *path,
> + const char *interface,
> + const char *member,
> + const char *argument)
> +{
> + GSList *current;
> +
> + for (current = listeners;
> + current != NULL; current = current->next) {
> + struct filter_data *data = current->data;
> +
> + if (connection != data->connection)
> + continue;
> +
> + if (g_strcmp0(name, data->name) != 0)
> + continue;
> +
> + if (g_strcmp0(owner, data->owner) != 0)
> + continue;
> +
> + if (g_strcmp0(path, data->path) != 0)
> + continue;
> +
> + if (g_strcmp0(interface, data->interface) != 0)
> + continue;
> +
> + if (g_strcmp0(member, data->member) != 0)
> + continue;
> +
> + if (g_strcmp0(argument, data->argument) != 0)
> + continue;
> +
> + return data;
> + }
> +
> + return NULL;
> +}
> +
> static struct filter_data *filter_data_find(DBusConnection *connection,
> const char *name,
> const char *owner,
> @@ -221,8 +262,8 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
> name = sender;
>
> proceed:
> - data = filter_data_find(connection, name, owner, path, interface,
> - member, argument);
> + data = filter_data_find_nonnull(connection, name, owner, path,
> + interface, member, argument);
Call it filter_data_find_match to be more obvious that we need an
exact match here.
> if (data)
> return data;
>
> @@ -501,6 +542,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> {
> struct filter_data *data;
> const char *sender, *path, *iface, *member, *arg = NULL;
> + GSList *current, *delete_listener = NULL;
>
> /* Only filter signals */
> if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
> @@ -512,30 +554,63 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> member = dbus_message_get_member(message);
> dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
>
> - /* Sender is always bus name */
> - data = filter_data_find(connection, NULL, sender, path, iface, member,
> - arg);
> - if (data == NULL) {
> - error("Got %s.%s signal which has no listeners", iface, member);
> - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
> - }
> + /* Sender is always the owner */
> +
> + for (current = listeners; current != NULL; current = current->next) {
> + data = current->data;
> +
> + if (connection != data->connection)
> + continue;
> +
> + if (data->owner && g_str_equal(sender, data->owner) == FALSE)
> + continue;
>
> - if (data->handle_func) {
> - data->lock = TRUE;
> + if (data->path && g_str_equal(path, data->path) == FALSE)
> + continue;
> +
> + if (data->interface && g_str_equal(iface,
> + data->interface) == FALSE)
> + continue;
>
> - data->handle_func(connection, message, data);
> + if (data->member && g_str_equal(member, data->member) == FALSE)
> + continue;
>
> - data->callbacks = data->processed;
> - data->processed = NULL;
> - data->lock = FALSE;
> + if (data->argument && g_str_equal(arg,
> + data->argument) == FALSE)
> + continue;
> +
> + if (data->handle_func) {
> + data->lock = TRUE;
> +
> + data->handle_func(connection, message, data);
> +
> + data->callbacks = data->processed;
> + data->processed = NULL;
> + data->lock = FALSE;
> + }
> +
> + if (!data->callbacks)
> + delete_listener = g_slist_prepend(delete_listener,
> + current);
> }
>
> - if (data->callbacks)
> - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
> + for (current = delete_listener; current != NULL;
> + current = delete_listener->next) {
> + GSList *l = current->data;
>
> - remove_match(data);
> + data = l->data;
>
> - listeners = g_slist_remove(listeners, data);
> + /* Has any other callback added callbacks back to this data? */
> + if (data->callbacks != NULL)
> + continue;
> +
> + remove_match(data);
> + listeners = g_slist_remove_link(listeners, l);
> +
> + filter_data_free(data);
> + }
> +
> + g_slist_free(delete_listener);
>
> /* Remove filter if there are no listeners left for the connection */
> if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
> @@ -543,8 +618,6 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
> dbus_connection_remove_filter(connection, message_filter,
> NULL);
>
> - filter_data_free(data);
> -
> return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
> }
>
> --
> 1.7.12.1
The rest looks good.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH v4] HID: Add support for Sony PS3 BD Remote Control
From: Antonio Ospite @ 2012-09-25 21:02 UTC (permalink / raw)
To: David Dillow
Cc: linux-bluetooth, David Herrmann, Luiz Augusto von Dentz,
Bastien Nocera, linux-input, jkosina, Antonio Ospite
In-Reply-To: <1348584182.27596.28.camel@frustration.ornl.gov>
From: David Dillow <dave@thedillows.org>
The Sony PS3 Blue-ray Disc Remote Control used to be supported by the
BlueZ project's user space, but the code that handled it was recently
removed as its functionality conflicted with a real HSP implementation
and the mapping was thought to be better handled in the kernel. This is
a port of the mapping logic from the fakehid driver by Marcel Holtmann
to the in-kernel HID layer.
We also add support for the Logitech Harmony Adapter for PS3, which
emulates the BD Remote.
Signed-off-by: David Dillow <dave@thedillows.org>
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---
Changes since v3:
- move the size check into the switch statement.
Thanks,
Antonio
drivers/hid/Kconfig | 13 ++-
drivers/hid/Makefile | 1 +
drivers/hid/hid-core.c | 2 +
drivers/hid/hid-ids.h | 2 +
drivers/hid/hid-ps3remote.c | 215 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 232 insertions(+), 1 deletion(-)
create mode 100644 drivers/hid/hid-ps3remote.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fbf4950..378be0b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -534,6 +534,15 @@ config HID_PRIMAX
Support for Primax devices that are not fully compliant with the
HID standard.
+config HID_PS3REMOTE
+ tristate "Sony PS3 BD Remote Control"
+ depends on BT_HIDP
+ ---help---
+ Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
+ Harmony Adapter for PS3, which connect over Bluetooth.
+
+ Support for the 6-axis controllers is provided by HID_SONY.
+
config HID_ROCCAT
tristate "Roccat device support"
depends on USB_HID
@@ -561,7 +570,9 @@ config HID_SONY
tristate "Sony PS3 controller"
depends on USB_HID
---help---
- Support for Sony PS3 controller.
+ Support for Sony PS3 6-axis controllers.
+
+ Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE.
config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support"
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f975485..333ed6c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
+obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8bcd168..e4275d4 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1566,6 +1566,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
@@ -1639,6 +1640,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1dcb76f..40411c9 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -496,6 +496,7 @@
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
+#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211
#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215
@@ -683,6 +684,7 @@
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
+#define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
new file mode 100644
index 0000000..03811e5
--- /dev/null
+++ b/drivers/hid/hid-ps3remote.c
@@ -0,0 +1,215 @@
+/*
+ * HID driver for Sony PS3 BD Remote Control
+ *
+ * Copyright (c) 2012 David Dillow <dave@thedillows.org>
+ * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann
+ * and other kernel HID drivers.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
+ * a Bluetooth host, the key combination Start+Enter has to be kept pressed
+ * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
+ *
+ * There will be no PIN request from the device.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static __u8 ps3remote_rdesc[] = {
+ 0x05, 0x01, /* GUsagePage Generic Desktop */
+ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */
+ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */
+
+ /* Use collection 1 for joypad buttons */
+ 0xA1, 0x02, /* MCollection Logical (interrelated data) */
+
+ /* Ignore the 1st byte, maybe it is used for a controller
+ * number but it's not needed for correct operation */
+ 0x75, 0x08, /* GReportSize 0x08 [8] */
+ 0x95, 0x01, /* GReportCount 0x01 [1] */
+ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
+
+ /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
+ * buttons multiple keypresses are allowed */
+ 0x05, 0x09, /* GUsagePage Button */
+ 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
+ 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */
+ 0x14, /* GLogicalMinimum [0] */
+ 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */
+ 0x75, 0x01, /* GReportSize 0x01 [1] */
+ 0x95, 0x18, /* GReportCount 0x18 [24] */
+ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
+
+ 0xC0, /* MEndCollection */
+
+ /* Use collection 2 for remote control buttons */
+ 0xA1, 0x02, /* MCollection Logical (interrelated data) */
+
+ /* 5th byte is used for remote control buttons */
+ 0x05, 0x09, /* GUsagePage Button */
+ 0x18, /* LUsageMinimum [No button pressed] */
+ 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */
+ 0x14, /* GLogicalMinimum [0] */
+ 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */
+ 0x75, 0x08, /* GReportSize 0x08 [8] */
+ 0x95, 0x01, /* GReportCount 0x01 [1] */
+ 0x80, /* MInput */
+
+ /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
+ * 0xff and 11th is for press indication */
+ 0x75, 0x08, /* GReportSize 0x08 [8] */
+ 0x95, 0x06, /* GReportCount 0x06 [6] */
+ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
+
+ /* 12th byte is for battery strength */
+ 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 */
+
+ 0xC0 /* MEndCollection [Game Pad] */
+};
+
+static const unsigned int ps3remote_keymap_joypad_buttons[] = {
+ [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_remote_buttons[] = {
+ [0x00] = KEY_1,
+ [0x01] = KEY_2,
+ [0x02] = KEY_3,
+ [0x03] = KEY_4,
+ [0x04] = KEY_5,
+ [0x05] = KEY_6,
+ [0x06] = KEY_7,
+ [0x07] = KEY_8,
+ [0x08] = KEY_9,
+ [0x09] = KEY_0,
+ [0x0e] = KEY_ESC, /* return */
+ [0x0f] = KEY_CLEAR,
+ [0x16] = KEY_EJECTCD,
+ [0x1a] = KEY_MENU, /* top menu */
+ [0x28] = KEY_TIME,
+ [0x30] = KEY_PREVIOUS,
+ [0x31] = KEY_NEXT,
+ [0x32] = KEY_PLAY,
+ [0x33] = KEY_REWIND, /* scan back */
+ [0x34] = KEY_FORWARD, /* scan forward */
+ [0x38] = KEY_STOP,
+ [0x39] = KEY_PAUSE,
+ [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */
+ [0x60] = KEY_FRAMEBACK, /* slow/step back */
+ [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */
+ [0x63] = KEY_SUBTITLE,
+ [0x64] = KEY_AUDIO,
+ [0x65] = KEY_ANGLE,
+ [0x70] = KEY_INFO, /* display */
+ [0x80] = KEY_BLUE,
+ [0x81] = KEY_RED,
+ [0x82] = KEY_GREEN,
+ [0x83] = KEY_YELLOW,
+};
+
+static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ *rsize = sizeof(ps3remote_rdesc);
+ return ps3remote_rdesc;
+}
+
+static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned int key = usage->hid & HID_USAGE;
+
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
+ return -1;
+
+ switch (usage->collection_index) {
+ case 1:
+ if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
+ return -1;
+
+ key = ps3remote_keymap_joypad_buttons[key];
+ if (!key)
+ return -1;
+ break;
+ case 2:
+ if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
+ return -1;
+
+ key = ps3remote_keymap_remote_buttons[key];
+ if (!key)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
+ return 1;
+}
+
+static const struct hid_device_id ps3remote_devices[] = {
+ /* PS3 BD Remote Control */
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
+ /* Logitech Harmony Adapter for PS3 */
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ps3remote_devices);
+
+static struct hid_driver ps3remote_driver = {
+ .name = "ps3_remote",
+ .id_table = ps3remote_devices,
+ .report_fixup = ps3remote_fixup,
+ .input_mapping = ps3remote_mapping,
+};
+
+static int __init ps3remote_init(void)
+{
+ return hid_register_driver(&ps3remote_driver);
+}
+
+static void __exit ps3remote_exit(void)
+{
+ hid_unregister_driver(&ps3remote_driver);
+}
+
+module_init(ps3remote_init);
+module_exit(ps3remote_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Dillow <dave@thedillows.org>, Antonio Ospite <ospite@studenti.unina.it>");
--
1.7.10.4
^ permalink raw reply related
* [PATCH BlueZ 2/2] gdbus: Refactor filter_data_find()
From: Lucas De Marchi @ 2012-09-25 19:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lucas De Marchi
In-Reply-To: <1348601288-18975-1-git-send-email-lucas.demarchi@profusion.mobi>
Now this function is only used for searching the listeners of a
connection and the other parameters are not needed anymore.
---
gdbus/watch.c | 43 +++++--------------------------------------
1 file changed, 5 insertions(+), 38 deletions(-)
diff --git a/gdbus/watch.c b/gdbus/watch.c
index 33c12ed..c4066c0 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -119,13 +119,7 @@ static struct filter_data *filter_data_find_nonnull(DBusConnection *connection,
return NULL;
}
-static struct filter_data *filter_data_find(DBusConnection *connection,
- const char *name,
- const char *owner,
- const char *path,
- const char *interface,
- const char *member,
- const char *argument)
+static struct filter_data *filter_data_find(DBusConnection *connection)
{
GSList *current;
@@ -136,30 +130,6 @@ static struct filter_data *filter_data_find(DBusConnection *connection,
if (connection != data->connection)
continue;
- if (name && data->name &&
- g_str_equal(name, data->name) == FALSE)
- continue;
-
- if (owner && data->owner &&
- g_str_equal(owner, data->owner) == FALSE)
- continue;
-
- if (path && data->path &&
- g_str_equal(path, data->path) == FALSE)
- continue;
-
- if (interface && data->interface &&
- g_str_equal(interface, data->interface) == FALSE)
- continue;
-
- if (member && data->member &&
- g_str_equal(member, data->member) == FALSE)
- continue;
-
- if (argument && data->argument &&
- g_str_equal(argument, data->argument) == FALSE)
- continue;
-
return data;
}
@@ -245,7 +215,7 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
struct filter_data *data;
const char *name = NULL, *owner = NULL;
- if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, NULL) == NULL) {
+ if (filter_data_find(connection) == NULL) {
if (!dbus_connection_add_filter(connection,
message_filter, NULL, NULL)) {
error("dbus_connection_add_filter() failed");
@@ -419,8 +389,7 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
listeners = g_slist_remove(listeners, data);
/* Remove filter if there are no listeners left for the connection */
- if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
- NULL) == NULL)
+ if (filter_data_find(connection) == NULL)
dbus_connection_remove_filter(connection, message_filter,
NULL);
@@ -613,8 +582,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
g_slist_free(delete_listener);
/* Remove filter if there are no listeners left for the connection */
- if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
- NULL) == NULL)
+ if (filter_data_find(connection) == NULL)
dbus_connection_remove_filter(connection, message_filter,
NULL);
@@ -810,8 +778,7 @@ void g_dbus_remove_all_watches(DBusConnection *connection)
{
struct filter_data *data;
- while ((data = filter_data_find(connection, NULL, NULL, NULL, NULL,
- NULL, NULL))) {
+ while ((data = filter_data_find(connection))) {
listeners = g_slist_remove(listeners, data);
filter_data_call_and_free(data);
}
--
1.7.12.1
^ permalink raw reply related
* [PATCH BlueZ 1/2] gdbus: Fix wrong signal handler match
From: Lucas De Marchi @ 2012-09-25 19:28 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lucas De Marchi
When we add a signal handler with g_dbus_add_signal_watch(), this
function tries to multiplex the matches added in libdbus by checking
if there's a previous filter_data with the same fields. However, if the
field is NULL it accepts as being the same. The result is that the
following watches will use the same filter data:
watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
cb1, data1, NULL);
watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
cb2, data2, NULL);
watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
cb3, data3, NULL);
The result is that when a signal arrives with path == "/path2", all 3
callbacks above will be called, with the same signal delivered to all of
them.
Another problem is that, if we invert the calls like below, only signals
to cb1 will never be trigerred, nonetheless it used path == NULL.
watch2 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path2", iface, member,
cb2, data2, NULL);
watch1 = g_dbus_add_signal_watch(conn, BUS_NAME, NULL, iface, member,
cb1, data1, NULL);
watch3 = g_dbus_add_signal_watch(conn, BUS_NAME, "/path3", iface, member,
cb3, data3, NULL);
This is fixed by not multiplexing the matchs with filter data if any of
the fields are different, including being NULL. When a signal arrives,
if a field is NULL we accept it as a match, but not when adding the
signal handler.
---
gdbus/watch.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 94 insertions(+), 21 deletions(-)
diff --git a/gdbus/watch.c b/gdbus/watch.c
index d749176..33c12ed 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -78,6 +78,47 @@ struct filter_data {
gboolean registered;
};
+static struct filter_data *filter_data_find_nonnull(DBusConnection *connection,
+ const char *name,
+ const char *owner,
+ const char *path,
+ const char *interface,
+ const char *member,
+ const char *argument)
+{
+ GSList *current;
+
+ for (current = listeners;
+ current != NULL; current = current->next) {
+ struct filter_data *data = current->data;
+
+ if (connection != data->connection)
+ continue;
+
+ if (g_strcmp0(name, data->name) != 0)
+ continue;
+
+ if (g_strcmp0(owner, data->owner) != 0)
+ continue;
+
+ if (g_strcmp0(path, data->path) != 0)
+ continue;
+
+ if (g_strcmp0(interface, data->interface) != 0)
+ continue;
+
+ if (g_strcmp0(member, data->member) != 0)
+ continue;
+
+ if (g_strcmp0(argument, data->argument) != 0)
+ continue;
+
+ return data;
+ }
+
+ return NULL;
+}
+
static struct filter_data *filter_data_find(DBusConnection *connection,
const char *name,
const char *owner,
@@ -221,8 +262,8 @@ static struct filter_data *filter_data_get(DBusConnection *connection,
name = sender;
proceed:
- data = filter_data_find(connection, name, owner, path, interface,
- member, argument);
+ data = filter_data_find_nonnull(connection, name, owner, path,
+ interface, member, argument);
if (data)
return data;
@@ -501,6 +542,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
{
struct filter_data *data;
const char *sender, *path, *iface, *member, *arg = NULL;
+ GSList *current, *delete_listener = NULL;
/* Only filter signals */
if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
@@ -512,30 +554,63 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
member = dbus_message_get_member(message);
dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
- /* Sender is always bus name */
- data = filter_data_find(connection, NULL, sender, path, iface, member,
- arg);
- if (data == NULL) {
- error("Got %s.%s signal which has no listeners", iface, member);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
+ /* Sender is always the owner */
+
+ for (current = listeners; current != NULL; current = current->next) {
+ data = current->data;
+
+ if (connection != data->connection)
+ continue;
+
+ if (data->owner && g_str_equal(sender, data->owner) == FALSE)
+ continue;
- if (data->handle_func) {
- data->lock = TRUE;
+ if (data->path && g_str_equal(path, data->path) == FALSE)
+ continue;
+
+ if (data->interface && g_str_equal(iface,
+ data->interface) == FALSE)
+ continue;
- data->handle_func(connection, message, data);
+ if (data->member && g_str_equal(member, data->member) == FALSE)
+ continue;
- data->callbacks = data->processed;
- data->processed = NULL;
- data->lock = FALSE;
+ if (data->argument && g_str_equal(arg,
+ data->argument) == FALSE)
+ continue;
+
+ if (data->handle_func) {
+ data->lock = TRUE;
+
+ data->handle_func(connection, message, data);
+
+ data->callbacks = data->processed;
+ data->processed = NULL;
+ data->lock = FALSE;
+ }
+
+ if (!data->callbacks)
+ delete_listener = g_slist_prepend(delete_listener,
+ current);
}
- if (data->callbacks)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ for (current = delete_listener; current != NULL;
+ current = delete_listener->next) {
+ GSList *l = current->data;
- remove_match(data);
+ data = l->data;
- listeners = g_slist_remove(listeners, data);
+ /* Has any other callback added callbacks back to this data? */
+ if (data->callbacks != NULL)
+ continue;
+
+ remove_match(data);
+ listeners = g_slist_remove_link(listeners, l);
+
+ filter_data_free(data);
+ }
+
+ g_slist_free(delete_listener);
/* Remove filter if there are no listeners left for the connection */
if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
@@ -543,8 +618,6 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
dbus_connection_remove_filter(connection, message_filter,
NULL);
- filter_data_free(data);
-
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
--
1.7.12.1
^ permalink raw reply related
* Re: [RFCv1 03/20] Bluetooth: Add L2CAP create channel request handling
From: Mat Martineau @ 2012-09-25 18:57 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth, gustavo, sunnyk
In-Reply-To: <20120925113828.GG2509@aemeltch-MOBL1>
Andrei -
On Tue, 25 Sep 2012, Andrei Emeltchenko wrote:
> 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;
>
> Please consider this:
>
> - rsp.result = L2CAP_CR_BAD_AMP;
> - rsp.status = L2CAP_CS_NO_INFO;
> + rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
> + rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
>
Ok, I'll fix that and look for similar issues.
--
Mat Martineau
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* [PATCH BlueZ v7 9/9] core: Suspend scanning before connect on pairing
From: João Paulo Rechi Vita @ 2012-09-25 17:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1348594686-26221-1-git-send-email-jprvita@openbossa.org>
If there is a disconnected bonded device there will be a scanning
procedure active due to the General Connection Establishment Procedure.
This scan have to be suspended before trying to connect to the remote
device for pairing.
---
src/device.c | 107 ++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 73 insertions(+), 34 deletions(-)
diff --git a/src/device.c b/src/device.c
index d23ea46..1cd9b5a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1959,6 +1959,36 @@ done:
browse_request_free(req);
}
+static void bonding_request_free(struct bonding_req *bonding)
+{
+ struct btd_device *device;
+
+ if (!bonding)
+ return;
+
+ if (bonding->listener_id)
+ g_dbus_remove_watch(btd_get_dbus_connection(),
+ bonding->listener_id);
+
+ if (bonding->msg)
+ dbus_message_unref(bonding->msg);
+
+ device = bonding->device;
+ g_free(bonding);
+
+ if (!device)
+ return;
+
+ device->bonding = NULL;
+
+ if (!device->agent)
+ return;
+
+ agent_cancel(device->agent);
+ agent_free(device->agent);
+ device->agent = NULL;
+}
+
static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
{
struct att_callbacks *attcb = user_data;
@@ -1988,6 +2018,21 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
if (attcb->success)
attcb->success(user_data);
+
+ if (device->bonding) {
+ /* this is a LE device during pairing */
+ int err = adapter_create_bonding(device->adapter,
+ &device->bdaddr, device->bdaddr_type,
+ agent_get_io_capability(device->agent));
+ if (err < 0) {
+ DBusMessage *reply = btd_error_failed(
+ device->bonding->msg, strerror(-err));
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ bonding_request_cancel(device->bonding);
+ bonding_request_free(device->bonding);
+ }
+ }
+
done:
g_free(attcb);
}
@@ -2039,16 +2084,30 @@ GIOChannel *device_att_connect(gpointer user_data)
attcb->user_data = device;
if (device_is_bredr(device)) {
- io = bt_io_connect(att_connect_cb,
- attcb, NULL, &gerr,
+ io = bt_io_connect(att_connect_cb, attcb, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &sba,
BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
BT_IO_OPT_PSM, ATT_PSM,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
BT_IO_OPT_INVALID);
+ } else if (device->bonding) {
+ /* this is a LE device during pairing, using low sec level */
+ io = bt_io_connect(att_connect_cb, attcb, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &sba,
+ BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
+ BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
+ BT_IO_OPT_CID, ATT_CID,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_INVALID);
+ if (io == NULL) {
+ DBusMessage *reply = btd_error_failed(
+ device->bonding->msg, gerr->message);
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ bonding_request_cancel(device->bonding);
+ bonding_request_free(device->bonding);
+ }
} else {
- io = bt_io_connect(att_connect_cb,
- attcb, NULL, &gerr,
+ io = bt_io_connect(att_connect_cb, attcb, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &sba,
BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
@@ -2368,36 +2427,6 @@ static DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
}
}
-static void bonding_request_free(struct bonding_req *bonding)
-{
- struct btd_device *device;
-
- if (!bonding)
- return;
-
- if (bonding->listener_id)
- g_dbus_remove_watch(btd_get_dbus_connection(),
- bonding->listener_id);
-
- if (bonding->msg)
- dbus_message_unref(bonding->msg);
-
- device = bonding->device;
- g_free(bonding);
-
- if (!device)
- return;
-
- device->bonding = NULL;
-
- if (!device->agent)
- return;
-
- agent_cancel(device->agent);
- agent_free(device->agent);
- device->agent = NULL;
-}
-
void device_set_paired(struct btd_device *device, gboolean value)
{
if (device->paired == value)
@@ -2534,6 +2563,16 @@ DBusMessage *device_create_bonding(struct btd_device *device,
device->bonding = bonding;
bonding->device = device;
+ if (device_is_le(device)) {
+ adapter_connect_list_add(adapter, device);
+ return NULL;
+ }
+
+ err = adapter_create_bonding(adapter, &device->bdaddr,
+ device->bdaddr_type, capability);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
return NULL;
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ v7 8/9] mgmt: Add address type to bonding debug message
From: João Paulo Rechi Vita @ 2012-09-25 17:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1348594686-26221-1-git-send-email-jprvita@openbossa.org>
---
src/mgmt.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/mgmt.c b/src/mgmt.c
index 405a683..67a6993 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -2383,7 +2383,8 @@ int mgmt_create_bonding(int index, bdaddr_t *bdaddr, uint8_t addr_type, uint8_t
char addr[18];
ba2str(bdaddr, addr);
- DBG("hci%d bdaddr %s io_cap 0x%02x", index, addr, io_cap);
+ DBG("hci%d bdaddr %s type %d io_cap 0x%02x",
+ index, addr, addr_type, io_cap);
memset(buf, 0, sizeof(buf));
hdr->opcode = htobs(MGMT_OP_PAIR_DEVICE);
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ v7 7/9] core: Re-connect for ECONNRESET or ECONNABORTED
From: João Paulo Rechi Vita @ 2012-09-25 17:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1348594686-26221-1-git-send-email-jprvita@openbossa.org>
From: Claudio Takahasi <claudio.takahasi@openbossa.org>
This patch keeps scanning and re-connections active if the disconnection
reason is ECONNRESET(Remote Initiated Disconnection).
Re-connection is a behaviour determined by Profiles or by the upper
layer(user actions). For instance, HoG requires re-connection always
active, no matter if the previous disconnection reason was page timeout
or remote initiated disconnection (ECONNRESET). Some devices disconnects
after some idle time, connectable advertises are sent by the peripheral
when commanded by the user(eg: key pressed). Disconnection can be also
triggered by the local host (ECONNABORTED) using command line tools or
Disconnect method in the Device interface.
The peripheral dictates the re-connection controlling the connectable
advertises, BlueZ(central) needs to keep the scanning always active to
able to detect the advertises and trigger the connection.
---
src/device.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/device.c b/src/device.c
index 96d8b72..d23ea46 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1889,10 +1889,18 @@ static gboolean attrib_disconnected_cb(GIOChannel *io, GIOCondition cond,
g_slist_foreach(device->attios, attio_disconnected, NULL);
- if (device->auto_connect == FALSE || err != ETIMEDOUT)
+ if (device->auto_connect == FALSE) {
+ DBG("Automatic connection disabled");
goto done;
+ }
- adapter_connect_list_add(device_get_adapter(device), device);
+ /*
+ * Keep scanning/re-connection active if disconnection reason
+ * is page timeout, remote user terminated connection or local
+ * initiated disconnection.
+ */
+ if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
+ adapter_connect_list_add(device_get_adapter(device), device);
done:
attio_cleanup(device);
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ v7 6/9] core: Disable unnecessary auto connections
From: João Paulo Rechi Vita @ 2012-09-25 17:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Paulo Alcantara
In-Reply-To: <1348594686-26221-1-git-send-email-jprvita@openbossa.org>
From: Paulo Alcantara <paulo.alcantara@openbossa.org>
BlueZ host disconnects the link when encryption fails. ECONNABORTED
error is returned by the kernel when the connection is terminated by the
local host. This scenario commonly happens when authentication fails due
PIN or Key Missing.
---
src/device.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/device.c b/src/device.c
index 5d92ff5..96d8b72 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1989,6 +1989,9 @@ static void att_error_cb(const GError *gerr, gpointer user_data)
struct att_callbacks *attcb = user_data;
struct btd_device *device = attcb->user_data;
+ if (g_error_matches(gerr, BT_IO_ERROR, ECONNABORTED))
+ return;
+
if (device->auto_connect == FALSE)
return;
--
1.7.11.4
^ 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