* [PATCH 5/5] device: Retrieve device pnp ids from storage
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>
When device pnp ids are updated, save them and emit property
changed signals.
---
src/device.c | 51 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 34 insertions(+), 17 deletions(-)
diff --git a/src/device.c b/src/device.c
index d4a553d..4559674 100644
--- a/src/device.c
+++ b/src/device.c
@@ -236,6 +236,17 @@ static gboolean store_device_info_cb(gpointer user_data)
g_key_file_set_boolean(key_file, "General", "Blocked",
device->blocked);
+ if (device->vendor_src) {
+ g_key_file_set_integer(key_file, "DeviceID", "Source",
+ device->vendor_src);
+ g_key_file_set_integer(key_file, "DeviceID", "Vendor",
+ device->vendor);
+ g_key_file_set_integer(key_file, "DeviceID", "Product",
+ device->product);
+ g_key_file_set_integer(key_file, "DeviceID", "Version",
+ device->version);
+ }
+
ba2str(adapter_get_address(device->adapter), adapter_addr);
ba2str(&device->bdaddr, device_addr);
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
@@ -1766,6 +1777,7 @@ static void load_info(struct btd_device *device, const gchar *local,
char *str;
gboolean store_needed = FALSE;
gboolean blocked;
+ int source, vendor, product, version;
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
filename[PATH_MAX] = '\0';
@@ -1811,6 +1823,24 @@ static void load_info(struct btd_device *device, const gchar *local,
if (blocked)
device_block(device, FALSE);
+ /* Load device id */
+ source = g_key_file_get_integer(key_file, "DeviceID", "Source", NULL);
+ if (source) {
+ device_set_vendor_src(device, source);
+
+ vendor = g_key_file_get_integer(key_file, "DeviceID",
+ "Vendor", NULL);
+ device_set_vendor(device, vendor);
+
+ product = g_key_file_get_integer(key_file, "DeviceID",
+ "Product", NULL);
+ device_set_product(device, product);
+
+ version = g_key_file_get_integer(key_file, "DeviceID",
+ "Version", NULL);
+ device_set_version(device, version);
+ }
+
if (store_needed)
store_device_info(device);
@@ -1825,7 +1855,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
const gchar *adapter_path = adapter_get_path(adapter);
const bdaddr_t *src;
char srcaddr[18];
- uint16_t vendor, product, version;
device = g_try_malloc0(sizeof(struct btd_device));
if (device == NULL)
@@ -1867,13 +1896,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
device_set_bonded(device, TRUE);
}
- if (read_device_id(srcaddr, address, bdaddr_type, NULL, &vendor,
- &product, &version) == 0) {
- device_set_vendor(device, vendor);
- device_set_product(device, product);
- device_set_version(device, version);
- }
-
return btd_device_ref(device);
}
@@ -2320,22 +2342,15 @@ static void update_bredr_services(struct browse_req *req, sdp_list_t *recs)
pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
vendor = pdlist ? pdlist->val.uint16 : 0x0000;
- device_set_vendor(device, vendor);
-
pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
product = pdlist ? pdlist->val.uint16 : 0x0000;
- device_set_product(device, product);
-
pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
version = pdlist ? pdlist->val.uint16 : 0x0000;
- device_set_version(device, version);
-
if (source || vendor || product || version)
- store_device_id(srcaddr, dstaddr,
- device->bdaddr_type, source,
- vendor, product, version);
+ device_set_pnpid(device, source, vendor,
+ product, version);
}
/* Check for duplicates */
@@ -4094,4 +4109,6 @@ void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
device_set_vendor_src(device, vendor_id_src);
device_set_product(device, product_id);
device_set_version(device, product_ver);
+
+ store_device_info(device);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/5] adapter: Convert storage did file
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>
---
src/adapter.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index 3dafacb..0d1dfea 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2548,6 +2548,45 @@ static void convert_blocked_entry(GKeyFile *key_file, void *value)
g_key_file_set_boolean(key_file, "General", "Blocked", TRUE);
}
+static void convert_did_entry(GKeyFile *key_file, void *value)
+{
+ char *vendor_str, *product_str, *version_str;
+ uint16_t val;
+
+ vendor_str = strchr(value, ' ');
+ if (!vendor_str)
+ return;
+
+ *(vendor_str++) = 0;
+
+ if (g_str_equal(value, "FFFF"))
+ return;
+
+ product_str = strchr(vendor_str, ' ');
+ if (!product_str)
+ return;
+
+ *(product_str++) = 0;
+
+ version_str = strchr(product_str, ' ');
+ if (!version_str)
+ return;
+
+ *(version_str++) = 0;
+
+ val = (uint16_t) strtol(value, NULL, 16);
+ g_key_file_set_integer(key_file, "DeviceID", "Source", val);
+
+ val = (uint16_t) strtol(vendor_str, NULL, 16);
+ g_key_file_set_integer(key_file, "DeviceID", "Vendor", val);
+
+ val = (uint16_t) strtol(product_str, NULL, 16);
+ g_key_file_set_integer(key_file, "DeviceID", "Product", val);
+
+ val = (uint16_t) strtol(version_str, NULL, 16);
+ g_key_file_set_integer(key_file, "DeviceID", "Version", val);
+}
+
static void convert_entry(char *key, char *value, void *user_data)
{
struct device_converter *converter = user_data;
@@ -2633,6 +2672,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
/* Convert blocked */
convert_file("blocked", address, convert_blocked_entry);
+
+ /* Convert device ids */
+ convert_file("did", address, convert_did_entry);
}
static void convert_config(struct btd_adapter *adapter, const char *filename,
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/5] device: Retrieve device blocked from storage
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>
---
src/device.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/device.c b/src/device.c
index 915b0f8..d4a553d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -233,6 +233,9 @@ static gboolean store_device_info_cb(gpointer user_data)
g_key_file_set_boolean(key_file, "General", "Trusted",
device->trusted);
+ g_key_file_set_boolean(key_file, "General", "Blocked",
+ device->blocked);
+
ba2str(adapter_get_address(device->adapter), adapter_addr);
ba2str(&device->bdaddr, device_addr);
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
@@ -920,10 +923,7 @@ int device_block(struct btd_device *device, gboolean update_only)
device->blocked = TRUE;
- err = write_blocked(adapter_get_address(device->adapter),
- &device->bdaddr, device->bdaddr_type, TRUE);
- if (err < 0)
- error("write_blocked(): %s (%d)", strerror(-err), -err);
+ store_device_info(device);
device_set_temporary(device, FALSE);
@@ -950,10 +950,7 @@ int device_unblock(struct btd_device *device, gboolean silent,
device->blocked = FALSE;
- err = write_blocked(adapter_get_address(device->adapter),
- &device->bdaddr, device->bdaddr_type, FALSE);
- if (err < 0)
- error("write_blocked(): %s (%d)", strerror(-err), -err);
+ store_device_info(device);
if (!silent) {
g_dbus_emit_property_changed(btd_get_dbus_connection(),
@@ -1768,6 +1765,7 @@ static void load_info(struct btd_device *device, const gchar *local,
GKeyFile *key_file;
char *str;
gboolean store_needed = FALSE;
+ gboolean blocked;
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", local, peer);
filename[PATH_MAX] = '\0';
@@ -1808,6 +1806,11 @@ static void load_info(struct btd_device *device, const gchar *local,
device->trusted = g_key_file_get_boolean(key_file, "General",
"Trusted", NULL);
+ /* Load device blocked */
+ blocked = g_key_file_get_boolean(key_file, "General", "Blocked", NULL);
+ if (blocked)
+ device_block(device, FALSE);
+
if (store_needed)
store_device_info(device);
@@ -1852,9 +1855,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,
load_info(device, srcaddr, address);
- if (read_blocked(src, &device->bdaddr, device->bdaddr_type))
- device_block(device, FALSE);
-
if (read_link_key(src, &device->bdaddr, device->bdaddr_type, NULL,
NULL) == 0) {
device_set_paired(device, TRUE);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/5] adapter: Convert storage device blocked
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353505791-21134-1-git-send-email-frederic.danis@linux.intel.com>
An entry exists in blocked file only when a device is blocked.
So, we do not need to check entry value and set device (entry key) as
blocked.
---
src/adapter.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index 0f6a078..3dafacb 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2543,6 +2543,11 @@ static void convert_classes_entry(GKeyFile *key_file, void *value)
g_key_file_set_string(key_file, "General", "Class", value);
}
+static void convert_blocked_entry(GKeyFile *key_file, void *value)
+{
+ g_key_file_set_boolean(key_file, "General", "Blocked", TRUE);
+}
+
static void convert_entry(char *key, char *value, void *user_data)
{
struct device_converter *converter = user_data;
@@ -2625,6 +2630,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
/* Convert classes */
convert_file("classes", address, convert_classes_entry);
+
+ /* Convert blocked */
+ convert_file("blocked", address, convert_blocked_entry);
}
static void convert_config(struct btd_adapter *adapter, const char *filename,
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/5] doc: Update settings-storage.txt
From: Frédéric Danis @ 2012-11-21 13:49 UTC (permalink / raw)
To: linux-bluetooth
Remote features are not available from user space,
so replace Features entry by SupportedTechnologies.
Device blocked should be saved in device info file.
---
doc/settings-storage.txt | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index 1174d44..3fdcb03 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -139,13 +139,16 @@ Long term key) related to a remote device.
Class String Device class in hexadecimal,
i.e. 0x000000
- Features String Bluetooth device features in
- hexadecimal, i.e. 0x0000000000000000
+ SupportedTechnologies List of List of technologies supported by
+ strings device, separated by ";"
+ Technologies can be BR/EDR or LE
AddressType String An address can be "static" or "public"
Trusted Boolean True if the remote device is trusted
+ Blocked Boolean True if the remote device is blocked
+
Profiles List of List of profiles advertised by remote,
strings in 128-bits UUID format, separated by
";"
--
1.7.9.5
^ permalink raw reply related
* [PATCH] Bluetooth: Provide definitions for CSA2 audio commands
From: Michael Knudsen @ 2012-11-21 13:22 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michael Knudsen
---
lib/hci.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lib/hci.c b/lib/hci.c
index 66b2d5f..fd27f1a 100644
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -590,6 +590,15 @@ static hci_map commands_map[] = {
{ "LE Test End", 230 },
{ "Reserved", 231 },
+ { "Reserved", 232 },
+ { "Reserved", 233 },
+ { "Reserved", 234 },
+ { "Enhanced Setup Synchronous Connection", 235 },
+ { "Enhanced Accept Synchronous Connection Request", 236 },
+ { "Read Local Supported Codecs", 237 },
+ { "Reserved", 238 },
+ { "Reserved", 239 },
+
{ NULL }
};
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect
From: Johan Hedberg @ 2012-11-21 12:37 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Wed, Nov 21, 2012, Luiz Augusto von Dentz wrote:
> We should with higher priority first.
> ---
> src/device.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
All patches in this set have been applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH v3] neard: Set device class in device object
From: Johan Hedberg @ 2012-11-21 12:34 UTC (permalink / raw)
To: Frédéric Danis; +Cc: linux-bluetooth
In-Reply-To: <1353499163-18479-1-git-send-email-frederic.danis@linux.intel.com>
Hi Frederic,
On Wed, Nov 21, 2012, Frédéric Danis wrote:
> As soon as we have info related to a new device,
> device object will be created if it does not exist yet.
>
> Change check_device() to use this device object and
> remove call to adapter_remove_device() in it.
> ---
> plugins/neard.c | 32 +++++++++++++++-----------------
> 1 file changed, 15 insertions(+), 17 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH BlueZ 6/6] control: Add profile .connect and .disconnect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Add the connection and disconnection hooks to the avrcp btd_profile.
---
profiles/audio/manager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index dad46a9..714489a 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -318,6 +318,62 @@ static int a2dp_sink_disconnect(struct btd_device *dev,
return 0;
}
+static int avrcp_control_connect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ const gchar *path = device_get_path(dev);
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ DBG("path %s", path);
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = control_connect(audio_dev, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
+static int avrcp_control_disconnect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ const gchar *path = device_get_path(dev);
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ DBG("path %s", path);
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = control_disconnect(audio_dev, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
{
adp->ref++;
@@ -506,6 +562,10 @@ static struct btd_profile avrcp_profile = {
.device_probe = avrcp_probe,
.device_remove = audio_remove,
+ .auto_connect = true,
+ .connect = avrcp_control_connect,
+ .disconnect = avrcp_control_disconnect,
+
.adapter_probe = avrcp_server_probe,
.adapter_remove = avrcp_server_remove,
};
--
1.7.11.7
^ permalink raw reply related
* [PATCH BlueZ 5/6] control: Expose internal connection API
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Separate the D-Bus code from the internal connection handling code,
exposing an internal API in case some internal codepath/plugin is
interested in using it.
---
profiles/audio/control.c | 118 ++++++++++++++++++++++++++++++++++++-----------
profiles/audio/control.h | 4 ++
2 files changed, 96 insertions(+), 26 deletions(-)
diff --git a/profiles/audio/control.c b/profiles/audio/control.c
index 1620128..b2bfb0a 100644
--- a/profiles/audio/control.c
+++ b/profiles/audio/control.c
@@ -61,12 +61,28 @@
static unsigned int avctp_id = 0;
+struct pending_request {
+ audio_device_cb cb;
+ void *data;
+ unsigned int id;
+};
+
struct control {
struct avctp *session;
gboolean target;
- DBusMessage *connect;
+ struct pending_request *connect;
};
+static void pending_request_free(struct audio_device *dev,
+ struct pending_request *pending,
+ int err)
+{
+ if (pending->cb)
+ pending->cb(dev, err, pending->data);
+
+ g_free(pending);
+}
+
static void state_changed(struct audio_device *dev, avctp_state_t old_state,
avctp_state_t new_state, void *user_data)
{
@@ -79,11 +95,7 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
control->session = NULL;
if (control->connect) {
- DBusMessage *reply = btd_error_failed(control->connect,
- "Unable to connect");
-
- g_dbus_send_message(btd_get_dbus_connection(), reply);
- dbus_message_unref(control->connect);
+ pending_request_free(dev, control->connect, -EIO);
control->connect = NULL;
}
@@ -105,9 +117,7 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
break;
case AVCTP_STATE_CONNECTED:
if (control->connect) {
- g_dbus_send_reply(conn, control->connect,
- DBUS_TYPE_INVALID);
- dbus_message_unref(control->connect);
+ pending_request_free(dev, control->connect, 0);
control->connect = NULL;
}
@@ -143,41 +153,97 @@ static DBusMessage *control_is_connected(DBusConnection *conn,
return reply;
}
-static DBusMessage *control_connect(DBusConnection *conn, DBusMessage *msg,
- void *data)
+int control_connect(struct audio_device *dev, audio_device_cb cb, void *data)
{
- struct audio_device *device = data;
- struct control *control = device->control;
+ struct control *control = dev->control;
+ struct pending_request *pending;
if (control->session)
- return btd_error_already_connected(msg);
+ return -EALREADY;
if (!control->target)
- return btd_error_not_supported(msg);
+ return -ENOTSUP;
if (control->connect)
- return btd_error_in_progress(msg);
+ return -EINPROGRESS;
- control->session = avctp_connect(&device->src, &device->dst);
+ control->session = avctp_connect(&dev->src, &dev->dst);
if (!control->session)
- return btd_error_failed(msg, "Unable to connect");
+ return -EIO;
- control->connect = dbus_message_ref(msg);
+ pending = g_new0(struct pending_request, 1);
+ pending->cb = cb;
+ pending->data = data;
+ control->connect = pending;
- return NULL;
+ return 0;
}
-static DBusMessage *control_disconnect(DBusConnection *conn, DBusMessage *msg,
+static void generic_cb(struct audio_device *dev, int err, void *data)
+{
+ DBusMessage *msg = data;
+ DBusMessage *reply;
+
+ if (err < 0) {
+ reply = btd_error_failed(msg, strerror(-err));
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ dbus_message_unref(msg);
+ return;
+ }
+
+ g_dbus_send_reply(btd_get_dbus_connection(), msg, DBUS_TYPE_INVALID);
+
+ dbus_message_unref(msg);
+}
+
+static DBusMessage *connect_control(DBusConnection *conn, DBusMessage *msg,
void *data)
{
struct audio_device *device = data;
- struct control *control = device->control;
+ int err;
+
+ err = control_connect(device, generic_cb, msg);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ dbus_message_ref(msg);
+
+ return NULL;
+}
+
+int control_disconnect(struct audio_device *dev, audio_device_cb cb,
+ void *data)
+{
+ struct control *control = dev->control;
if (!control->session)
- return btd_error_not_connected(msg);
+ return -ENOTCONN;
+
+ /* cancel pending connect */
+ if (control->connect) {
+ pending_request_free(dev, control->connect, -ECANCELED);
+ control->connect = NULL;
+ }
avctp_disconnect(control->session);
+ if (cb)
+ cb(dev, 0, data);
+
+ return 0;
+
+}
+
+static DBusMessage *disconnect_control(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct audio_device *device = data;
+ int err;
+
+ err = control_disconnect(device, NULL, NULL);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
return dbus_message_new_method_return(msg);
}
@@ -259,8 +325,8 @@ static const GDBusMethodTable control_methods[] = {
{ GDBUS_DEPRECATED_METHOD("IsConnected",
NULL, GDBUS_ARGS({ "connected", "b" }),
control_is_connected) },
- { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, control_connect) },
- { GDBUS_METHOD("Disconnect", NULL, NULL, control_disconnect) },
+ { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, connect_control) },
+ { GDBUS_METHOD("Disconnect", NULL, NULL, disconnect_control) },
{ GDBUS_METHOD("Play", NULL, NULL, control_play) },
{ GDBUS_METHOD("Pause", NULL, NULL, control_pause) },
{ GDBUS_METHOD("Stop", NULL, NULL, control_stop) },
@@ -294,7 +360,7 @@ static void path_unregister(void *data)
avctp_disconnect(control->session);
if (control->connect)
- dbus_message_unref(control->connect);
+ pending_request_free(dev, control->connect, -ECANCELED);
g_free(control);
dev->control = NULL;
diff --git a/profiles/audio/control.h b/profiles/audio/control.h
index 5f4f728..800a151 100644
--- a/profiles/audio/control.h
+++ b/profiles/audio/control.h
@@ -28,3 +28,7 @@ struct control *control_init(struct audio_device *dev, GSList *uuids);
void control_update(struct control *control, GSList *uuids);
void control_unregister(struct audio_device *dev);
gboolean control_is_active(struct audio_device *dev);
+
+int control_connect(struct audio_device *dev, audio_device_cb cb, void *data);
+int control_disconnect(struct audio_device *dev, audio_device_cb cb,
+ void *data);
--
1.7.11.7
^ permalink raw reply related
* [PATCH BlueZ 4/6] sink: Add profile .connect and .disconnect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Add the connection and disconnection hooks to the a2dp_sink btd_profile.
---
profiles/audio/manager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index eaae018..dad46a9 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -262,6 +262,62 @@ static int a2dp_source_disconnect(struct btd_device *dev,
return 0;
}
+static int a2dp_sink_connect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ const gchar *path = device_get_path(dev);
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ DBG("path %s", path);
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = sink_connect(audio_dev, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
+static int a2dp_sink_disconnect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ const gchar *path = device_get_path(dev);
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ DBG("path %s", path);
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = sink_disconnect(audio_dev, FALSE, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
{
adp->ref++;
@@ -436,6 +492,10 @@ static struct btd_profile a2dp_sink_profile = {
.device_probe = a2dp_sink_probe,
.device_remove = audio_remove,
+ .auto_connect = true,
+ .connect = a2dp_sink_connect,
+ .disconnect = a2dp_sink_disconnect,
+
.adapter_probe = a2dp_sink_server_probe,
};
--
1.7.11.7
^ permalink raw reply related
* [PATCH BlueZ 3/6] source: Add profile .connect and .disconnect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Add the connection and disconnection hooks to the a2dp_source
btd_profile.
---
profiles/audio/manager.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index 2f36efd..eaae018 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -74,6 +74,12 @@ struct audio_adapter {
gint ref;
};
+struct profile_req {
+ struct btd_device *device;
+ struct btd_profile *profile;
+ btd_profile_cb cb;
+};
+
static gboolean auto_connect = TRUE;
static int max_connected_headsets = 1;
static GKeyFile *config = NULL;
@@ -176,6 +182,86 @@ static int avrcp_probe(struct btd_profile *p, struct btd_device *device,
return 0;
}
+static struct profile_req *new_profile_request(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ struct profile_req *req;
+
+ req = g_new0(struct profile_req, 1);
+ req->device = dev;
+ req->profile = profile;
+ req->cb = cb;
+
+ return req;
+}
+
+static void profile_cb(struct audio_device *dev, int err, void *data)
+{
+ struct profile_req *req = data;
+
+ if (req->cb)
+ req->cb(req->profile, req->device, err);
+
+ g_free(req);
+}
+
+static int a2dp_source_connect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ const gchar *path = device_get_path(dev);
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ DBG("path %s", path);
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = source_connect(audio_dev, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
+static int a2dp_source_disconnect(struct btd_device *dev,
+ struct btd_profile *profile,
+ btd_profile_cb cb)
+{
+ const gchar *path = device_get_path(dev);
+ struct audio_device *audio_dev;
+ struct profile_req *req;
+ int err;
+
+ DBG("path %s", path);
+
+ audio_dev = get_audio_dev(dev);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ req = new_profile_request(dev, profile, cb);
+
+ err = source_disconnect(audio_dev, FALSE, profile_cb, req);
+ if (err < 0) {
+ g_free(req);
+ return err;
+ }
+
+ return 0;
+}
+
static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
{
adp->ref++;
@@ -335,6 +421,10 @@ static struct btd_profile a2dp_source_profile = {
.device_probe = a2dp_source_probe,
.device_remove = audio_remove,
+ .auto_connect = true,
+ .connect = a2dp_source_connect,
+ .disconnect = a2dp_source_disconnect,
+
.adapter_probe = a2dp_source_server_probe,
};
--
1.7.11.7
^ permalink raw reply related
* [PATCH BlueZ 2/6] audio: Split A2DP into two btd_profile
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1353499818-10153-1-git-send-email-luiz.dentz@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Merging the three audio profiles (AVDTP, A2DP sink and A2DP source)
into one was convenient in the past was doesn't fit very well the new
btd_profile approach. The split is also more consistent with other
existing profiles.
---
profiles/audio/a2dp.c | 80 +++++++++++++++++++++++------------------------
profiles/audio/a2dp.h | 3 +-
profiles/audio/manager.c | 81 +++++++++++++++++++++++++++++++-----------------
3 files changed, 92 insertions(+), 72 deletions(-)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 50c0f43..177f653 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1166,63 +1166,59 @@ static struct a2dp_server *find_server(GSList *list, const bdaddr_t *src)
return NULL;
}
-int a2dp_register(const bdaddr_t *src, GKeyFile *config)
+static struct a2dp_server *a2dp_server_register(const bdaddr_t *src,
+ GKeyFile *config)
{
- gboolean source = TRUE, sink = FALSE;
- char *str;
- GError *err = NULL;
struct a2dp_server *server;
+ int av_err;
- if (!config)
- goto proceed;
+ server = g_new0(struct a2dp_server, 1);
- str = g_key_file_get_string(config, "General", "Enable", &err);
-
- if (err) {
- DBG("audio.conf: %s", err->message);
- g_clear_error(&err);
- } else {
- if (strstr(str, "Sink"))
- source = TRUE;
- if (strstr(str, "Source"))
- sink = TRUE;
- g_free(str);
+ av_err = avdtp_init(src, config);
+ if (av_err < 0) {
+ DBG("AVDTP not registered");
+ g_free(server);
+ return NULL;
}
- str = g_key_file_get_string(config, "General", "Disable", &err);
+ bacpy(&server->src, src);
+ servers = g_slist_append(servers, server);
- if (err) {
- DBG("audio.conf: %s", err->message);
- g_clear_error(&err);
- } else {
- if (strstr(str, "Sink"))
- source = FALSE;
- if (strstr(str, "Source"))
- sink = FALSE;
- g_free(str);
- }
+ return server;
+}
-proceed:
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config)
+{
+ struct a2dp_server *server;
server = find_server(servers, src);
- if (!server) {
- int av_err;
+ if (server != NULL)
+ goto done;
- server = g_new0(struct a2dp_server, 1);
+ server = a2dp_server_register(src, config);
+ if (server == NULL)
+ return -EPROTONOSUPPORT;
- av_err = avdtp_init(src, config);
- if (av_err < 0) {
- g_free(server);
- return av_err;
- }
+done:
+ server->source_enabled = TRUE;
- bacpy(&server->src, src);
- servers = g_slist_append(servers, server);
- }
+ return 0;
+}
- server->source_enabled = source;
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config)
+{
+ struct a2dp_server *server;
- server->sink_enabled = sink;
+ server = find_server(servers, src);
+ if (server != NULL)
+ goto done;
+
+ server = a2dp_server_register(src, config);
+ if (server == NULL)
+ return -EPROTONOSUPPORT;
+
+done:
+ server->sink_enabled = TRUE;
return 0;
}
diff --git a/profiles/audio/a2dp.h b/profiles/audio/a2dp.h
index 736bc66..ded1060 100644
--- a/profiles/audio/a2dp.h
+++ b/profiles/audio/a2dp.h
@@ -64,7 +64,8 @@ typedef void (*a2dp_stream_cb_t) (struct avdtp *session,
struct avdtp_error *err,
void *user_data);
-int a2dp_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_source_register(const bdaddr_t *src, GKeyFile *config);
+int a2dp_sink_register(const bdaddr_t *src, GKeyFile *config);
void a2dp_unregister(const bdaddr_t *src);
struct a2dp_sep *a2dp_add_sep(const bdaddr_t *src, uint8_t type,
diff --git a/profiles/audio/manager.c b/profiles/audio/manager.c
index e453e26..2f36efd 100644
--- a/profiles/audio/manager.c
+++ b/profiles/audio/manager.c
@@ -122,7 +122,7 @@ static void audio_remove(struct btd_profile *p, struct btd_device *device)
audio_device_unregister(dev);
}
-static int a2dp_probe(struct btd_profile *p, struct btd_device *device,
+static int a2dp_source_probe(struct btd_profile *p, struct btd_device *device,
GSList *uuids)
{
struct audio_device *audio_dev;
@@ -133,13 +133,23 @@ static int a2dp_probe(struct btd_profile *p, struct btd_device *device,
return -1;
}
- if (g_slist_find_custom(uuids, A2DP_SINK_UUID, bt_uuid_strcmp) &&
- audio_dev->sink == NULL)
- audio_dev->sink = sink_init(audio_dev);
+ audio_dev->source = source_init(audio_dev);
- if (g_slist_find_custom(uuids, A2DP_SOURCE_UUID, bt_uuid_strcmp) &&
- audio_dev->source == NULL)
- audio_dev->source = source_init(audio_dev);
+ return 0;
+}
+
+static int a2dp_sink_probe(struct btd_profile *p, struct btd_device *device,
+ GSList *uuids)
+{
+ struct audio_device *audio_dev;
+
+ audio_dev = get_audio_dev(device);
+ if (!audio_dev) {
+ DBG("unable to get a device object");
+ return -1;
+ }
+
+ audio_dev->sink = sink_init(audio_dev);
return 0;
}
@@ -213,12 +223,11 @@ static struct audio_adapter *audio_adapter_get(struct btd_adapter *adapter)
return adp;
}
-static int a2dp_server_probe(struct btd_profile *p,
+static int a2dp_source_server_probe(struct btd_profile *p,
struct btd_adapter *adapter)
{
struct audio_adapter *adp;
const gchar *path = adapter_get_path(adapter);
- int err;
DBG("path %s", path);
@@ -226,14 +235,12 @@ static int a2dp_server_probe(struct btd_profile *p,
if (!adp)
return -EINVAL;
- err = a2dp_register(adapter_get_address(adapter), config);
- if (err < 0)
- audio_adapter_unref(adp);
+ audio_adapter_unref(adp); /* Referenced by a2dp server */
- return err;
+ return a2dp_source_register(adapter_get_address(adapter), config);
}
-static void a2dp_server_remove(struct btd_profile *p,
+static int a2dp_sink_server_probe(struct btd_profile *p,
struct btd_adapter *adapter)
{
struct audio_adapter *adp;
@@ -241,12 +248,13 @@ static void a2dp_server_remove(struct btd_profile *p,
DBG("path %s", path);
- adp = find_adapter(adapters, adapter);
+ adp = audio_adapter_get(adapter);
if (!adp)
- return;
+ return -EINVAL;
- a2dp_unregister(adapter_get_address(adapter));
- audio_adapter_unref(adp);
+ audio_adapter_unref(adp); /* Referenced by a2dp server */
+
+ return a2dp_sink_register(adapter_get_address(adapter), config);
}
static int avrcp_server_probe(struct btd_profile *p,
@@ -319,17 +327,26 @@ static void media_server_remove(struct btd_adapter *adapter)
audio_adapter_unref(adp);
}
-static struct btd_profile a2dp_profile = {
- .name = "audio-a2dp",
+static struct btd_profile a2dp_source_profile = {
+ .name = "audio-source",
.priority = BTD_PROFILE_PRIORITY_MEDIUM,
- .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID,
- ADVANCED_AUDIO_UUID),
- .device_probe = a2dp_probe,
+ .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID),
+ .device_probe = a2dp_source_probe,
.device_remove = audio_remove,
- .adapter_probe = a2dp_server_probe,
- .adapter_remove = a2dp_server_remove,
+ .adapter_probe = a2dp_source_server_probe,
+};
+
+static struct btd_profile a2dp_sink_profile = {
+ .name = "audio-sink",
+ .priority = BTD_PROFILE_PRIORITY_MEDIUM,
+
+ .remote_uuids = BTD_UUIDS(A2DP_SINK_UUID),
+ .device_probe = a2dp_sink_probe,
+ .device_remove = audio_remove,
+
+ .adapter_probe = a2dp_sink_server_probe,
};
static struct btd_profile avrcp_profile = {
@@ -402,8 +419,11 @@ int audio_manager_init(GKeyFile *conf)
max_connected_headsets = i;
proceed:
- if (enabled.source || enabled.sink)
- btd_profile_register(&a2dp_profile);
+ if (enabled.source)
+ btd_profile_register(&a2dp_source_profile);
+
+ if (enabled.sink)
+ btd_profile_register(&a2dp_sink_profile);
if (enabled.control)
btd_profile_register(&avrcp_profile);
@@ -420,8 +440,11 @@ void audio_manager_exit(void)
config = NULL;
}
- if (enabled.source || enabled.sink)
- btd_profile_unregister(&a2dp_profile);
+ if (enabled.source)
+ btd_profile_unregister(&a2dp_source_profile);
+
+ if (enabled.sink)
+ btd_profile_unregister(&a2dp_sink_profile);
if (enabled.control)
btd_profile_unregister(&avrcp_profile);
--
1.7.11.7
^ permalink raw reply related
* [PATCH BlueZ 1/6] core: Fix connection order of Device.Connect
From: Luiz Augusto von Dentz @ 2012-11-21 12:10 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
We should with higher priority first.
---
src/device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/device.c b/src/device.c
index 0053098..fd29a7f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1299,7 +1299,7 @@ static gint profile_prio_cmp(gconstpointer a, gconstpointer b)
{
const struct btd_profile *p1 = a, *p2 = b;
- return p1->priority - p2->priority;
+ return p2->priority - p1->priority;
}
static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
--
1.7.11.7
^ permalink raw reply related
* [PATCH v3] neard: Set device class in device object
From: Frédéric Danis @ 2012-11-21 11:59 UTC (permalink / raw)
To: linux-bluetooth
As soon as we have info related to a new device,
device object will be created if it does not exist yet.
Change check_device() to use this device object and
remove call to adapter_remove_device() in it.
---
plugins/neard.c | 32 +++++++++++++++-----------------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 963c8e4..5c9e032 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -39,7 +39,6 @@
#include "manager.h"
#include "device.h"
#include "eir.h"
-#include "storage.h"
#include "agent.h"
#include "hcid.h"
#include "event.h"
@@ -260,28 +259,23 @@ static void bonding_complete(struct btd_adapter *adapter,
error("D-Bus send failed");
}
-static int check_device(struct btd_adapter *adapter, const char *address)
+static int check_device(struct btd_device *device)
{
- struct btd_device *device;
-
- device = adapter_find_device(adapter, address);
+ if (!device)
+ return -ENOENT;
/* If already paired */
- if (device && device_is_paired(device)) {
+ if (device_is_paired(device)) {
DBG("already paired");
return 1;
}
/* Pairing in progress... */
- if (device && device_is_bonding(device, NULL)) {
+ if (device_is_bonding(device, NULL)) {
DBG("pairing in progress");
return -EINPROGRESS;
}
- /* If we have unpaired device hanging around, purge it */
- if (device)
- adapter_remove_device(adapter, device, TRUE);
-
return 0;
}
@@ -291,6 +285,7 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
{
struct eir_data eir_data;
char remote_address[18];
+ struct btd_device *device;
int ret;
DBG("size %zu", size);
@@ -304,7 +299,9 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
- ret = check_device (adapter, remote_address);
+ device = adapter_get_device(adapter, remote_address);
+
+ ret = check_device(device);
if (ret != 0) {
eir_data_free(&eir_data);
return ret;
@@ -312,8 +309,7 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
/* store OOB data */
if (eir_data.class != 0)
- write_remote_class(adapter_get_address(adapter),
- &eir_data.addr, eir_data.class);
+ device_set_class(device, eir_data.class);
/* TODO handle incomplete name? */
if (eir_data.name)
@@ -461,6 +457,7 @@ static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
{
uint8_t *marker;
struct nokia_com_bt nokia;
+ struct btd_device *device;
int ret;
char remote_address[18];
@@ -499,7 +496,9 @@ static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
ba2str(&nokia.address, remote_address);
DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
- ret = check_device(adapter, remote_address);
+ device = adapter_get_device(adapter, remote_address);
+
+ ret = check_device(device);
if (ret != 0) {
g_free(nokia.name);
return ret;
@@ -514,8 +513,7 @@ static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
}
if (nokia.cod != 0)
- write_remote_class(adapter_get_address(adapter), remote,
- nokia.cod);
+ device_set_class(device, nokia.cod);
if (nokia.pin_len > 0) {
/* TODO
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] doc: Add HFP design document
From: Johan Hedberg @ 2012-11-21 11:05 UTC (permalink / raw)
To: Frédéric Danis; +Cc: linux-bluetooth
In-Reply-To: <1353000939-16880-1-git-send-email-frederic.danis@linux.intel.com>
Hi Frederic,
On Thu, Nov 15, 2012, Frédéric Danis wrote:
> ---
> Makefile.am | 2 +-
> doc/audio-telephony-design.txt | 320 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 321 insertions(+), 1 deletion(-)
> create mode 100644 doc/audio-telephony-design.txt
Applied. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH] gdbus: Remove not needed NULL pointer checks
From: Johan Hedberg @ 2012-11-21 10:38 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1353493263-18191-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Wed, Nov 21, 2012, Szymon Janc wrote:
> g_strdup returns NULL if argument passed is NULL and there is no need
> to double check that.
> ---
> gdbus/watch.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH] gdbus: Remove not needed NULL pointer checks
From: Szymon Janc @ 2012-11-21 10:21 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
g_strdup returns NULL if argument passed is NULL and there is no need
to double check that.
---
gdbus/watch.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/gdbus/watch.c b/gdbus/watch.c
index 07feb61..1cd1211 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -240,8 +240,8 @@ proceed:
data = g_new0(struct filter_data, 1);
data->connection = dbus_connection_ref(connection);
- data->name = name ? g_strdup(name) : NULL;
- data->owner = owner ? g_strdup(owner) : NULL;
+ data->name = g_strdup(name);
+ data->owner = g_strdup(owner);
data->path = g_strdup(path);
data->interface = g_strdup(interface);
data->member = g_strdup(member);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 2/2] Bluetooth: Implement deferred sco socket setup
From: Frédéric Dalleau @ 2012-11-21 9:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1353491473-3789-1-git-send-email-frederic.dalleau@linux.intel.com>
In order to authenticate and configure an incoming SCO connection, the
BT_DEFER_SETUP option was added. This option is intended to defer reply
to Connect Request on SCO sockets.
When a connection is requested, the listening socket is unblocked but
the effective connection setup happens only on first recv. Any send
between accept and recv fails with -ENOTCONN.
Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com>
---
include/net/bluetooth/hci_core.h | 9 ++++---
net/bluetooth/hci_event.c | 52 +++++++++++++++++++++++++++++++++++---
net/bluetooth/sco.c | 35 ++++++++++++++++++++++---
3 files changed, 86 insertions(+), 10 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ef5b85d..76891a9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -376,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
u16 flags);
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
@@ -577,6 +577,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
+void hci_conn_accept(struct hci_conn *conn, int mask);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
void hci_chan_del(struct hci_chan *chan);
@@ -779,8 +780,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_host_le_br_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE_BREDR)
/* ----- HCI protocols ----- */
+#define HCI_PROTO_DEFER 0x01
+
static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
- __u8 type)
+ __u8 type, __u8 *flags)
{
switch (type) {
case ACL_LINK:
@@ -788,7 +791,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
case SCO_LINK:
case ESCO_LINK:
- return sco_connect_ind(hdev, bdaddr);
+ return sco_connect_ind(hdev, bdaddr, flags);
default:
BT_ERR("unknown link type %d", type);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9f5c5f2..c3e16d8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2047,15 +2047,53 @@ unlock:
hci_conn_check_pending(hdev);
}
+void hci_conn_accept(struct hci_conn *conn, int mask)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("conn %p", conn);
+
+ if (!lmp_esco_capable(hdev)) {
+ struct hci_cp_accept_conn_req cp;
+
+ conn->state = BT_CONFIG;
+ bacpy(&cp.bdaddr, &conn->dst);
+
+ if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+ cp.role = 0x00; /* Become master */
+ else
+ cp.role = 0x01; /* Remain slave */
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+ } else /* lmp_esco_capable(hdev)) */ {
+ struct hci_cp_accept_sync_conn_req cp;
+
+ conn->state = BT_CONFIG;
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+ cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.max_latency = __constant_cpu_to_le16(0xffff);
+ cp.content_format = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = 0xff;
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+ sizeof(cp), &cp);
+ }
+}
+
static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_request *ev = (void *) skb->data;
int mask = hdev->link_mode;
+ __u8 flags = 0;
BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
ev->link_type);
- mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
+ mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
+ &flags);
if ((mask & HCI_LM_ACCEPT) &&
!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
@@ -2081,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
}
memcpy(conn->dev_class, ev->dev_class, 3);
- conn->state = BT_CONNECT;
hci_dev_unlock(hdev);
- if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
+ if (ev->link_type == ACL_LINK ||
+ (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
struct hci_cp_accept_conn_req cp;
+ conn->state = BT_CONNECT;
bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -2097,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
&cp);
- } else {
+ } else if (!(flags & HCI_PROTO_DEFER)) {
struct hci_cp_accept_sync_conn_req cp;
+ conn->state = BT_CONNECT;
bacpy(&cp.bdaddr, &ev->bdaddr);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
@@ -2111,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
sizeof(cp), &cp);
+ } else {
+ conn->state = BT_CONNECT2;
+ hci_proto_connect_cfm(conn, 0);
+ hci_conn_put(conn);
}
} else {
/* Connection rejected */
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index c6678f2..eea17cd 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -397,6 +397,7 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
if (parent) {
sk->sk_type = parent->sk_type;
+ bt_sk(sk)->flags = bt_sk(parent)->flags;
security_sk_clone(parent, sk);
}
}
@@ -662,6 +663,28 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return err;
}
+static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct sco_pinfo *pi = sco_pi(sk);
+
+ lock_sock(sk);
+
+ if (sk->sk_state == BT_CONNECT2 &&
+ test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+ hci_conn_accept(pi->conn->hcon, 0);
+ sk->sk_state = BT_CONFIG;
+
+ release_sock(sk);
+ return 0;
+ }
+
+ release_sock(sk);
+
+ return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+}
+
static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
@@ -906,7 +929,10 @@ static void sco_conn_ready(struct sco_conn *conn)
hci_conn_hold(conn->hcon);
__sco_chan_add(conn, sk, parent);
- sk->sk_state = BT_CONNECTED;
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
+ sk->sk_state = BT_CONNECT2;
+ else
+ sk->sk_state = BT_CONNECTED;
/* Wake up parent */
parent->sk_data_ready(parent, 1);
@@ -919,7 +945,7 @@ done:
}
/* ----- SCO interface with lower layer (HCI) ----- */
-int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
{
struct sock *sk;
struct hlist_node *node;
@@ -936,6 +962,9 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
lm |= HCI_LM_ACCEPT;
+
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+ *flags |= HCI_PROTO_DEFER;
break;
}
}
@@ -1024,7 +1053,7 @@ static const struct proto_ops sco_sock_ops = {
.accept = sco_sock_accept,
.getname = sco_sock_getname,
.sendmsg = sco_sock_sendmsg,
- .recvmsg = bt_sock_recvmsg,
+ .recvmsg = sco_sock_recvmsg,
.poll = bt_sock_poll,
.ioctl = bt_sock_ioctl,
.mmap = sock_no_mmap,
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 1/2] Bluetooth: Add BT_DEFER_SETUP option to sco socket
From: Frédéric Dalleau @ 2012-11-21 9:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1353491473-3789-1-git-send-email-frederic.dalleau@linux.intel.com>
This option will set the BT_SK_DEFER_SETUP bit in socket flags.
Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com>
---
net/bluetooth/sco.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 450cdcd..c6678f2 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -666,12 +666,31 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
{
struct sock *sk = sock->sk;
int err = 0;
+ u32 opt;
BT_DBG("sk %p", sk);
lock_sock(sk);
switch (optname) {
+
+ case BT_DEFER_SETUP:
+ if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ else
+ clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -753,6 +772,19 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
lock_sock(sk);
switch (optname) {
+
+ case BT_DEFER_SETUP:
+ if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
+ (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 0/2] sco: BT_DEFER_SETUP for SCO sockets
From: Frédéric Dalleau @ 2012-11-21 9:51 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
Hi,
This patch implements BT_DEFER_SETUP option on SCO sockets. hci layer get some
changes since previous behavior was to accept all SCO connections.
How to test :
compile bluez (3fd3d5f or newer) with --enable-test and run:
$ btiotest -s -d -a 5
on another machine run:
$ btiotest -s <bdaddr>
Check result with btmon.
Best regards,
Frédéric
Frédéric Dalleau (2):
Bluetooth: Add BT_DEFER_SETUP option to sco socket
Bluetooth: Implement deferred sco socket setup
include/net/bluetooth/hci_core.h | 9 +++--
net/bluetooth/hci_event.c | 52 ++++++++++++++++++++++++++---
net/bluetooth/sco.c | 67 ++++++++++++++++++++++++++++++++++++--
3 files changed, 118 insertions(+), 10 deletions(-)
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH 2/2] Bluetooth: Implement deferred sco socket setup
From: Frédéric Dalleau @ 2012-11-20 18:08 UTC (permalink / raw)
To: Gustavo Padovan, linux-bluetooth
In-Reply-To: <20121120180114.GJ14006@joana>
Hi,
On 11/20/2012 07:01 PM, Gustavo Padovan wrote:
> * Frédéric Dalleau <frederic.dalleau@linux.intel.com> [2012-11-20 18:55:39 +0100]:
>
>> Hi Gustavo,
>>
>> I'm taking your remarks into account asap
>>
>> On 11/20/2012 06:37 PM, Gustavo Padovan wrote:
>>> Where do you set sk_state to BT_CONNECTED. Doesn't it need to be here?
>> The state is set to BT_CONNECTED in hci_sync_conn_complete_evt. ie when
>> the connection is effectively created.
>
> Are we both talking about the sk_state var? I failed to see how it is set to
> BT_CONNECTED.
Yes, hci_sync_conn_complete_evt > hci_proto_connect_cfm > sco_connect_cfm >
if there is no error, sco_conn_ready.
Since the socket is already created we get in first if branch.
Frédéric
^ permalink raw reply
* Re: [PATCH v2] Bluetooth: Remove OOB data if device was discovered in band
From: Gustavo Padovan @ 2012-11-20 18:04 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1353407934-17831-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
* Szymon Janc <szymon.janc@tieto.com> [2012-11-20 11:38:54 +0100]:
> OOB authentication mechanism should be used only if pairing process
> has been activated by previous OOB information exchange (Core Spec
> 4.0 , vol. 1, Part A, 5.1.4.3). Stored OOB data for specific device
> should be removed if that device was discovered in band later on.
>
> Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
> ---
> V2:
> Move OOB data removal to hci_inquiry_cache_update to cover all inquiry
> events (ext/rssi) in one place.
>
> net/bluetooth/hci_core.c | 2 ++
> 1 file changed, 2 insertions(+)
patch has been applied to bluetooth-next. Thanks.
Gustavo
^ permalink raw reply
* Re: [PATCH 2/2] Bluetooth: Implement deferred sco socket setup
From: Gustavo Padovan @ 2012-11-20 18:01 UTC (permalink / raw)
To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <50ABC41B.8030802@linux.intel.com>
* Frédéric Dalleau <frederic.dalleau@linux.intel.com> [2012-11-20 18:55:39 +0100]:
> Hi Gustavo,
>
> I'm taking your remarks into account asap
>
> On 11/20/2012 06:37 PM, Gustavo Padovan wrote:
> >Where do you set sk_state to BT_CONNECTED. Doesn't it need to be here?
> The state is set to BT_CONNECTED in hci_sync_conn_complete_evt. ie when
> the connection is effectively created.
Are we both talking about the sk_state var? I failed to see how it is set to
BT_CONNECTED.
Gustavo
^ permalink raw reply
* Re: [RFC 4/4] Bluetooth: AMP: Set no FCS for incoming L2CAP chan
From: Gustavo Padovan @ 2012-11-20 17:56 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1353424582-26042-5-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
* Andrei Emeltchenko <Andrei.Emeltchenko.news@gmail.com> [2012-11-20 17:16:22 +0200]:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> When receiving L2CAP Create Channel Request set the channel as
> L2CAP_FCS_NONE. Then in "L2CAP Config req" following field will
> be set: "FCS Option 0x00 (No FCS)". So by default High Speed
> channels have no FCS.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
> net/bluetooth/l2cap_core.c | 1 +
> 1 file changed, 1 insertion(+)
All 4 patches have been applied to bluetooth-next. Thanks.
Gustavo
^ 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