* Re: [PATCH_v3 3/3] android/pan: Handle connection and control state notifications
From: Szymon Janc @ 2013-11-13 9:59 UTC (permalink / raw)
To: Ravi Kumar Veeramally; +Cc: linux-bluetooth, Johan Hedberg
In-Reply-To: <52834A76.4050600@linux.intel.com>
Hi,
> >> +
> >> + switch (opcode) {
> >> + case HAL_EV_PAN_CONN_STATE:
> >> + handle_conn_state(buf);
> >> + break;
> >> + case HAL_EV_PAN_CTRL_STATE:
> >> + handle_ctrl_state(buf);
> >> + break;
> >> + default:
> >> + DBG("Unhandled callback opcode=0x%x", opcode);
> >> + break;
> >> + }
> >> }
> > What I don't like about this is that you're not pushing the data length
> > to the handler functions. If you did that the handler functions could:
> >
> > if (len < sizeof(*ev))
> > return;
> >
> > Instead of return we could also just abort - what's the general policy
> > on the HAL side regarding invalid data from the daemon? How does this
> > relate to the work Szymon is doing to add proper checks for the IPC
> > data? Is that only for the daemon side?
> >
> > Are we missing similar checks in other HALs too?
>
> Yes, we are not doing similar checks in other HALs
> (hal-bluetooth/a2dp/hid/) too.
> Very few places in hal-bluetooth length is passing but validation is
> not done.
> I will fix them all and send you the patch.
As mentioned in my RFC, messages have very similar format and can be checked
in single place using some common macros. I'm now working on addressing Johan
comments in that RFC. As suggested I'm going to use tables of handlers instead
switch-case and this should also allow to refactor current code to avoid
switch-cases we currently have. Services will simply register own tables of
handlers for service they implement. Idea is that check will be done in common
place and then handlers will have form of void handle_foo(struct foo *ev) with
guarantee that passed command/event is memory size valid.
Plan is to make this generic code use both by hal and daemon.
So, I'm not sure if it makes much sense to fix passing buf+len to all handlers
we have now.
If you have other ideas for this please comment.
--
BR
Szymon Janc
^ permalink raw reply
* Re: [PATCH_v3 3/3] android/pan: Handle connection and control state notifications
From: Ravi Kumar Veeramally @ 2013-11-13 9:46 UTC (permalink / raw)
To: linux-bluetooth, Johan Hedberg
In-Reply-To: <20131113093301.GB1749@x220.p-661hnu-f1>
Hi Johan,
On 11/13/2013 11:33 AM, Johan Hedberg wrote:
> Hi Ravi,
>
> On Wed, Nov 13, 2013, Ravi kumar Veeramally wrote:
>> ---
>> android/hal-pan.c | 31 +++++++++++++++++++++++++++++++
>> 1 file changed, 31 insertions(+)
> I've applied the first two patches, but for this one I've got a few
> questions:
>
>> diff --git a/android/hal-pan.c b/android/hal-pan.c
>> index 851c5d2..2bc560e 100644
>> --- a/android/hal-pan.c
>> +++ b/android/hal-pan.c
>> @@ -31,10 +31,41 @@ static bool interface_ready(void)
>> return cbs != NULL;
>> }
>>
>> +static void handle_conn_state(void *buf)
>> +{
>> + struct hal_ev_pan_conn_state *ev = buf;
>> +
>> + if (cbs->connection_state_cb)
>> + cbs->connection_state_cb(ev->state, ev->status,
>> + (bt_bdaddr_t *) ev->bdaddr,
>> + ev->local_role, ev->remote_role);
>> +}
>> +
>> +static void handle_ctrl_state(void *buf)
>> +{
>> + struct hal_ev_pan_ctrl_state *ev = buf;
>> +
>> + if (cbs->control_state_cb)
>> + cbs->control_state_cb(ev->state, ev->status,
>> + ev->local_role, (char *)ev->name);
>> +}
>> +
>> void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len)
>> {
>> if (!interface_ready())
>> return;
>> +
>> + switch (opcode) {
>> + case HAL_EV_PAN_CONN_STATE:
>> + handle_conn_state(buf);
>> + break;
>> + case HAL_EV_PAN_CTRL_STATE:
>> + handle_ctrl_state(buf);
>> + break;
>> + default:
>> + DBG("Unhandled callback opcode=0x%x", opcode);
>> + break;
>> + }
>> }
> What I don't like about this is that you're not pushing the data length
> to the handler functions. If you did that the handler functions could:
>
> if (len < sizeof(*ev))
> return;
>
> Instead of return we could also just abort - what's the general policy
> on the HAL side regarding invalid data from the daemon? How does this
> relate to the work Szymon is doing to add proper checks for the IPC
> data? Is that only for the daemon side?
>
> Are we missing similar checks in other HALs too?
Yes, we are not doing similar checks in other HALs
(hal-bluetooth/a2dp/hid/) too.
Very few places in hal-bluetooth length is passing but validation is
not done.
I will fix them all and send you the patch.
Thanks,
Ravi.
^ permalink raw reply
* Re: [PATCH_v3 3/3] android/pan: Handle connection and control state notifications
From: Johan Hedberg @ 2013-11-13 9:33 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384334727-25940-3-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Wed, Nov 13, 2013, Ravi kumar Veeramally wrote:
> ---
> android/hal-pan.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
I've applied the first two patches, but for this one I've got a few
questions:
> diff --git a/android/hal-pan.c b/android/hal-pan.c
> index 851c5d2..2bc560e 100644
> --- a/android/hal-pan.c
> +++ b/android/hal-pan.c
> @@ -31,10 +31,41 @@ static bool interface_ready(void)
> return cbs != NULL;
> }
>
> +static void handle_conn_state(void *buf)
> +{
> + struct hal_ev_pan_conn_state *ev = buf;
> +
> + if (cbs->connection_state_cb)
> + cbs->connection_state_cb(ev->state, ev->status,
> + (bt_bdaddr_t *) ev->bdaddr,
> + ev->local_role, ev->remote_role);
> +}
> +
> +static void handle_ctrl_state(void *buf)
> +{
> + struct hal_ev_pan_ctrl_state *ev = buf;
> +
> + if (cbs->control_state_cb)
> + cbs->control_state_cb(ev->state, ev->status,
> + ev->local_role, (char *)ev->name);
> +}
> +
> void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len)
> {
> if (!interface_ready())
> return;
> +
> + switch (opcode) {
> + case HAL_EV_PAN_CONN_STATE:
> + handle_conn_state(buf);
> + break;
> + case HAL_EV_PAN_CTRL_STATE:
> + handle_ctrl_state(buf);
> + break;
> + default:
> + DBG("Unhandled callback opcode=0x%x", opcode);
> + break;
> + }
> }
What I don't like about this is that you're not pushing the data length
to the handler functions. If you did that the handler functions could:
if (len < sizeof(*ev))
return;
Instead of return we could also just abort - what's the general policy
on the HAL side regarding invalid data from the daemon? How does this
relate to the work Szymon is doing to add proper checks for the IPC
data? Is that only for the daemon side?
Are we missing similar checks in other HALs too?
Johan
^ permalink raw reply
* Re: [PATCH_v2 1/3] android/hidhost: Handle uhid output and feature events
From: Johan Hedberg @ 2013-11-13 9:27 UTC (permalink / raw)
To: Ravi Kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <528343B1.5020306@linux.intel.com>
Hi Ravi,
On Wed, Nov 13, 2013, Ravi Kumar Veeramally wrote:
> Hi Johan,
>
> >>+ sscanf((char *) &(ev->u.output.data)[i * 2],
> >>+ "%hhx", &(req + 1)[i]);
> >The last parameter is a bit of a brain twister. How about simply &req[1 + i]?
> >
> Yeap, simple :).
I fixed this up myself, so all three patches have now been applied.
Johan
^ permalink raw reply
* [PATCH_v3 3/3] android/pan: Handle connection and control state notifications
From: Ravi kumar Veeramally @ 2013-11-13 9:25 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1384334727-25940-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-pan.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index 851c5d2..2bc560e 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -31,10 +31,41 @@ static bool interface_ready(void)
return cbs != NULL;
}
+static void handle_conn_state(void *buf)
+{
+ struct hal_ev_pan_conn_state *ev = buf;
+
+ if (cbs->connection_state_cb)
+ cbs->connection_state_cb(ev->state, ev->status,
+ (bt_bdaddr_t *) ev->bdaddr,
+ ev->local_role, ev->remote_role);
+}
+
+static void handle_ctrl_state(void *buf)
+{
+ struct hal_ev_pan_ctrl_state *ev = buf;
+
+ if (cbs->control_state_cb)
+ cbs->control_state_cb(ev->state, ev->status,
+ ev->local_role, (char *)ev->name);
+}
+
void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len)
{
if (!interface_ready())
return;
+
+ switch (opcode) {
+ case HAL_EV_PAN_CONN_STATE:
+ handle_conn_state(buf);
+ break;
+ case HAL_EV_PAN_CTRL_STATE:
+ handle_ctrl_state(buf);
+ break;
+ default:
+ DBG("Unhandled callback opcode=0x%x", opcode);
+ break;
+ }
}
static bt_status_t pan_enable(int local_role)
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v3 2/3] android/pan: Add notify method to PAN notifications
From: Ravi kumar Veeramally @ 2013-11-13 9:25 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1384334727-25940-1-git-send-email-ravikumar.veeramally@linux.intel.com>
---
android/hal-pan.c | 6 ++++++
android/hal.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/android/hal-pan.c b/android/hal-pan.c
index bec179f..851c5d2 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -31,6 +31,12 @@ static bool interface_ready(void)
return cbs != NULL;
}
+void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len)
+{
+ if (!interface_ready())
+ return;
+}
+
static bt_status_t pan_enable(int local_role)
{
struct hal_cmd_pan_enable cmd;
diff --git a/android/hal.h b/android/hal.h
index baa4754..72090fe 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -31,3 +31,4 @@ void bt_thread_associate(void);
void bt_thread_disassociate(void);
void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len);
void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
+void bt_notify_pan(uint8_t opcode, void *buf, uint16_t len);
--
1.8.3.2
^ permalink raw reply related
* [PATCH_v3 1/3] android: Fix opcode parameter type from uint16_t to uint8_t
From: Ravi kumar Veeramally @ 2013-11-13 9:25 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally
---
android/hal-a2dp.c | 2 +-
android/hal-bluetooth.c | 2 +-
android/hal-hidhost.c | 2 +-
android/hal.h | 6 +++---
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index f0c301e..4fe7c20 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -49,7 +49,7 @@ static void handle_audio_state(void *buf)
}
/* will be called from notification thread context */
-void bt_notify_a2dp(uint16_t opcode, void *buf, uint16_t len)
+void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len)
{
if (!interface_ready())
return;
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 3e5d41f..1cfd994 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -281,7 +281,7 @@ static void handle_acl_state_changed(void *buf)
}
/* will be called from notification thread context */
-void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
+void bt_notify_adapter(uint8_t opcode, void *buf, uint16_t len)
{
if (!interface_ready())
return;
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 97a1aa0..2ce17a3 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -88,7 +88,7 @@ static void handle_virtual_unplug(void *buf)
}
/* will be called from notification thread context */
-void bt_notify_hidhost(uint16_t opcode, void *buf, uint16_t len)
+void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len)
{
if (!interface_ready())
return;
diff --git a/android/hal.h b/android/hal.h
index 2ce7932..baa4754 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -26,8 +26,8 @@ bthh_interface_t *bt_get_hidhost_interface(void);
btpan_interface_t *bt_get_pan_interface(void);
btav_interface_t *bt_get_a2dp_interface(void);
-void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len);
+void bt_notify_adapter(uint8_t opcode, void *buf, uint16_t len);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
-void bt_notify_hidhost(uint16_t opcode, void *buf, uint16_t len);
-void bt_notify_a2dp(uint16_t opcode, void *buf, uint16_t len);
+void bt_notify_hidhost(uint8_t opcode, void *buf, uint16_t len);
+void bt_notify_a2dp(uint8_t opcode, void *buf, uint16_t len);
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH_v2 1/3] android/hidhost: Handle uhid output and feature events
From: Ravi Kumar Veeramally @ 2013-11-13 9:17 UTC (permalink / raw)
To: linux-bluetooth, Johan Hedberg
In-Reply-To: <20131113090159.GA32659@x220.p-661hnu-f1>
Hi Johan,
>> + sscanf((char *) &(ev->u.output.data)[i * 2],
>> + "%hhx", &(req + 1)[i]);
> The last parameter is a bit of a brain twister. How about simply &req[1 + i]?
>
Yeap, simple :).
Thanks,
Ravi.
^ permalink raw reply
* Re: [PATCH_v2 1/3] android/hidhost: Handle uhid output and feature events
From: Johan Hedberg @ 2013-11-13 9:01 UTC (permalink / raw)
To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384268835-7570-1-git-send-email-ravikumar.veeramally@linux.intel.com>
Hi Ravi,
On Tue, Nov 12, 2013, Ravi kumar Veeramally wrote:
> + sscanf((char *) &(ev->u.output.data)[i * 2],
> + "%hhx", &(req + 1)[i]);
The last parameter is a bit of a brain twister. How about simply &req[1 + i]?
Johan
^ permalink raw reply
* [RFC BlueZ 3/3] input: Fix setting .local_uuid
From: Luiz Augusto von Dentz @ 2013-11-13 8:53 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384332813-7891-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
By setting .local_uuid it makes the core do a scrict check on uuids
enabled for the adapter but HID host does not have a record so it
does not require a .local_uuid to be set.
---
profiles/input/manager.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index 689ccdd..b12b43e 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -57,7 +57,6 @@ static void hid_server_remove(struct btd_profile *p,
static struct btd_profile input_profile = {
.name = "input-hid",
- .local_uuid = HID_UUID,
.remote_uuid = HID_UUID,
.auto_connect = true,
--
1.8.3.1
^ permalink raw reply related
* [RFC BlueZ 2/3] audio/A2DP: Set profile .local_uuid properly
From: Luiz Augusto von Dentz @ 2013-11-13 8:53 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384332813-7891-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
With the changes to the core now it does a strict match of adapter
profiles with .local_uuid to prevent connecting to profiles not
enabled in SDP.
---
profiles/audio/a2dp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 6b3d6b2..0a347e5 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -2008,6 +2008,7 @@ static struct btd_profile a2dp_source_profile = {
.name = "a2dp-source",
.priority = BTD_PROFILE_PRIORITY_MEDIUM,
+ .local_uuid = A2DP_SINK_UUID,
.remote_uuid = A2DP_SOURCE_UUID,
.device_probe = a2dp_source_probe,
.device_remove = a2dp_source_remove,
@@ -2024,6 +2025,7 @@ static struct btd_profile a2dp_sink_profile = {
.name = "a2dp-sink",
.priority = BTD_PROFILE_PRIORITY_MEDIUM,
+ .local_uuid = A2DP_SOURCE_UUID,
.remote_uuid = A2DP_SINK_UUID,
.device_probe = a2dp_sink_probe,
.device_remove = a2dp_sink_remove,
--
1.8.3.1
^ permalink raw reply related
* [RFC BlueZ 1/3] core/device: Only connect profiles which are enabled
From: Luiz Augusto von Dentz @ 2013-11-13 8:53 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1384332813-7891-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Some profile may register their records dynamically e.g. A2DP so the code
has to check if the profile is really available before attempting to
connect.
---
src/device.c | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/src/device.c b/src/device.c
index 9ca457e..60efd62 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1224,11 +1224,25 @@ void device_add_eir_uuids(struct btd_device *dev, GSList *uuids)
DEVICE_INTERFACE, "UUIDs");
}
+static int uuid_cmp(const void *a, const void *b)
+{
+ const sdp_record_t *rec = a;
+ const char *string = b;
+ uuid_t uuid;
+
+ if (bt_string2uuid(&uuid, string) < 0)
+ return -1;
+
+ return sdp_uuid_cmp(&rec->svclass, &uuid);
+}
+
static struct btd_service *find_connectable_service(struct btd_device *dev,
const char *uuid)
{
GSList *l;
+ sdp_list_t *uuids;
+ uuids = btd_adapter_get_services(dev->adapter);
for (l = dev->services; l != NULL; l = g_slist_next(l)) {
struct btd_service *service = l->data;
struct btd_profile *p = btd_service_get_profile(service);
@@ -1236,7 +1250,12 @@ static struct btd_service *find_connectable_service(struct btd_device *dev,
if (!p->connect || !p->remote_uuid)
continue;
- if (strcasecmp(uuid, p->remote_uuid) == 0)
+ if (strcasecmp(uuid, p->remote_uuid))
+ continue;
+
+ /* Check if adapter has the local_uuid enabled */
+ if (!p->local_uuid || sdp_list_find(uuids,
+ (void *) p->local_uuid, uuid_cmp))
return service;
}
@@ -1256,6 +1275,7 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
struct btd_service *service;
struct btd_profile *p;
GSList *l;
+ sdp_list_t *uuids;
if (uuid) {
service = find_connectable_service(dev, uuid);
@@ -1265,6 +1285,7 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
return dev->pending;
}
+ uuids = btd_adapter_get_services(dev->adapter);
for (l = dev->services; l != NULL; l = g_slist_next(l)) {
service = l->data;
p = btd_service_get_profile(service);
@@ -1272,14 +1293,18 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid)
if (!p->auto_connect)
continue;
- if (g_slist_find(dev->pending, service))
- continue;
-
if (btd_service_get_state(service) !=
BTD_SERVICE_STATE_DISCONNECTED)
continue;
- dev->pending = g_slist_insert_sorted(dev->pending, service,
+ if (g_slist_find(dev->pending, service))
+ continue;
+
+ /* Check if adapter has the local_uuid enabled */
+ if (!p->local_uuid || sdp_list_find(uuids,
+ (void *) p->local_uuid, uuid_cmp))
+ dev->pending = g_slist_insert_sorted(dev->pending,
+ service,
service_prio_cmp);
}
--
1.8.3.1
^ permalink raw reply related
* [RFC BlueZ 0/3] Check if profile local_uuid is enabled
From: Luiz Augusto von Dentz @ 2013-11-13 8:53 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This attempts to solve a problem with certain APIs that are adapter bond
such as Media interface and adapter_service_add as opposed to btd_profile
that is valid for every adapter.
Making Media API to be available on /org/bluez and perhaps tight btd_profile
and adapter_service_add should solve the problem in the long term but since
we cannot just break the API this is probably still necessary.
Luiz Augusto von Dentz (3):
core/device: Only connect profiles which are enabled
audio/A2DP: Set profile .local_uuid properly
input: Fix setting .local_uuid
profiles/audio/a2dp.c | 2 ++
profiles/input/manager.c | 1 -
src/device.c | 35 ++++++++++++++++++++++++++++++-----
3 files changed, 32 insertions(+), 6 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH RFC] tty_ldisc: add more limits to the @write_wakeup
From: Huang Shijie @ 2013-11-13 7:30 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, marcel, linux-bluetooth, Huang Shijie
In the uart_handle_cts_change(), uart_write_wakeup() is called after
we call @uart_port->ops->start_tx().
The Documentation/serial/driver tells us:
-----------------------------------------------
start_tx(port)
Start transmitting characters.
Locking: port->lock taken.
Interrupts: locally disabled.
-----------------------------------------------
So when the uart_write_wakeup() is called, the port->lock is taken by
the upper. See the following callstack:
|_ uart_write_wakeup
|_ tty_wakeup
|_ ld->ops->write_wakeup
With the port->lock held, we call the @write_wakeup. Some implemetation of
the @write_wakeup does not notice that the port->lock is held, and it still
tries to send data with uart_write() which will try to grab the prot->lock.
A dead lock occurs, see the following log caught in the Bluetooth by uart:
--------------------------------------------------------------------
BUG: spinlock lockup suspected on CPU#0, swapper/0/0
lock: 0xdc3f4410, .magic: dead4ead, .owner: swapper/0/0, .owner_cpu: 0
CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.10.17-16839-ge4a1bef #1320
[<80014cbc>] (unwind_backtrace+0x0/0x138) from [<8001251c>] (show_stack+0x10/0x14)
[<8001251c>] (show_stack+0x10/0x14) from [<802816ac>] (do_raw_spin_lock+0x108/0x184)
[<802816ac>] (do_raw_spin_lock+0x108/0x184) from [<806a22b0>] (_raw_spin_lock_irqsave+0x54/0x60)
[<806a22b0>] (_raw_spin_lock_irqsave+0x54/0x60) from [<802f5754>] (uart_write+0x38/0xe0)
[<802f5754>] (uart_write+0x38/0xe0) from [<80455270>] (hci_uart_tx_wakeup+0xa4/0x168)
[<80455270>] (hci_uart_tx_wakeup+0xa4/0x168) from [<802dab18>] (tty_wakeup+0x50/0x5c)
[<802dab18>] (tty_wakeup+0x50/0x5c) from [<802f81a4>] (imx_rtsint+0x50/0x80)
[<802f81a4>] (imx_rtsint+0x50/0x80) from [<802f88f4>] (imx_int+0x158/0x17c)
[<802f88f4>] (imx_int+0x158/0x17c) from [<8007abe0>] (handle_irq_event_percpu+0x50/0x194)
[<8007abe0>] (handle_irq_event_percpu+0x50/0x194) from [<8007ad60>] (handle_irq_event+0x3c/0x5c)
--------------------------------------------------------------------
This patch adds more limits to the @write_wakeup, the one who wants to
implemet the @write_wakeup should follow the limits which avoid the deadlock.
Signed-off-by: Huang Shijie <b32955@freescale.com>
---
include/linux/tty_ldisc.h | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index f15c898..539ccc5 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -91,7 +91,10 @@
* This function is called by the low-level tty driver to signal
* that line discpline should try to send more characters to the
* low-level driver for transmission. If the line discpline does
- * not have any more data to send, it can just return.
+ * not have any more data to send, it can just return. If the line
+ * discipline does have some data to send, please arise a tasklet
+ * or workqueue to do the real data transfer. Do not send data in
+ * this hook, it may leads to a deadlock.
*
* int (*hangup)(struct tty_struct *)
*
--
1.7.2.rc3
^ permalink raw reply related
* Re: shutdown(3) and bluetooth.
From: Marcel Holtmann @ 2013-11-13 1:58 UTC (permalink / raw)
To: Dave Jones; +Cc: netdev, linux-bluetooth@vger.kernel.org development
In-Reply-To: <20131113002819.GB12615@redhat.com>
Hi Dave,
>>> So it seems it affects both SCO and RFCOMM.
>>>
>>>> What kernel did you run this against? It is a shot in the dark, but can you try linux-next quickly.
>>>> There was a socket related fix for the socket options where we confused RFCOMM vs L2CAP struct sock.
>>>
>>> first noticed it on Linus' latest HEAD, and then reproduced it on 3.11.6
>>> I'll look at linux-next tomorrow.
>>
>> I looked through the code and only call bt_sock_wait_state when SOCK_LINGER and sk_lingertime is set. In that case we actually block until the socket state changes to BT_CLOSED.
>>
>> The only way I see this could happen is if you have a huge linger timeout and confused the socket state before. What is actually the list of system calls that you are throwing at this socket.
>
> Ah. I recently changed some code that's now doing this on every socket at shutdown..
> (simplified cut-n-paste)
>
> struct linger ling = { .l_onoff = FALSE, };
>
> for (i = 0; i < nr_sockets; i++) {
> fd = shm->sockets[i].fd;
> shm->sockets[i].fd = 0;
>
> setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger));
> shutdown(fd, SHUT_RDWR);
> close(fd);
> }
>
> I could just rip out that linger code completely and just hope that sockets staying in
> TIME_WAIT is good enough. iirc, I added it when after multiple runs, some of the
> weirder protocols would fail to open a socket once a certain number of existing
> sockets had opened, even if they were in SOCK_WAIT
>
> two remaining questions though. That code is setting linger to false. Why would
> that cause the sk_lingertime to be taken into consideration ? And why is this
> only a problem for bluetooth (apparently) ?
we are not touching that part of setsockopt. That is handled by net/core/sock.c and we just check if SOCK_LINGER flag is set and if we have a positive sk_lingertime. So this is a bit suspicious on why this is happening, but I don’t think it is our mistake.
Regards
Marcel
^ permalink raw reply
* Re: shutdown(3) and bluetooth.
From: Dave Jones @ 2013-11-13 0:28 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: netdev, linux-bluetooth@vger.kernel.org development
In-Reply-To: <D8BE686E-E81D-48CD-8D67-2B138191E0CC@holtmann.org>
On Wed, Nov 13, 2013 at 08:37:15AM +0900, Marcel Holtmann wrote:
> > So it seems it affects both SCO and RFCOMM.
> >
> >> What kernel did you run this against? It is a shot in the dark, but can you try linux-next quickly.
> >> There was a socket related fix for the socket options where we confused RFCOMM vs L2CAP struct sock.
> >
> > first noticed it on Linus' latest HEAD, and then reproduced it on 3.11.6
> > I'll look at linux-next tomorrow.
>
> I looked through the code and only call bt_sock_wait_state when SOCK_LINGER and sk_lingertime is set. In that case we actually block until the socket state changes to BT_CLOSED.
>
> The only way I see this could happen is if you have a huge linger timeout and confused the socket state before. What is actually the list of system calls that you are throwing at this socket.
Ah. I recently changed some code that's now doing this on every socket at shutdown..
(simplified cut-n-paste)
struct linger ling = { .l_onoff = FALSE, };
for (i = 0; i < nr_sockets; i++) {
fd = shm->sockets[i].fd;
shm->sockets[i].fd = 0;
setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger));
shutdown(fd, SHUT_RDWR);
close(fd);
}
I could just rip out that linger code completely and just hope that sockets staying in
TIME_WAIT is good enough. iirc, I added it when after multiple runs, some of the
weirder protocols would fail to open a socket once a certain number of existing
sockets had opened, even if they were in SOCK_WAIT
two remaining questions though. That code is setting linger to false. Why would
that cause the sk_lingertime to be taken into consideration ? And why is this
only a problem for bluetooth (apparently) ?
Dave
^ permalink raw reply
* [PATCH v2 8/8] android: Rename bluetooth service functions to match service name
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
Make public functions match service name.
---
android/bluetooth.c | 26 +++++++++++++-------------
android/bluetooth.h | 16 ++++++++--------
android/main.c | 13 +++++++------
3 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 7a33d4f..39589fa 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -938,7 +938,7 @@ static void register_mgmt_handlers(void)
static void load_link_keys_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
- bt_adapter_ready cb = user_data;
+ bt_bluetooth_ready cb = user_data;
int err;
if (status) {
@@ -957,7 +957,7 @@ failed:
cb(err, NULL);
}
-static void load_link_keys(GSList *keys, bt_adapter_ready cb)
+static void load_link_keys(GSList *keys, bt_bluetooth_ready cb)
{
struct mgmt_cp_load_link_keys *cp;
struct mgmt_link_key_info *key;
@@ -1279,7 +1279,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
const struct mgmt_rp_read_info *rp = param;
- bt_adapter_ready cb = user_data;
+ bt_bluetooth_ready cb = user_data;
uint32_t missing_settings, supported_settings;
int err;
@@ -1342,7 +1342,7 @@ failed:
static void mgmt_index_added_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
- bt_adapter_ready cb = user_data;
+ bt_bluetooth_ready cb = user_data;
DBG("index %u", index);
@@ -1379,7 +1379,7 @@ static void read_index_list_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
const struct mgmt_rp_read_index_list *rp = param;
- bt_adapter_ready cb = user_data;
+ bt_bluetooth_ready cb = user_data;
uint16_t num;
int i;
@@ -1433,7 +1433,7 @@ static void read_version_complete(uint8_t status, uint16_t length,
{
const struct mgmt_rp_read_version *rp = param;
uint8_t mgmt_version, mgmt_revision;
- bt_adapter_ready cb = user_data;
+ bt_bluetooth_ready cb = user_data;
DBG("");
@@ -1474,7 +1474,7 @@ failed:
cb(-EIO, NULL);
}
-bool bt_adapter_start(int index, bt_adapter_ready cb)
+bool bt_bluetooth_start(int index, bt_bluetooth_ready cb)
{
DBG("index %d", index);
@@ -1503,7 +1503,7 @@ bool bt_adapter_start(int index, bt_adapter_ready cb)
static void shutdown_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
- bt_adapter_stopped cb = user_data;
+ bt_bluetooth_stopped cb = user_data;
if (status != MGMT_STATUS_SUCCESS)
error("Clean controller shutdown failed");
@@ -1511,7 +1511,7 @@ static void shutdown_complete(uint8_t status, uint16_t length,
cb();
}
-bool bt_adapter_stop(bt_adapter_stopped cb)
+bool bt_bluetooth_stop(bt_bluetooth_stopped cb)
{
struct mgmt_mode cp;
@@ -1527,7 +1527,7 @@ bool bt_adapter_stop(bt_adapter_stopped cb)
NULL) > 0;
}
-void bt_adapter_cleanup(void)
+void bt_bluetooth_cleanup(void)
{
g_free(adapter.name);
adapter.name = NULL;
@@ -2041,7 +2041,7 @@ static uint8_t get_remote_services(void *buf, uint16_t len)
return browse_remote_sdp(&addr);
}
-void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
+void bt_bluetooth_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
{
uint8_t status = HAL_STATUS_FAILED;
@@ -2160,7 +2160,7 @@ error:
ipc_send_rsp(sk, HAL_SERVICE_ID_BLUETOOTH, status);
}
-bool bt_adapter_register(int sk)
+bool bt_bluetooth_register(int sk)
{
DBG("");
@@ -2169,7 +2169,7 @@ bool bt_adapter_register(int sk)
return true;
}
-void bt_adapter_unregister(void)
+void bt_bluetooth_unregister(void)
{
DBG("");
diff --git a/android/bluetooth.h b/android/bluetooth.h
index 99bd85f..44b8e9e 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -21,18 +21,18 @@
*
*/
-typedef void (*bt_adapter_ready)(int err, const bdaddr_t *addr);
-bool bt_adapter_start(int index, bt_adapter_ready cb);
+typedef void (*bt_bluetooth_ready)(int err, const bdaddr_t *addr);
+bool bt_bluetooth_start(int index, bt_bluetooth_ready cb);
-typedef void (*bt_adapter_stopped)(void);
-bool bt_adapter_stop(bt_adapter_stopped cb);
+typedef void (*bt_bluetooth_stopped)(void);
+bool bt_bluetooth_stop(bt_bluetooth_stopped cb);
-void bt_adapter_cleanup(void);
+void bt_bluetooth_cleanup(void);
-void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
+void bt_bluetooth_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-bool bt_adapter_register(int sk);
-void bt_adapter_unregister(void);
+bool bt_bluetooth_register(int sk);
+void bt_bluetooth_unregister(void);
int bt_adapter_add_record(sdp_record_t *rec, uint8_t svc_hint);
void bt_adapter_remove_record(uint32_t handle);
diff --git a/android/main.c b/android/main.c
index e4c93ec..cbbfc06 100644
--- a/android/main.c
+++ b/android/main.c
@@ -84,7 +84,7 @@ static void service_register(void *buf, uint16_t len)
switch (m->service_id) {
case HAL_SERVICE_ID_BLUETOOTH:
- if (!bt_adapter_register(sk))
+ if (!bt_bluetooth_register(sk))
goto failed;
break;
@@ -134,7 +134,7 @@ static void service_unregister(void *buf, uint16_t len)
switch (m->service_id) {
case HAL_SERVICE_ID_BLUETOOTH:
- bt_adapter_unregister();
+ bt_bluetooth_unregister();
break;
case HAL_SERVICE_ID_SOCK:
bt_socket_unregister();
@@ -203,7 +203,7 @@ static void stop_bluetooth(void)
__stop = true;
- if (!bt_adapter_stop(bluetooth_stopped)) {
+ if (!bt_bluetooth_stop(bluetooth_stopped)) {
g_main_loop_quit(event_loop);
return;
}
@@ -251,7 +251,8 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
handle_service_core(msg->opcode, msg->payload, msg->len);
break;
case HAL_SERVICE_ID_BLUETOOTH:
- bt_adapter_handle_cmd(fd, msg->opcode, msg->payload, msg->len);
+ bt_bluetooth_handle_cmd(fd, msg->opcode, msg->payload,
+ msg->len);
break;
case HAL_SERVICE_ID_HIDHOST:
bt_hid_handle_cmd(fd, msg->opcode, msg->payload, msg->len);
@@ -560,7 +561,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
- if (!bt_adapter_start(option_index, adapter_ready))
+ if (!bt_bluetooth_start(option_index, adapter_ready))
return EXIT_FAILURE;
/* Use params: mtu = 0, flags = 0 */
@@ -574,7 +575,7 @@ int main(int argc, char *argv[])
cleanup_hal_connection();
stop_sdp_server();
- bt_adapter_cleanup();
+ bt_bluetooth_cleanup();
g_main_loop_unref(event_loop);
info("Exit");
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 6/8] android: Remove not needed bt_adapter_get_address function
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
All services receive adapter address on init so there is no need for
this function. Removing it will also help keeping services not depend
on adapter service.
---
android/adapter.c | 5 -----
android/adapter.h | 2 --
2 files changed, 7 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index dcb823b..3f135be 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -2160,11 +2160,6 @@ error:
ipc_send_rsp(sk, HAL_SERVICE_ID_BLUETOOTH, status);
}
-const bdaddr_t *bt_adapter_get_address(void)
-{
- return &adapter.bdaddr;
-}
-
bool bt_adapter_register(int sk)
{
DBG("");
diff --git a/android/adapter.h b/android/adapter.h
index 68f2046..99bd85f 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -31,8 +31,6 @@ void bt_adapter_cleanup(void);
void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-const bdaddr_t *bt_adapter_get_address(void);
-
bool bt_adapter_register(int sk);
void bt_adapter_unregister(void);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 5/8] android: Report adapter address in adapter_ready callback
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
Adapter is not going to change while daemon is running so its address
can be stored after init is complete.
---
android/adapter.c | 14 +++++++-------
android/adapter.h | 2 +-
android/main.c | 7 +++++--
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index 001059a..dcb823b 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -950,11 +950,11 @@ static void load_link_keys_complete(uint8_t status, uint16_t length,
DBG("status %u", status);
- cb(0);
+ cb(0, &adapter.bdaddr);
return;
failed:
- cb(err);
+ cb(err, NULL);
}
static void load_link_keys(GSList *keys, bt_adapter_ready cb)
@@ -989,7 +989,7 @@ static void load_link_keys(GSList *keys, bt_adapter_ready cb)
if (id == 0) {
error("Failed to load link keys");
- cb(-EIO);
+ cb(-EIO, NULL);
}
}
@@ -1336,7 +1336,7 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
return;
failed:
- cb(err);
+ cb(err, NULL);
}
static void mgmt_index_added_event(uint16_t index, uint16_t length,
@@ -1358,7 +1358,7 @@ static void mgmt_index_added_event(uint16_t index, uint16_t length,
if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
read_info_complete, cb, NULL) == 0) {
- cb(-EIO);
+ cb(-EIO, NULL);
return;
}
}
@@ -1425,7 +1425,7 @@ static void read_index_list_complete(uint8_t status, uint16_t length,
return;
failed:
- cb(-EIO);
+ cb(-EIO, NULL);
}
static void read_version_complete(uint8_t status, uint16_t length,
@@ -1471,7 +1471,7 @@ static void read_version_complete(uint8_t status, uint16_t length,
error("Failed to read controller index list");
failed:
- cb(-EIO);
+ cb(-EIO, NULL);
}
bool bt_adapter_start(int index, bt_adapter_ready cb)
diff --git a/android/adapter.h b/android/adapter.h
index e8993f2..68f2046 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -21,7 +21,7 @@
*
*/
-typedef void (*bt_adapter_ready)(int err);
+typedef void (*bt_adapter_ready)(int err, const bdaddr_t *addr);
bool bt_adapter_start(int index, bt_adapter_ready cb);
typedef void (*bt_adapter_stopped)(void);
diff --git a/android/main.c b/android/main.c
index f82e6d8..27513f8 100644
--- a/android/main.c
+++ b/android/main.c
@@ -65,6 +65,8 @@
static guint bluetooth_start_timeout = 0;
+static const bdaddr_t *adapter_bdaddr = NULL;
+
static GMainLoop *event_loop;
static GIOChannel *hal_cmd_io = NULL;
@@ -75,7 +77,6 @@ static bool services[HAL_SERVICE_ID_MAX + 1] = { false };
static void service_register(void *buf, uint16_t len)
{
struct hal_cmd_register_module *m = buf;
- const bdaddr_t *adapter_bdaddr = bt_adapter_get_address();
int sk = g_io_channel_unix_get_fd(hal_notif_io);
if (m->service_id > HAL_SERVICE_ID_MAX || services[m->service_id])
@@ -365,13 +366,15 @@ static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
return FALSE;
}
-static void adapter_ready(int err)
+static void adapter_ready(int err, const bdaddr_t *addr)
{
if (err < 0) {
error("Adapter initialization failed: %s", strerror(-err));
exit(EXIT_FAILURE);
}
+ adapter_bdaddr = addr;
+
if (bluetooth_start_timeout > 0) {
g_source_remove(bluetooth_start_timeout);
bluetooth_start_timeout = 0;
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 4/8] android/hidhost: Use adapter address provided on register
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
There is no need to use bt_adapter_get_address every time local address
is needed.
---
android/hidhost.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index cba80a6..cf670d6 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -47,7 +47,6 @@
#include "hal-msg.h"
#include "ipc.h"
#include "hidhost.h"
-#include "adapter.h"
#include "utils.h"
#define L2CAP_PSM_HIDP_CTRL 0x11
@@ -77,6 +76,8 @@
/* HID Virtual Cable Unplug */
#define HID_VIRTUAL_CABLE_UNPLUG 0x05
+static const bdaddr_t *adapter_addr = NULL;
+
static int notification_sk = -1;
static GIOChannel *ctrl_io = NULL;
static GIOChannel *intr_io = NULL;
@@ -563,7 +564,6 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
{
struct hid_device *dev = user_data;
GError *err = NULL;
- const bdaddr_t *src = bt_adapter_get_address();
DBG("");
@@ -575,7 +575,7 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
/* Connect to the HID interrupt channel */
dev->intr_io = bt_io_connect(interrupt_connect_cb, dev, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_SOURCE_BDADDR, adapter_addr,
BT_IO_OPT_DEST_BDADDR, &dev->dst,
BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
@@ -601,7 +601,6 @@ static void hid_sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
struct hid_device *dev = data;
sdp_list_t *list;
GError *gerr = NULL;
- const bdaddr_t *src = bt_adapter_get_address();
DBG("");
@@ -675,7 +674,7 @@ static void hid_sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
}
dev->ctrl_io = bt_io_connect(control_connect_cb, dev, NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_SOURCE_BDADDR, adapter_addr,
BT_IO_OPT_DEST_BDADDR, &dev->dst,
BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
@@ -700,7 +699,6 @@ static uint8_t bt_hid_connect(struct hal_cmd_hidhost_connect *cmd,
char addr[18];
bdaddr_t dst;
GSList *l;
- const bdaddr_t *src = bt_adapter_get_address();
uuid_t uuid;
DBG("");
@@ -722,8 +720,8 @@ static uint8_t bt_hid_connect(struct hal_cmd_hidhost_connect *cmd,
DBG("connecting to %s", addr);
bt_string2uuid(&uuid, HID_UUID);
- if (bt_search_service(src, &dev->dst, &uuid, hid_sdp_search_cb, dev,
- NULL) < 0) {
+ if (bt_search_service(adapter_addr, &dev->dst, &uuid,
+ hid_sdp_search_cb, dev, NULL) < 0) {
error("Failed to search sdp details");
hid_device_free(dev);
return HAL_STATUS_FAILED;
@@ -1161,12 +1159,13 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
bool bt_hid_register(int sk, const bdaddr_t *addr)
{
GError *err = NULL;
- const bdaddr_t *src = bt_adapter_get_address();
DBG("");
+ adapter_addr = addr;
+
ctrl_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_SOURCE_BDADDR, adapter_addr,
BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
BT_IO_OPT_INVALID);
@@ -1177,7 +1176,7 @@ bool bt_hid_register(int sk, const bdaddr_t *addr)
}
intr_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_SOURCE_BDADDR, adapter_addr,
BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
BT_IO_OPT_INVALID);
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 3/8] android: Don't use static pointer for storing adapter_ready callback
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
There is no need to keep ready callback for daemon lifetime as it is
not used after reporting adapter being ready. Use mgmt library feature
for passing user data so that static pointer is not needed.
---
android/adapter.c | 40 +++++++++++++++++++++-------------------
1 file changed, 21 insertions(+), 19 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index 1d628c8..001059a 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -65,8 +65,6 @@ static int notification_sk = -1;
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
-static bt_adapter_ready adapter_ready = NULL;
-
static struct mgmt *mgmt_if = NULL;
static struct {
@@ -940,6 +938,7 @@ static void register_mgmt_handlers(void)
static void load_link_keys_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
+ bt_adapter_ready cb = user_data;
int err;
if (status) {
@@ -951,14 +950,14 @@ static void load_link_keys_complete(uint8_t status, uint16_t length,
DBG("status %u", status);
- adapter_ready(0);
+ cb(0);
return;
failed:
- adapter_ready(err);
+ cb(err);
}
-static void load_link_keys(GSList *keys)
+static void load_link_keys(GSList *keys, bt_adapter_ready cb)
{
struct mgmt_cp_load_link_keys *cp;
struct mgmt_link_key_info *key;
@@ -984,13 +983,13 @@ static void load_link_keys(GSList *keys)
memcpy(key, keys->data, sizeof(*key));
id = mgmt_send(mgmt_if, MGMT_OP_LOAD_LINK_KEYS, adapter.index,
- cp_size, cp, load_link_keys_complete, NULL, NULL);
+ cp_size, cp, load_link_keys_complete, cb, NULL);
g_free(cp);
if (id == 0) {
error("Failed to load link keys");
- adapter_ready(-EIO);
+ cb(-EIO);
}
}
@@ -1280,6 +1279,7 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
void *user_data)
{
const struct mgmt_rp_read_info *rp = param;
+ bt_adapter_ready cb = user_data;
uint32_t missing_settings, supported_settings;
int err;
@@ -1320,7 +1320,7 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
clear_uuids();
- load_link_keys(NULL);
+ load_link_keys(NULL, cb);
set_io_capability();
set_device_id();
@@ -1336,12 +1336,14 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
return;
failed:
- adapter_ready(err);
+ cb(err);
}
static void mgmt_index_added_event(uint16_t index, uint16_t length,
const void *param, void *user_data)
{
+ bt_adapter_ready cb = user_data;
+
DBG("index %u", index);
if (adapter.index != MGMT_INDEX_NONE) {
@@ -1355,8 +1357,8 @@ static void mgmt_index_added_event(uint16_t index, uint16_t length,
}
if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
- read_info_complete, NULL, NULL) == 0) {
- adapter_ready(-EIO);
+ read_info_complete, cb, NULL) == 0) {
+ cb(-EIO);
return;
}
}
@@ -1377,6 +1379,7 @@ static void read_index_list_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
const struct mgmt_rp_read_index_list *rp = param;
+ bt_adapter_ready cb = user_data;
uint16_t num;
int i;
@@ -1412,7 +1415,7 @@ static void read_index_list_complete(uint8_t status, uint16_t length,
continue;
if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
- read_info_complete, NULL, NULL) == 0)
+ read_info_complete, cb, NULL) == 0)
goto failed;
adapter.index = index;
@@ -1422,7 +1425,7 @@ static void read_index_list_complete(uint8_t status, uint16_t length,
return;
failed:
- adapter_ready(-EIO);
+ cb(-EIO);
}
static void read_version_complete(uint8_t status, uint16_t length,
@@ -1430,6 +1433,7 @@ static void read_version_complete(uint8_t status, uint16_t length,
{
const struct mgmt_rp_read_version *rp = param;
uint8_t mgmt_version, mgmt_revision;
+ bt_adapter_ready cb = user_data;
DBG("");
@@ -1456,18 +1460,18 @@ static void read_version_complete(uint8_t status, uint16_t length,
}
mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
- mgmt_index_added_event, NULL, NULL);
+ mgmt_index_added_event, cb, NULL);
mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
mgmt_index_removed_event, NULL, NULL);
if (mgmt_send(mgmt_if, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
- NULL, read_index_list_complete, NULL, NULL) > 0)
+ NULL, read_index_list_complete, cb, NULL) > 0)
return;
error("Failed to read controller index list");
failed:
- adapter_ready(-EIO);
+ cb(-EIO);
}
bool bt_adapter_start(int index, bt_adapter_ready cb)
@@ -1481,7 +1485,7 @@ bool bt_adapter_start(int index, bt_adapter_ready cb)
}
if (mgmt_send(mgmt_if, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE, 0, NULL,
- read_version_complete, NULL, NULL) == 0) {
+ read_version_complete, cb, NULL) == 0) {
error("Error sending READ_VERSION mgmt command");
mgmt_unref(mgmt_if);
@@ -1493,8 +1497,6 @@ bool bt_adapter_start(int index, bt_adapter_ready cb)
if (index >= 0)
option_index = index;
- adapter_ready = cb;
-
return true;
}
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 2/8] android: Move adapter initialization to adapter.c
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
There is no need to handle that in main.c. Also this removes mgmt
interface dependency from adapter API as all mgmt commands are handled
from adapter code.
Startup and shutdown timeouts handling is left in main.c.
---
android/adapter.c | 195 +++++++++++++++++++++++++++++++++--
android/adapter.h | 7 +-
android/main.c | 300 +++++++++---------------------------------------------
3 files changed, 240 insertions(+), 262 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index f8bfb36..1d628c8 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -58,6 +58,8 @@
#define BASELEN_PROP_CHANGED sizeof(struct hal_ev_adapter_props_changed) \
+ (sizeof(struct hal_property))
+static uint16_t option_index = MGMT_INDEX_NONE;
+
static int notification_sk = -1;
/* This list contains addresses which are asked for records */
@@ -1337,28 +1339,201 @@ failed:
adapter_ready(err);
}
-void bt_adapter_init(uint16_t index, struct mgmt *mgmt, bt_adapter_ready cb)
+static void mgmt_index_added_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
{
- mgmt_if = mgmt_ref(mgmt);
+ DBG("index %u", index);
- adapter.index = index;
+ if (adapter.index != MGMT_INDEX_NONE) {
+ DBG("skip event for index %u", index);
+ return;
+ }
- adapter_ready = cb;
+ if (option_index != MGMT_INDEX_NONE && option_index != index) {
+ DBG("skip event for index %u (option %u)", index, option_index);
+ return;
+ }
- /* TODO: Read discoverable timeout from some storage */
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
+ read_info_complete, NULL, NULL) == 0) {
+ adapter_ready(-EIO);
+ return;
+ }
+}
- if (mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
- read_info_complete, NULL, NULL) > 0)
+static void mgmt_index_removed_event(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ DBG("index %u", index);
+
+ if (index != adapter.index)
return;
- mgmt_unref(mgmt_if);
- mgmt_if = NULL;
+ error("Adapter was removed. Exiting.");
+ raise(SIGTERM);
+}
+
+static void read_index_list_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_index_list *rp = param;
+ uint16_t num;
+ int i;
+
+ DBG("");
+
+ if (status) {
+ error("%s: Failed to read index list: %s (0x%02x)",
+ __func__, mgmt_errstr(status), status);
+ goto failed;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("%s: Wrong size of read index list response", __func__);
+ goto failed;
+ }
+
+ num = btohs(rp->num_controllers);
+
+ DBG("Number of controllers: %u", num);
+
+ if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
+ error("%s: Incorrect pkt size for index list rsp", __func__);
+ goto failed;
+ }
+
+ if (adapter.index != MGMT_INDEX_NONE)
+ return;
+
+ for (i = 0; i < num; i++) {
+ uint16_t index = btohs(rp->index[i]);
+
+ if (option_index != MGMT_INDEX_NONE && option_index != index)
+ continue;
+
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_INFO, index, 0, NULL,
+ read_info_complete, NULL, NULL) == 0)
+ goto failed;
+
+ adapter.index = index;
+ return;
+ }
+
+ return;
+
+failed:
+ adapter_ready(-EIO);
+}
+
+static void read_version_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_read_version *rp = param;
+ uint8_t mgmt_version, mgmt_revision;
+
+ DBG("");
+
+ if (status) {
+ error("Failed to read version information: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ goto failed;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Wrong size response");
+ goto failed;
+ }
- adapter.index = MGMT_INDEX_NONE;
+ mgmt_version = rp->version;
+ mgmt_revision = btohs(rp->revision);
+
+ info("Bluetooth management interface %u.%u initialized",
+ mgmt_version, mgmt_revision);
+
+ if (MGMT_VERSION(mgmt_version, mgmt_revision) < MGMT_VERSION(1, 3)) {
+ error("Version 1.3 or later of management interface required");
+ goto failed;
+ }
+
+ mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
+ mgmt_index_added_event, NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
+ mgmt_index_removed_event, NULL, NULL);
+
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
+ NULL, read_index_list_complete, NULL, NULL) > 0)
+ return;
+ error("Failed to read controller index list");
+
+failed:
adapter_ready(-EIO);
}
+bool bt_adapter_start(int index, bt_adapter_ready cb)
+{
+ DBG("index %d", index);
+
+ mgmt_if = mgmt_new_default();
+ if (!mgmt_if) {
+ error("Failed to access management interface");
+ return false;
+ }
+
+ if (mgmt_send(mgmt_if, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE, 0, NULL,
+ read_version_complete, NULL, NULL) == 0) {
+ error("Error sending READ_VERSION mgmt command");
+
+ mgmt_unref(mgmt_if);
+ mgmt_if = NULL;
+
+ return false;
+ }
+
+ if (index >= 0)
+ option_index = index;
+
+ adapter_ready = cb;
+
+ return true;
+}
+
+static void shutdown_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ bt_adapter_stopped cb = user_data;
+
+ if (status != MGMT_STATUS_SUCCESS)
+ error("Clean controller shutdown failed");
+
+ cb();
+}
+
+bool bt_adapter_stop(bt_adapter_stopped cb)
+{
+ struct mgmt_mode cp;
+
+ if (adapter.index == MGMT_INDEX_NONE)
+ return false;
+
+ info("Switching controller off");
+
+ memset(&cp, 0, sizeof(cp));
+
+ return mgmt_send(mgmt_if, MGMT_OP_SET_POWERED, adapter.index,
+ sizeof(cp), &cp, shutdown_complete, (void *)cb,
+ NULL) > 0;
+}
+
+void bt_adapter_cleanup(void)
+{
+ g_free(adapter.name);
+ adapter.name = NULL;
+
+ mgmt_unref(mgmt_if);
+ mgmt_if = NULL;
+}
+
static bool set_discoverable(uint8_t mode, uint16_t timeout)
{
struct mgmt_cp_set_discoverable cp;
diff --git a/android/adapter.h b/android/adapter.h
index 0e84cb0..e8993f2 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -22,9 +22,12 @@
*/
typedef void (*bt_adapter_ready)(int err);
+bool bt_adapter_start(int index, bt_adapter_ready cb);
-void bt_adapter_init(uint16_t index, struct mgmt *mgmt_if,
- bt_adapter_ready cb);
+typedef void (*bt_adapter_stopped)(void);
+bool bt_adapter_stop(bt_adapter_stopped cb);
+
+void bt_adapter_cleanup(void);
void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
diff --git a/android/main.c b/android/main.c
index 36cc8aa..f82e6d8 100644
--- a/android/main.c
+++ b/android/main.c
@@ -45,8 +45,6 @@
#include "src/sdpd.h"
#include "lib/bluetooth.h"
-#include "lib/mgmt.h"
-#include "src/shared/mgmt.h"
#include "adapter.h"
#include "socket.h"
@@ -65,11 +63,9 @@
#define STARTUP_GRACE_SECONDS 5
#define SHUTDOWN_GRACE_SECONDS 10
-static GMainLoop *event_loop;
-static struct mgmt *mgmt_if = NULL;
+static guint bluetooth_start_timeout = 0;
-static uint16_t adapter_index = MGMT_INDEX_NONE;
-static guint adapter_timeout = 0;
+static GMainLoop *event_loop;
static GIOChannel *hal_cmd_io = NULL;
static GIOChannel *hal_notif_io = NULL;
@@ -186,35 +182,32 @@ static void handle_service_core(uint8_t opcode, void *buf, uint16_t len)
}
}
-static void shutdown_complete(uint8_t status, uint16_t length,
- const void *param, void *user_data)
+static void bluetooth_stopped(void)
{
- if (status != MGMT_STATUS_SUCCESS)
- error("Clean controller shutdown failed");
+ g_main_loop_quit(event_loop);
+}
+static gboolean quit_eventloop(gpointer user_data)
+{
g_main_loop_quit(event_loop);
+ return FALSE;
}
-static void shutdown_controller(void)
+static void stop_bluetooth(void)
{
- static bool __shutdown = false;
- struct mgmt_mode cp;
+ static bool __stop = false;
- if (__shutdown)
+ if (__stop)
return;
- __shutdown = true;
-
- info("Switching controller off");
+ __stop = true;
- memset(&cp, 0, sizeof(cp));
- cp.val = 0x00;
-
- if (mgmt_send(mgmt_if, MGMT_OP_SET_POWERED, adapter_index,
- sizeof(cp), &cp, shutdown_complete, NULL, NULL) > 0)
+ if (!bt_adapter_stop(bluetooth_stopped)) {
+ g_main_loop_quit(event_loop);
return;
+ }
- g_main_loop_quit(event_loop);
+ g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS, quit_eventloop, NULL);
}
static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
@@ -279,7 +272,7 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
return TRUE;
fail:
- shutdown_controller();
+ stop_bluetooth();
return FALSE;
}
@@ -287,7 +280,7 @@ static gboolean notif_watch_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
info("HAL notification socket closed, terminating");
- shutdown_controller();
+ stop_bluetooth();
return FALSE;
}
@@ -336,7 +329,7 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
DBG("");
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
- g_main_loop_quit(event_loop);
+ stop_bluetooth();
return FALSE;
}
@@ -359,23 +352,38 @@ static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
DBG("");
if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
- g_main_loop_quit(event_loop);
+ stop_bluetooth();
return FALSE;
}
hal_notif_io = connect_hal(notif_connect_cb);
if (!hal_notif_io) {
error("Cannot connect to HAL, terminating");
- g_main_loop_quit(event_loop);
+ stop_bluetooth();
}
return FALSE;
}
-static gboolean quit_eventloop(gpointer user_data)
+static void adapter_ready(int err)
{
- g_main_loop_quit(event_loop);
- return FALSE;
+ if (err < 0) {
+ error("Adapter initialization failed: %s", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ if (bluetooth_start_timeout > 0) {
+ g_source_remove(bluetooth_start_timeout);
+ bluetooth_start_timeout = 0;
+ }
+
+ info("Adapter initialized");
+
+ hal_cmd_io = connect_hal(cmd_connect_cb);
+ if (!hal_cmd_io) {
+ error("Cannot connect to HAL, terminating");
+ stop_bluetooth();
+ }
}
static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
@@ -400,12 +408,7 @@ static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
case SIGTERM:
if (!__terminated) {
info("Terminating");
- if (adapter_index != MGMT_INDEX_NONE) {
- g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
- quit_eventloop, NULL);
- shutdown_controller();
- } else
- g_main_loop_quit(event_loop);
+ stop_bluetooth();
}
__terminated = true;
@@ -453,7 +456,7 @@ static guint setup_signalfd(void)
}
static gboolean option_version = FALSE;
-static gint option_index = MGMT_INDEX_NONE;
+static gint option_index = -1;
static GOptionEntry options[] = {
{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
@@ -463,216 +466,6 @@ static GOptionEntry options[] = {
{ NULL }
};
-static void adapter_ready(int err)
-{
- if (err < 0) {
- error("Adapter initialization failed: %s", strerror(-err));
- exit(EXIT_FAILURE);
- }
-
- info("Adapter initialized");
-
- hal_cmd_io = connect_hal(cmd_connect_cb);
- if (!hal_cmd_io) {
- error("Cannot connect to HAL, terminating");
- g_main_loop_quit(event_loop);
- }
-}
-
-static void mgmt_index_added_event(uint16_t index, uint16_t length,
- const void *param, void *user_data)
-{
- uint16_t opt_index = option_index;
-
- DBG("index %u", index);
-
- if (adapter_index != MGMT_INDEX_NONE) {
- DBG("skip event for index %u", index);
- return;
- }
-
- if (opt_index != MGMT_INDEX_NONE && opt_index != index) {
- DBG("skip event for index %u (option %u)", index, opt_index);
- return;
- }
-
- if (adapter_timeout > 0) {
- g_source_remove(adapter_timeout);
- adapter_timeout = 0;
- }
-
- adapter_index = index;
- bt_adapter_init(index, mgmt_if, adapter_ready);
-}
-
-static void mgmt_index_removed_event(uint16_t index, uint16_t length,
- const void *param, void *user_data)
-{
- DBG("index %u", index);
-
- if (index != adapter_index)
- return;
-
- error("Adapter was removed. Exiting.");
- g_main_loop_quit(event_loop);
-}
-
-static gboolean adapter_timeout_handler(gpointer user_data)
-{
- adapter_timeout = 0;
- g_main_loop_quit(event_loop);
-
- return FALSE;
-}
-
-static void read_index_list_complete(uint8_t status, uint16_t length,
- const void *param, void *user_data)
-{
- const struct mgmt_rp_read_index_list *rp = param;
- uint16_t opt_index = option_index;
- uint16_t num;
- int i;
-
- DBG("");
-
- if (status) {
- error("%s: Failed to read index list: %s (0x%02x)",
- __func__, mgmt_errstr(status), status);
- goto failed;
- }
-
- if (length < sizeof(*rp)) {
- error("%s: Wrong size of read index list response", __func__);
- goto failed;
- }
-
- num = btohs(rp->num_controllers);
-
- DBG("Number of controllers: %u", num);
-
- if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
- error("%s: Incorrect pkt size for index list rsp", __func__);
- goto failed;
- }
-
- if (adapter_index != MGMT_INDEX_NONE)
- return;
-
- for (i = 0; i < num; i++) {
- uint16_t index = btohs(rp->index[i]);
-
- if (opt_index != MGMT_INDEX_NONE && opt_index != index)
- continue;
-
- adapter_index = index;
- bt_adapter_init(adapter_index, mgmt_if, adapter_ready);
- return;
- }
-
- if (adapter_index != MGMT_INDEX_NONE)
- return;
-
- adapter_timeout = g_timeout_add_seconds(STARTUP_GRACE_SECONDS,
- adapter_timeout_handler, NULL);
- if (adapter_timeout > 0)
- return;
-
- error("%s: Failed init timeout", __func__);
-
-failed:
- g_main_loop_quit(event_loop);
-}
-
-static void read_commands_complete(uint8_t status, uint16_t length,
- const void *param, void *user_data)
-{
- const struct mgmt_rp_read_commands *rp = param;
-
- DBG("");
-
- if (status) {
- error("Failed to read supported commands: %s (0x%02x)",
- mgmt_errstr(status), status);
- return;
- }
-
- if (length < sizeof(*rp)) {
- error("Wrong size response");
- return;
- }
-}
-
-static void read_version_complete(uint8_t status, uint16_t length,
- const void *param, void *user_data)
-{
- const struct mgmt_rp_read_version *rp = param;
- uint8_t mgmt_version, mgmt_revision;
-
- DBG("");
-
- if (status) {
- error("Failed to read version information: %s (0x%02x)",
- mgmt_errstr(status), status);
- goto failed;
- }
-
- if (length < sizeof(*rp)) {
- error("Wrong size response");
- goto failed;
- }
-
- mgmt_version = rp->version;
- mgmt_revision = btohs(rp->revision);
-
- info("Bluetooth management interface %u.%u initialized",
- mgmt_version, mgmt_revision);
-
- if (MGMT_VERSION(mgmt_version, mgmt_revision) < MGMT_VERSION(1, 3)) {
- error("Version 1.3 or later of management interface required");
- goto failed;
- }
-
- mgmt_send(mgmt_if, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE, 0, NULL,
- read_commands_complete, NULL, NULL);
-
- mgmt_register(mgmt_if, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
- mgmt_index_added_event, NULL, NULL);
- mgmt_register(mgmt_if, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
- mgmt_index_removed_event, NULL, NULL);
-
- if (mgmt_send(mgmt_if, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0,
- NULL, read_index_list_complete, NULL, NULL) > 0)
- return;
-
- error("Failed to read controller index list");
-
-failed:
- g_main_loop_quit(event_loop);
-}
-
-static bool init_mgmt_interface(void)
-{
- mgmt_if = mgmt_new_default();
- if (!mgmt_if) {
- error("Failed to access management interface");
- return false;
- }
-
- if (mgmt_send(mgmt_if, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE, 0, NULL,
- read_version_complete, NULL, NULL) == 0) {
- error("Error sending READ_VERSION mgmt command");
- return false;
- }
-
- return true;
-}
-
-static void cleanup_mgmt_interface(void)
-{
- mgmt_unref(mgmt_if);
- mgmt_if = NULL;
-}
-
static void cleanup_hal_connection(void)
{
if (hal_cmd_io) {
@@ -757,7 +550,14 @@ int main(int argc, char *argv[])
if (!set_capabilities())
return EXIT_FAILURE;
- if (!init_mgmt_interface())
+ bluetooth_start_timeout = g_timeout_add_seconds(STARTUP_GRACE_SECONDS,
+ quit_eventloop, NULL);
+ if (bluetooth_start_timeout == 0) {
+ error("Failed to init startup timeout");
+ return EXIT_FAILURE;
+ }
+
+ if (!bt_adapter_start(option_index, adapter_ready))
return EXIT_FAILURE;
/* Use params: mtu = 0, flags = 0 */
@@ -771,7 +571,7 @@ int main(int argc, char *argv[])
cleanup_hal_connection();
stop_sdp_server();
- cleanup_mgmt_interface();
+ bt_adapter_cleanup();
g_main_loop_unref(event_loop);
info("Exit");
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 1/8] android: Make adapter static
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1384300100-8941-1-git-send-email-szymon.janc@tieto.com>
Only one controller is used so there is no need to keep it as allocable
structure. This will also make memory management simpler and more
correct eg. adapter was never free.
Elements not directly related to adapter are kept outside of adapter
structure.
---
android/adapter.c | 307 +++++++++++++++++++++++++++---------------------------
1 file changed, 152 insertions(+), 155 deletions(-)
diff --git a/android/adapter.c b/android/adapter.c
index 9690861..f8bfb36 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -59,26 +59,36 @@
+ (sizeof(struct hal_property))
static int notification_sk = -1;
+
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
-struct bt_adapter {
- uint16_t index;
- struct mgmt *mgmt;
+static bt_adapter_ready adapter_ready = NULL;
- bt_adapter_ready ready;
+static struct mgmt *mgmt_if = NULL;
+
+static struct {
+ uint16_t index;
bdaddr_t bdaddr;
uint32_t dev_class;
char *name;
- uint32_t supported_settings;
uint32_t current_settings;
bool discovering;
uint32_t discoverable_timeout;
+
GSList *uuids;
+} adapter = {
+ .index = MGMT_INDEX_NONE,
+ .dev_class = 0,
+ .name = NULL,
+ .current_settings = 0,
+ .discovering = false,
+ .discoverable_timeout = DEFAULT_DISCOVERABLE_TIMEOUT,
+ .uuids = NULL,
};
struct browse_req {
@@ -95,7 +105,6 @@ static const uint16_t uuid_list[] = {
0
};
-static struct bt_adapter *adapter;
static GSList *found_devices = NULL;
static void adapter_name_changed(const uint8_t *name)
@@ -120,13 +129,13 @@ static void adapter_name_changed(const uint8_t *name)
static void adapter_set_name(const uint8_t *name)
{
- if (!g_strcmp0(adapter->name, (const char *) name))
+ if (!g_strcmp0(adapter.name, (const char *) name))
return;
DBG("%s", name);
- g_free(adapter->name);
- adapter->name = g_strdup((const char *) name);
+ g_free(adapter.name);
+ adapter.name = g_strdup((const char *) name);
adapter_name_changed(name);
}
@@ -150,7 +159,7 @@ static void powered_changed(void)
{
struct hal_ev_adapter_state_changed ev;
- ev.state = (adapter->current_settings & MGMT_SETTING_POWERED) ?
+ ev.state = (adapter.current_settings & MGMT_SETTING_POWERED) ?
HAL_POWER_ON : HAL_POWER_OFF;
DBG("%u", ev.state);
@@ -163,8 +172,8 @@ static uint8_t settings2scan_mode(void)
{
bool connectable, discoverable;
- connectable = adapter->current_settings & MGMT_SETTING_CONNECTABLE;
- discoverable = adapter->current_settings & MGMT_SETTING_DISCOVERABLE;
+ connectable = adapter.current_settings & MGMT_SETTING_CONNECTABLE;
+ discoverable = adapter.current_settings & MGMT_SETTING_DISCOVERABLE;
if (connectable && discoverable)
return HAL_ADAPTER_SCAN_MODE_CONN_DISC;
@@ -206,7 +215,7 @@ static void adapter_class_changed(void)
ev->props[0].type = HAL_PROP_ADAPTER_CLASS;
ev->props[0].len = sizeof(uint32_t);
- memcpy(ev->props->val, &adapter->dev_class, sizeof(uint32_t));
+ memcpy(ev->props->val, &adapter.dev_class, sizeof(uint32_t));
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), buf, -1);
@@ -217,9 +226,9 @@ static void settings_changed(uint32_t settings)
uint32_t changed_mask;
uint32_t scan_mode_mask;
- changed_mask = adapter->current_settings ^ settings;
+ changed_mask = adapter.current_settings ^ settings;
- adapter->current_settings = settings;
+ adapter.current_settings = settings;
DBG("0x%08x", changed_mask);
@@ -234,7 +243,7 @@ static void settings_changed(uint32_t settings)
* Only when powered, the connectable and discoverable
* state changes should be communicated.
*/
- if (adapter->current_settings & MGMT_SETTING_POWERED)
+ if (adapter.current_settings & MGMT_SETTING_POWERED)
if (changed_mask & scan_mode_mask)
scan_mode_changed();
}
@@ -251,10 +260,10 @@ static void new_settings_callback(uint16_t index, uint16_t length,
settings = bt_get_le32(param);
- DBG("settings: 0x%8.8x -> 0x%8.8x", adapter->current_settings,
+ DBG("settings: 0x%8.8x -> 0x%8.8x", adapter.current_settings,
settings);
- if (settings == adapter->current_settings)
+ if (settings == adapter.current_settings)
return;
settings_changed(settings);
@@ -273,12 +282,12 @@ static void mgmt_dev_class_changed_event(uint16_t index, uint16_t length,
dev_class = rp->val[0] | (rp->val[1] << 8) | (rp->val[2] << 16);
- if (dev_class == adapter->dev_class)
+ if (dev_class == adapter.dev_class)
return;
DBG("Class: 0x%06x", dev_class);
- adapter->dev_class = dev_class;
+ adapter.dev_class = dev_class;
adapter_class_changed();
@@ -415,7 +424,7 @@ static void browse_cb(sdp_list_t *recs, int err, gpointer user_data)
/* Search for mandatory uuids */
if (uuid_list[req->search_uuid]) {
sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
- bt_search_service(&adapter->bdaddr, &req->bdaddr, &uuid,
+ bt_search_service(&adapter.bdaddr, &req->bdaddr, &uuid,
browse_cb, user_data, NULL);
return;
}
@@ -447,7 +456,7 @@ static uint8_t browse_remote_sdp(const bdaddr_t *addr)
bacpy(&req->bdaddr, addr);
sdp_uuid16_create(&uuid, uuid_list[req->search_uuid++]);
- if (bt_search_service(&adapter->bdaddr,
+ if (bt_search_service(&adapter.bdaddr,
&req->bdaddr, &uuid, browse_cb, req, NULL) < 0) {
browse_req_free(req);
return false;
@@ -602,17 +611,17 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
return;
}
- DBG("hci%u type %u discovering %u", adapter->index, ev->type,
+ DBG("hci%u type %u discovering %u", index, ev->type,
ev->discovering);
- if (adapter->discovering == !!ev->discovering)
+ if (adapter.discovering == !!ev->discovering)
return;
- adapter->discovering = !!ev->discovering;
+ adapter.discovering = !!ev->discovering;
DBG("new discovering state %u", ev->discovering);
- if (adapter->discovering) {
+ if (adapter.discovering) {
cp.state = HAL_DISCOVERY_STATE_STARTED;
} else {
g_slist_free_full(found_devices, g_free);
@@ -633,8 +642,8 @@ static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type)
bacpy(&cp.addr.bdaddr, addr);
cp.addr.type = addr_type;
- if (mgmt_reply(adapter->mgmt, MGMT_OP_CONFIRM_NAME, adapter->index,
- sizeof(cp), &cp, NULL, NULL, NULL) == 0)
+ if (mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) == 0)
error("Failed to send confirm name request");
}
@@ -880,56 +889,49 @@ static void mgmt_device_unpaired_event(uint16_t index, uint16_t length,
static void register_mgmt_handlers(void)
{
- mgmt_register(adapter->mgmt, MGMT_EV_NEW_SETTINGS, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_NEW_SETTINGS, adapter.index,
new_settings_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_CLASS_OF_DEV_CHANGED,
- adapter->index, mgmt_dev_class_changed_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_CLASS_OF_DEV_CHANGED, adapter.index,
+ mgmt_dev_class_changed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_LOCAL_NAME_CHANGED,
- adapter->index, mgmt_local_name_changed_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_LOCAL_NAME_CHANGED, adapter.index,
+ mgmt_local_name_changed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_NEW_LINK_KEY, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_NEW_LINK_KEY, adapter.index,
new_link_key_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_PIN_CODE_REQUEST, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_PIN_CODE_REQUEST, adapter.index,
pin_code_request_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_USER_CONFIRM_REQUEST,
- adapter->index, user_confirm_request_callback,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_USER_CONFIRM_REQUEST, adapter.index,
+ user_confirm_request_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_USER_PASSKEY_REQUEST,
- adapter->index, user_passkey_request_callback,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_USER_PASSKEY_REQUEST, adapter.index,
+ user_passkey_request_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_PASSKEY_NOTIFY, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_PASSKEY_NOTIFY, adapter.index,
user_passkey_notify_callback, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DISCOVERING, adapter->index,
- mgmt_discovering_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_DISCOVERING, adapter.index,
+ mgmt_discovering_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_FOUND,
- adapter->index, mgmt_device_found_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_FOUND, adapter.index,
+ mgmt_device_found_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_CONNECTED, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_CONNECTED, adapter.index,
mgmt_device_connected_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_DISCONNECTED,
- adapter->index, mgmt_device_disconnected_event,
- NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_DISCONNECTED, adapter.index,
+ mgmt_device_disconnected_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_CONNECT_FAILED, adapter->index,
- mgmt_connect_failed_event, NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_CONNECT_FAILED, adapter.index,
+ mgmt_connect_failed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_AUTH_FAILED, adapter->index,
- mgmt_auth_failed_event, NULL, NULL);
+ mgmt_register(mgmt_if, MGMT_EV_AUTH_FAILED, adapter.index,
+ mgmt_auth_failed_event, NULL, NULL);
- mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_UNPAIRED, adapter->index,
+ mgmt_register(mgmt_if, MGMT_EV_DEVICE_UNPAIRED, adapter.index,
mgmt_device_unpaired_event, NULL, NULL);
}
@@ -940,18 +942,18 @@ static void load_link_keys_complete(uint8_t status, uint16_t length,
if (status) {
error("Failed to load link keys for index %u: %s (0x%02x)",
- adapter->index, mgmt_errstr(status), status);
+ adapter.index, mgmt_errstr(status), status);
err = -EIO;
goto failed;
}
DBG("status %u", status);
- adapter->ready(0);
+ adapter_ready(0);
return;
failed:
- adapter->ready(err);
+ adapter_ready(err);
}
static void load_link_keys(GSList *keys)
@@ -979,14 +981,14 @@ static void load_link_keys(GSList *keys)
for (key = cp->keys; keys != NULL; keys = g_slist_next(keys), key++)
memcpy(key, keys->data, sizeof(*key));
- id = mgmt_send(adapter->mgmt, MGMT_OP_LOAD_LINK_KEYS, adapter->index,
+ id = mgmt_send(mgmt_if, MGMT_OP_LOAD_LINK_KEYS, adapter.index,
cp_size, cp, load_link_keys_complete, NULL, NULL);
g_free(cp);
if (id == 0) {
error("Failed to load link keys");
- adapter->ready(-EIO);
+ adapter_ready(-EIO);
}
}
@@ -1004,7 +1006,7 @@ static void uuid16_to_uint128(uint16_t uuid, uint128_t *u128)
static bool get_uuids(void)
{
struct hal_ev_adapter_props_changed *ev;
- GSList *list = adapter->uuids;
+ GSList *list = adapter.uuids;
unsigned int uuid_count = g_slist_length(list);
int len = uuid_count * sizeof(uint128_t);
uint8_t buf[BASELEN_PROP_CHANGED + len];
@@ -1049,7 +1051,7 @@ static void remove_uuid_complete(uint8_t status, uint16_t length,
return;
}
- mgmt_dev_class_changed_event(adapter->index, length, param, NULL);
+ mgmt_dev_class_changed_event(adapter.index, length, param, NULL);
/* send notification only if bluetooth service is registered */
if (notification_sk >= 0)
@@ -1064,9 +1066,8 @@ static void remove_uuid(uint16_t uuid)
uuid16_to_uint128(uuid, &uint128);
htob128(&uint128, (uint128_t *) cp.uuid);
- mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_UUID,
- adapter->index, sizeof(cp), &cp,
- remove_uuid_complete, NULL, NULL);
+ mgmt_send(mgmt_if, MGMT_OP_REMOVE_UUID, adapter.index, sizeof(cp), &cp,
+ remove_uuid_complete, NULL, NULL);
}
static void add_uuid_complete(uint8_t status, uint16_t length,
@@ -1078,7 +1079,7 @@ static void add_uuid_complete(uint8_t status, uint16_t length,
return;
}
- mgmt_dev_class_changed_event(adapter->index, length, param, NULL);
+ mgmt_dev_class_changed_event(adapter.index, length, param, NULL);
/* send notification only if bluetooth service is registered */
if (notification_sk >= 0)
@@ -1095,9 +1096,8 @@ static void add_uuid(uint8_t svc_hint, uint16_t uuid)
htob128(&uint128, (uint128_t *) cp.uuid);
cp.svc_hint = svc_hint;
- mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
- adapter->index, sizeof(cp), &cp,
- add_uuid_complete, NULL, NULL);
+ mgmt_send(mgmt_if, MGMT_OP_ADD_UUID, adapter.index, sizeof(cp), &cp,
+ add_uuid_complete, NULL, NULL);
}
int bt_adapter_add_record(sdp_record_t *rec, uint8_t svc_hint)
@@ -1112,17 +1112,16 @@ int bt_adapter_add_record(sdp_record_t *rec, uint8_t svc_hint)
uuid = rec->svclass.value.uuid16;
- if (g_slist_find(adapter->uuids, GUINT_TO_POINTER(uuid))) {
+ if (g_slist_find(adapter.uuids, GUINT_TO_POINTER(uuid))) {
DBG("UUID 0x%x already added", uuid);
return -EALREADY;
}
- adapter->uuids = g_slist_prepend(adapter->uuids,
- GUINT_TO_POINTER(uuid));
+ adapter.uuids = g_slist_prepend(adapter.uuids, GUINT_TO_POINTER(uuid));
add_uuid(svc_hint, uuid);
- return add_record_to_server(&adapter->bdaddr, rec);
+ return add_record_to_server(&adapter.bdaddr, rec);
}
void bt_adapter_remove_record(uint32_t handle)
@@ -1137,11 +1136,11 @@ void bt_adapter_remove_record(uint32_t handle)
uuid = rec->svclass.value.uuid16;
- uuid_found = g_slist_find(adapter->uuids, GUINT_TO_POINTER(uuid));
+ uuid_found = g_slist_find(adapter.uuids, GUINT_TO_POINTER(uuid));
if (uuid_found) {
remove_uuid(uuid);
- adapter->uuids = g_slist_remove(adapter->uuids,
+ adapter.uuids = g_slist_remove(adapter.uuids,
uuid_found->data);
}
@@ -1162,7 +1161,7 @@ static void set_mode_complete(uint8_t status, uint16_t length,
* required in both cases. So it is safe to just call the
* event handling functions here.
*/
- new_settings_callback(adapter->index, length, param, NULL);
+ new_settings_callback(adapter.index, length, param, NULL);
}
static bool set_mode(uint16_t opcode, uint8_t mode)
@@ -1174,7 +1173,7 @@ static bool set_mode(uint16_t opcode, uint8_t mode)
DBG("opcode=0x%x mode=0x%x", opcode, mode);
- if (mgmt_send(adapter->mgmt, opcode, adapter->index, sizeof(cp), &cp,
+ if (mgmt_send(mgmt_if, opcode, adapter.index, sizeof(cp), &cp,
set_mode_complete, NULL, NULL) > 0)
return true;
@@ -1190,9 +1189,8 @@ static void set_io_capability(void)
memset(&cp, 0, sizeof(cp));
cp.io_capability = DEFAULT_IO_CAPABILITY;
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_IO_CAPABILITY,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_IO_CAPABILITY, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) == 0)
error("Failed to set IO capability");
}
@@ -1213,9 +1211,8 @@ static void set_device_id(void)
cp.product = htobs(DEVICE_ID_PRODUCT);
cp.version = htobs(version);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_ID,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_DEVICE_ID, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) == 0)
error("Failed to set device id");
register_device_id(DEVICE_ID_SOURCE, DEVICE_ID_VENDOR,
@@ -1245,9 +1242,9 @@ static uint8_t set_adapter_name(uint8_t *name, uint16_t len)
memset(&cp, 0, sizeof(cp));
memcpy(cp.name, name, len);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_LOCAL_NAME, adapter->index,
- sizeof(cp), &cp, set_adapter_name_complete, NULL,
- NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_LOCAL_NAME, adapter.index,
+ sizeof(cp), &cp, set_adapter_name_complete,
+ NULL, NULL) > 0)
return HAL_STATUS_SUCCESS;
error("Failed to set name");
@@ -1262,7 +1259,7 @@ static uint8_t set_discoverable_timeout(uint8_t *timeout)
* Just need to store this value here */
/* TODO: This should be in some storage */
- memcpy(&adapter->discoverable_timeout, timeout, sizeof(uint32_t));
+ memcpy(&adapter.discoverable_timeout, timeout, sizeof(uint32_t));
return HAL_STATUS_SUCCESS;
}
@@ -1273,7 +1270,7 @@ static void clear_uuids(void)
memset(&cp, 0, sizeof(cp));
- mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_UUID, adapter->index,
+ mgmt_send(mgmt_if, MGMT_OP_REMOVE_UUID, adapter.index,
sizeof(cp), &cp, NULL, NULL, NULL);
}
@@ -1281,14 +1278,14 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
void *user_data)
{
const struct mgmt_rp_read_info *rp = param;
- uint32_t missing_settings;
+ uint32_t missing_settings, supported_settings;
int err;
DBG("");
if (status) {
error("Failed to read info for index %u: %s (0x%02x)",
- adapter->index, mgmt_errstr(status), status);
+ adapter.index, mgmt_errstr(status), status);
err = -EIO;
goto failed;
}
@@ -1306,13 +1303,15 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
}
/* Store adapter information */
- bacpy(&adapter->bdaddr, &rp->bdaddr);
- adapter->dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
+ bacpy(&adapter.bdaddr, &rp->bdaddr);
+ adapter.dev_class = rp->dev_class[0] | (rp->dev_class[1] << 8) |
(rp->dev_class[2] << 16);
- adapter->name = g_strdup((const char *) rp->name);
+ adapter.name = g_strdup((const char *) rp->name);
- adapter->supported_settings = btohs(rp->supported_settings);
- adapter->current_settings = btohs(rp->current_settings);
+ supported_settings = btohs(rp->supported_settings);
+ adapter.current_settings = btohs(rp->current_settings);
+
+ /* TODO: Read discoverable timeout from storage here */
/* TODO: Register all event notification handlers */
register_mgmt_handlers();
@@ -1324,8 +1323,7 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
set_io_capability();
set_device_id();
- missing_settings = adapter->current_settings ^
- adapter->supported_settings;
+ missing_settings = adapter.current_settings ^ supported_settings;
if (missing_settings & MGMT_SETTING_SSP)
set_mode(MGMT_OP_SET_SSP, 0x01);
@@ -1336,26 +1334,29 @@ static void read_info_complete(uint8_t status, uint16_t length, const void *para
return;
failed:
- adapter->ready(err);
+ adapter_ready(err);
}
void bt_adapter_init(uint16_t index, struct mgmt *mgmt, bt_adapter_ready cb)
{
- adapter = g_new0(struct bt_adapter, 1);
+ mgmt_if = mgmt_ref(mgmt);
+
+ adapter.index = index;
+
+ adapter_ready = cb;
- adapter->mgmt = mgmt_ref(mgmt);
- adapter->index = index;
- adapter->discovering = false;
- adapter->ready = cb;
- /* TODO: Read it from some storage */
- adapter->discoverable_timeout = DEFAULT_DISCOVERABLE_TIMEOUT;
+ /* TODO: Read discoverable timeout from some storage */
if (mgmt_send(mgmt, MGMT_OP_READ_INFO, index, 0, NULL,
read_info_complete, NULL, NULL) > 0)
return;
- mgmt_unref(adapter->mgmt);
- adapter->ready(-EIO);
+ mgmt_unref(mgmt_if);
+ mgmt_if = NULL;
+
+ adapter.index = MGMT_INDEX_NONE;
+
+ adapter_ready(-EIO);
}
static bool set_discoverable(uint8_t mode, uint16_t timeout)
@@ -1368,9 +1369,8 @@ static bool set_discoverable(uint8_t mode, uint16_t timeout)
DBG("mode %u timeout %u", mode, timeout);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DISCOVERABLE,
- adapter->index, sizeof(cp), &cp,
- set_mode_complete, adapter, NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_SET_DISCOVERABLE, adapter.index,
+ sizeof(cp), &cp, set_mode_complete, NULL, NULL) > 0)
return true;
error("Failed to set mode discoverable");
@@ -1388,7 +1388,7 @@ static void get_address(void)
ev->props[0].type = HAL_PROP_ADAPTER_ADDR;
ev->props[0].len = sizeof(bdaddr_t);
- bdaddr2android(&adapter->bdaddr, ev->props[0].val);
+ bdaddr2android(&adapter.bdaddr, ev->props[0].val);
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), buf, -1);
@@ -1396,10 +1396,10 @@ static void get_address(void)
static bool get_name(void)
{
- if (!adapter->name)
+ if (!adapter.name)
return false;
- adapter_name_changed((uint8_t *) adapter->name);
+ adapter_name_changed((uint8_t *) adapter.name);
return true;
}
@@ -1463,7 +1463,7 @@ static bool get_discoverable_timeout(void)
ev->props[0].type = HAL_PROP_ADAPTER_DISC_TIMEOUT;
ev->props[0].len = sizeof(uint32_t);
- memcpy(&ev->props[0].val, &adapter->discoverable_timeout,
+ memcpy(&ev->props[0].val, &adapter.discoverable_timeout,
sizeof(uint32_t));
ipc_send(notification_sk, HAL_SERVICE_ID_BLUETOOTH,
@@ -1519,15 +1519,15 @@ static bool start_discovery(void)
struct mgmt_cp_start_discovery cp;
uint8_t type = 1 << BDADDR_BREDR;
- if (adapter->current_settings & type)
+ if (adapter.current_settings & type)
cp.type = type;
else
cp.type = 0;
DBG("type=0x%x", type);
- if (mgmt_send(adapter->mgmt, MGMT_OP_START_DISCOVERY, adapter->index,
- sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_START_DISCOVERY, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
return true;
error("Failed to start discovery");
@@ -1539,15 +1539,15 @@ static bool stop_discovery(void)
struct mgmt_cp_stop_discovery cp;
uint8_t type = 1 << BDADDR_BREDR;
- if (adapter->current_settings & type)
+ if (adapter.current_settings & type)
cp.type = type;
else
cp.type = 0;
DBG("type=0x%x", type);
- if (mgmt_send(adapter->mgmt, MGMT_OP_STOP_DISCOVERY, adapter->index,
- sizeof(cp), &cp, NULL, NULL, NULL) > 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_STOP_DISCOVERY, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0)
return true;
error("Failed to start discovery");
@@ -1559,8 +1559,8 @@ static uint8_t set_scan_mode(void *buf, uint16_t len)
uint8_t *mode = buf;
bool conn, disc, cur_conn, cur_disc;
- cur_conn = adapter->current_settings & MGMT_SETTING_CONNECTABLE;
- cur_disc = adapter->current_settings & MGMT_SETTING_DISCOVERABLE;
+ cur_conn = adapter.current_settings & MGMT_SETTING_CONNECTABLE;
+ cur_disc = adapter.current_settings & MGMT_SETTING_DISCOVERABLE;
DBG("connectable %u discoverable %d mode %u", cur_conn, cur_disc,
*mode);
@@ -1674,9 +1674,8 @@ static bool create_bond(void *buf, uint16_t len)
cp.addr.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.addr.bdaddr);
- if (mgmt_send(adapter->mgmt, MGMT_OP_PAIR_DEVICE, adapter->index,
- sizeof(cp), &cp, pair_device_complete, NULL,
- NULL) == 0)
+ if (mgmt_send(mgmt_if, MGMT_OP_PAIR_DEVICE, adapter.index, sizeof(cp),
+ &cp, pair_device_complete, NULL, NULL) == 0)
return false;
send_bond_state_change(&cp.addr.bdaddr, HAL_STATUS_SUCCESS,
@@ -1693,9 +1692,8 @@ static bool cancel_bond(void *buf, uint16_t len)
cp.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.bdaddr);
- return mgmt_reply(adapter->mgmt, MGMT_OP_CANCEL_PAIR_DEVICE,
- adapter->index, sizeof(cp), &cp, NULL, NULL,
- NULL) > 0;
+ return mgmt_reply(mgmt_if, MGMT_OP_CANCEL_PAIR_DEVICE, adapter.index,
+ sizeof(cp), &cp, NULL, NULL, NULL) > 0;
}
static void unpair_device_complete(uint8_t status, uint16_t length,
@@ -1721,9 +1719,9 @@ static bool remove_bond(void *buf, uint16_t len)
cp.addr.type = BDADDR_BREDR;
android2bdaddr(cmd->bdaddr, &cp.addr.bdaddr);
- return mgmt_send(adapter->mgmt, MGMT_OP_UNPAIR_DEVICE,
- adapter->index, sizeof(cp), &cp,
- unpair_device_complete, NULL, NULL) > 0;
+ return mgmt_send(mgmt_if, MGMT_OP_UNPAIR_DEVICE, adapter.index,
+ sizeof(cp), &cp, unpair_device_complete,
+ NULL, NULL) > 0;
}
static uint8_t pin_reply(void *buf, uint16_t len)
@@ -1750,9 +1748,8 @@ static uint8_t pin_reply(void *buf, uint16_t len)
rp.pin_len = cmd->pin_len;
memcpy(rp.pin_code, cmd->pin_code, rp.pin_len);
- if (mgmt_reply(adapter->mgmt, MGMT_OP_PIN_CODE_REPLY,
- adapter->index, sizeof(rp), &rp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_reply(mgmt_if, MGMT_OP_PIN_CODE_REPLY, adapter.index,
+ sizeof(rp), &rp, NULL, NULL, NULL) == 0)
return HAL_STATUS_FAILED;
} else {
struct mgmt_cp_pin_code_neg_reply rp;
@@ -1760,9 +1757,9 @@ static uint8_t pin_reply(void *buf, uint16_t len)
bacpy(&rp.addr.bdaddr, &bdaddr);
rp.addr.type = BDADDR_BREDR;
- if (mgmt_reply(adapter->mgmt, MGMT_OP_PIN_CODE_NEG_REPLY,
- adapter->index, sizeof(rp), &rp,
- NULL, NULL, NULL) == 0)
+ if (mgmt_reply(mgmt_if, MGMT_OP_PIN_CODE_NEG_REPLY,
+ adapter.index, sizeof(rp), &rp,
+ NULL, NULL, NULL) == 0)
return HAL_STATUS_FAILED;
}
@@ -1782,7 +1779,7 @@ static uint8_t user_confirm_reply(const bdaddr_t *bdaddr, bool accept)
bacpy(&cp.bdaddr, bdaddr);
cp.type = BDADDR_BREDR;
- if (mgmt_reply(adapter->mgmt, opcode, adapter->index, sizeof(cp), &cp,
+ if (mgmt_reply(mgmt_if, opcode, adapter.index, sizeof(cp), &cp,
NULL, NULL, NULL) > 0)
return HAL_STATUS_SUCCESS;
@@ -1802,9 +1799,9 @@ static uint8_t user_passkey_reply(const bdaddr_t *bdaddr, bool accept,
cp.addr.type = BDADDR_BREDR;
cp.passkey = htobl(passkey);
- id = mgmt_reply(adapter->mgmt, MGMT_OP_USER_PASSKEY_REPLY,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL);
+ id = mgmt_reply(mgmt_if, MGMT_OP_USER_PASSKEY_REPLY,
+ adapter.index, sizeof(cp), &cp,
+ NULL, NULL, NULL);
} else {
struct mgmt_cp_user_passkey_neg_reply cp;
@@ -1812,9 +1809,9 @@ static uint8_t user_passkey_reply(const bdaddr_t *bdaddr, bool accept,
bacpy(&cp.addr.bdaddr, bdaddr);
cp.addr.type = BDADDR_BREDR;
- id = mgmt_reply(adapter->mgmt, MGMT_OP_USER_PASSKEY_NEG_REPLY,
- adapter->index, sizeof(cp), &cp,
- NULL, NULL, NULL);
+ id = mgmt_reply(mgmt_if, MGMT_OP_USER_PASSKEY_NEG_REPLY,
+ adapter.index, sizeof(cp), &cp,
+ NULL, NULL, NULL);
}
if (id == 0)
@@ -1877,7 +1874,7 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
* enabling adapter */
get_properties();
- if (adapter->current_settings & MGMT_SETTING_POWERED) {
+ if (adapter.current_settings & MGMT_SETTING_POWERED) {
status = HAL_STATUS_DONE;
goto error;
}
@@ -1887,7 +1884,7 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
case HAL_OP_DISABLE:
- if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
status = HAL_STATUS_DONE;
goto error;
}
@@ -1938,12 +1935,12 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
goto error;
break;
case HAL_OP_START_DISCOVERY:
- if (adapter->discovering) {
+ if (adapter.discovering) {
status = HAL_STATUS_DONE;
goto error;
}
- if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
status = HAL_STATUS_NOT_READY;
goto error;
}
@@ -1953,12 +1950,12 @@ void bt_adapter_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
break;
case HAL_OP_CANCEL_DISCOVERY:
- if (!adapter->discovering) {
+ if (!adapter.discovering) {
status = HAL_STATUS_DONE;
goto error;
}
- if (!(adapter->current_settings & MGMT_SETTING_POWERED)) {
+ if (!(adapter.current_settings & MGMT_SETTING_POWERED)) {
status = HAL_STATUS_NOT_READY;
goto error;
}
@@ -1988,7 +1985,7 @@ error:
const bdaddr_t *bt_adapter_get_address(void)
{
- return &adapter->bdaddr;
+ return &adapter.bdaddr;
}
bool bt_adapter_register(int sk)
--
1.8.4.3
^ permalink raw reply related
* [PATCH v2 0/8] android: Some adapter and mgmt handling code cleanup
From: Szymon Janc @ 2013-11-12 23:48 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Hi,
v2:
- addressed Johan comments about using static adapter structure instead of
bunch of static adapter_* variables
- Added a patch for utilizing mgmt library for passing adapter ready callback
(patch 3)
v1:
This patchset moves mgmt initalization handling from main.c to adapter.c so
now all mgmt handling is done from adaper.c. Adapter.c is also renamed to
bluetooth.c to match service name implemented by it.
Startup and shutdown timeouts are still handled in main.c (mostly due to
both resulting in mainloop shutdown so extra callback are avoided).
IO handling and commands dispatch is still done in main.c
Comments are welcome.
--
BR
Szymon Janc
Szymon Janc (8):
android: Make adapter static
android: Move adapter initialization to adapter.c
android: Don't use static pointer for storing adapter_ready callback
android/hidhost: Use adapter address provided on register
android: Report adapter address in adapter_ready callback
android: Remove not needed bt_adapter_get_address function
android: Rename adapter.c to bluetooth.c
android: Rename bluetooth service functions to match service name
android/Android.mk | 2 +-
android/Makefile.am | 4 +-
android/adapter.c | 2008 -----------------------------------------------
android/adapter.h | 37 -
android/bluetooth.c | 2177 +++++++++++++++++++++++++++++++++++++++++++++++++++
android/bluetooth.h | 38 +
android/hidhost.c | 21 +-
android/main.c | 314 ++------
8 files changed, 2287 insertions(+), 2314 deletions(-)
delete mode 100644 android/adapter.c
delete mode 100644 android/adapter.h
create mode 100644 android/bluetooth.c
create mode 100644 android/bluetooth.h
--
1.8.4.3
^ permalink raw reply
* Re: shutdown(3) and bluetooth.
From: Marcel Holtmann @ 2013-11-12 23:37 UTC (permalink / raw)
To: Dave Jones; +Cc: netdev, linux-bluetooth@vger.kernel.org development
In-Reply-To: <20131112224819.GE9057@redhat.com>
Hi Dave,
>>> Here's the info I found in the logs, it looks like this was the only bluetooth socket.
>>>
>>> fd[195] = domain:31 (PF_BLUETOOTH) type:0x5 protocol:2
>>> Setsockopt(1 d 2134000 8) on fd 195
>>
>> this is a bit confusing. Protocol 2 is actually SCO, but the stack trace shows RFCOMM.
>
> Sorry, mixed up two separate runs. In the log above, the stack trace is actually..
>
> [<ffffffffa0492dca>] bt_sock_wait_state+0xda/0x240 [bluetooth]
> [<ffffffffa04c86d8>] sco_sock_release+0xb8/0xf0 [bluetooth]
> [<ffffffff815cb1ff>] sock_release+0x1f/0x90
> [<ffffffff815cb282>] sock_close+0x12/0x20
>
>
>>> ./trinity -P PF_BLUETOOTH -l off -c setsockopt
>>>
>>> let it run a few seconds, and then ctrl-c. The main process will never exit.
>>>
>>> 5814 pts/6 Ss 0:00 | \_ bash
>>> 5876 pts/6 S+ 0:00 | | \_ ./trinity -P PF_BLUETOOTH -l off -c setsockopt
>>> 5877 pts/6 Z+ 0:00 | | \_ [trinity] <defunct>
>>> 5878 pts/6 S+ 0:01 | | \_ [trinity-main]
>>>
>>> $ sudo cat /proc/5878/stack
>>> [<ffffffffa04397a2>] bt_sock_wait_state+0xc2/0x190 [bluetooth]
>>> [<ffffffffa0847a75>] rfcomm_sock_shutdown+0x85/0xb0 [rfcomm]
>>> [<ffffffffa0847ad9>] rfcomm_sock_release+0x39/0xb0 [rfcomm]
>
> So it seems it affects both SCO and RFCOMM.
>
>> What kernel did you run this against? It is a shot in the dark, but can you try linux-next quickly.
>> There was a socket related fix for the socket options where we confused RFCOMM vs L2CAP struct sock.
>
> first noticed it on Linus' latest HEAD, and then reproduced it on 3.11.6
> I'll look at linux-next tomorrow.
I looked through the code and only call bt_sock_wait_state when SOCK_LINGER and sk_lingertime is set. In that case we actually block until the socket state changes to BT_CLOSED.
The only way I see this could happen is if you have a huge linger timeout and confused the socket state before. What is actually the list of system calls that you are throwing at this socket.
Regards
Marcel
^ permalink raw reply
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