* [PATCH v2 BlueZ 09/27] alert: Implement category registration in RegisterAlert()
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Eder Ruiz Maria
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
From: Eder Ruiz Maria <eder.ruiz@openbossa.org>
The given alert category is now validated and registered.
---
profiles/alert/server.c | 102 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 98 insertions(+), 4 deletions(-)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index c0434a4..2c7373c 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -77,19 +77,113 @@ enum {
RINGER_NORMAL,
};
+struct alert_data {
+ const char *category;
+ char *srv;
+ char *path;
+};
+
+static GSList *registered_alerts = NULL;
static uint8_t ringer_setting = RINGER_NORMAL;
static uint8_t alert_status = 0;
+static const char *anp_categories[] = {
+ "simple",
+ "email",
+ "news",
+ "call",
+ "missed_call",
+ "sms_mms",
+ "voice_mail",
+ "schedule",
+ "high_priority",
+ "instant_message",
+};
+
+static const char *pasp_categories[] = {
+ "ringer",
+ "vibrate",
+ "display",
+};
+
+static void alert_data_destroy(gpointer user_data)
+{
+ struct alert_data *alert = user_data;
+
+ g_free(alert->srv);
+ g_free(alert->path);
+ g_free(alert);
+}
+
+static void alert_destroy(gpointer user_data)
+{
+ g_slist_free_full(registered_alerts, alert_data_destroy);
+ registered_alerts = NULL;
+}
+
+static const char *valid_category(const char *category)
+{
+ unsigned i;
+
+ for (i = 0; i < G_N_ELEMENTS(anp_categories); i++) {
+ if (g_str_equal(anp_categories[i], category))
+ return anp_categories[i];
+ }
+
+ for (i = 0; i < G_N_ELEMENTS(pasp_categories); i++) {
+ if (g_str_equal(pasp_categories[i], category))
+ return pasp_categories[i];
+ }
+
+ return NULL;
+}
+
+static gboolean registered_category(const char *category)
+{
+ GSList *l;
+ struct alert_data *alert;
+
+ for (l = registered_alerts; l; l = g_slist_next(l)) {
+ alert = l->data;
+ if (g_str_equal(alert->category, category))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static DBusMessage *register_alert(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+ const char *sender = dbus_message_get_sender(msg);
+ char *path;
const char *category;
+ const char *c;
+ struct alert_data *alert;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &c,
+ DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &category,
- DBUS_TYPE_INVALID))
+ category = valid_category(c);
+ if (!category) {
+ DBG("Invalid category: %s", c);
return btd_error_invalid_args(msg);
+ }
+
+ if (registered_category(category)) {
+ DBG("Category %s already registered", category);
+ return dbus_message_new_method_return(msg);
+ }
+
+ alert = g_new0(struct alert_data, 1);
+ alert->srv = g_strdup(sender);
+ alert->path = g_strdup(path);
+ alert->category = category;
+
+ registered_alerts = g_slist_append(registered_alerts, alert);
- DBG("RegisterAlert: %s", category);
+ DBG("RegisterAlert(\"%s\", \"%s\")", alert->category, alert->path);
return dbus_message_new_method_return(msg);
}
@@ -290,7 +384,7 @@ int alert_server_init(void)
if (!g_dbus_register_interface(btd_get_dbus_connection(),
ALERT_OBJECT_PATH, ALERT_INTERFACE,
alert_methods, NULL, NULL, NULL,
- NULL)) {
+ alert_destroy)) {
error("D-Bus failed to register %s interface",
ALERT_INTERFACE);
return -EIO;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 08/27] alert: Initial Alert Notification
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
Initial implementation for Alert Notification Profile (ANP).
---
profiles/alert/server.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index 90536d5..c0434a4 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -27,9 +27,12 @@
#endif
#include <stdbool.h>
+#include <errno.h>
+#include <gdbus.h>
#include <glib.h>
#include <bluetooth/uuid.h>
+#include "dbus-common.h"
#include "att.h"
#include "adapter.h"
#include "device.h"
@@ -41,13 +44,33 @@
#include "gatt.h"
#include "server.h"
#include "profile.h"
+#include "error.h"
#define PHONE_ALERT_STATUS_SVC_UUID 0x180E
+#define ALERT_NOTIF_SVC_UUID 0x1811
#define ALERT_STATUS_CHR_UUID 0x2A3F
#define RINGER_CP_CHR_UUID 0x2A40
#define RINGER_SETTING_CHR_UUID 0x2A41
+#define ALERT_NOTIF_CP_CHR_UUID 0x2A44
+#define UNREAD_ALERT_CHR_UUID 0x2A45
+#define NEW_ALERT_CHR_UUID 0x2A46
+#define SUPP_NEW_ALERT_CAT_CHR_UUID 0x2A47
+#define SUPP_UNREAD_ALERT_CAT_CHR_UUID 0x2A48
+
+#define ALERT_OBJECT_PATH "/org/bluez"
+#define ALERT_INTERFACE "org.bluez.Alert"
+
+enum {
+ ENABLE_NEW_INCOMING,
+ ENABLE_UNREAD_CAT,
+ DISABLE_NEW_INCOMING,
+ DISABLE_UNREAD_CAT,
+ NOTIFY_NEW_INCOMING,
+ NOTIFY_UNREAD_CAT,
+};
+
/* Ringer Setting characteristic values */
enum {
RINGER_SILENT,
@@ -57,6 +80,20 @@ enum {
static uint8_t ringer_setting = RINGER_NORMAL;
static uint8_t alert_status = 0;
+static DBusMessage *register_alert(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *category;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &category,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ DBG("RegisterAlert: %s", category);
+
+ return dbus_message_new_method_return(msg);
+}
+
static uint8_t ringer_cp_write(struct attribute *a,
struct btd_device *device,
gpointer user_data)
@@ -124,10 +161,107 @@ static void register_phone_alert_service(struct btd_adapter *adapter)
GATT_OPT_INVALID);
}
+static uint8_t supp_new_alert_cat_read(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+ uint8_t value[] = {0x00, 0x00};
+
+ DBG("a = %p", a);
+
+ if (a->data == NULL)
+ attrib_db_update(adapter, a->handle, NULL, value, sizeof(value),
+ NULL);
+
+ return 0;
+}
+
+static uint8_t supp_unread_alert_cat_read(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+ uint8_t value[] = {0x00, 0x00};
+
+ DBG("a = %p", a);
+
+ if (a->data == NULL)
+ attrib_db_update(adapter, a->handle, NULL, value, sizeof(value),
+ NULL);
+
+ return 0;
+}
+
+static uint8_t alert_notif_cp_write(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ DBG("a = %p", a);
+
+ switch (a->data[0]) {
+ case ENABLE_NEW_INCOMING:
+ DBG("ENABLE_NEW_INCOMING: 0x%02x", a->data[1]);
+ break;
+ case ENABLE_UNREAD_CAT:
+ DBG("ENABLE_UNREAD_CAT: 0x%02x", a->data[1]);
+ break;
+ case DISABLE_NEW_INCOMING:
+ DBG("DISABLE_NEW_INCOMING: 0x%02x", a->data[1]);
+ break;
+ case DISABLE_UNREAD_CAT:
+ DBG("DISABLE_UNREAD_CAT: 0x%02x", a->data[1]);
+ break;
+ case NOTIFY_NEW_INCOMING:
+ DBG("NOTIFY_NEW_INCOMING: 0x%02x", a->data[1]);
+ break;
+ case NOTIFY_UNREAD_CAT:
+ DBG("NOTIFY_UNREAD_CAT: 0x%02x", a->data[1]);
+ break;
+ default:
+ DBG("0x%02x 0x%02x", a->data[0], a->data[1]);
+ }
+
+ return 0;
+}
+
+static void register_alert_notif_service(struct btd_adapter *adapter)
+{
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, ALERT_NOTIF_SVC_UUID);
+
+ /* Alert Notification Service */
+ gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+ /* Supported New Alert Category */
+ GATT_OPT_CHR_UUID, SUPP_NEW_ALERT_CAT_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ supp_new_alert_cat_read, adapter,
+ /* New Alert */
+ GATT_OPT_CHR_UUID, NEW_ALERT_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_NOTIFY,
+ /* Supported Unread Alert Category */
+ GATT_OPT_CHR_UUID, SUPP_UNREAD_ALERT_CAT_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ supp_unread_alert_cat_read, adapter,
+ /* Unread Alert Status */
+ GATT_OPT_CHR_UUID, UNREAD_ALERT_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_NOTIFY,
+ /* Alert Notification Control Point */
+ GATT_OPT_CHR_UUID, ALERT_NOTIF_CP_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_WRITE,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
+ alert_notif_cp_write, NULL,
+ GATT_OPT_INVALID);
+}
+
static int alert_server_probe(struct btd_profile *p,
struct btd_adapter *adapter)
{
register_phone_alert_service(adapter);
+ register_alert_notif_service(adapter);
return 0;
}
@@ -143,8 +277,25 @@ static struct btd_profile alert_profile = {
.adapter_remove = alert_server_remove,
};
+static const GDBusMethodTable alert_methods[] = {
+ { GDBUS_METHOD("RegisterAlert",
+ GDBUS_ARGS({ "category", "s" },
+ { "agent", "o" }), NULL,
+ register_alert) },
+ { }
+};
+
int alert_server_init(void)
{
+ if (!g_dbus_register_interface(btd_get_dbus_connection(),
+ ALERT_OBJECT_PATH, ALERT_INTERFACE,
+ alert_methods, NULL, NULL, NULL,
+ NULL)) {
+ error("D-Bus failed to register %s interface",
+ ALERT_INTERFACE);
+ return -EIO;
+ }
+
btd_profile_register(&alert_profile);
return 0;
@@ -153,4 +304,7 @@ int alert_server_init(void)
void alert_server_exit(void)
{
btd_profile_unregister(&alert_profile);
+
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ ALERT_OBJECT_PATH, ALERT_INTERFACE);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 07/27] alert: Add Alert Status characteristic
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
This characteristic allows to read/notify the status of the ringer,
display and vibration motor.
---
profiles/alert/server.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index 59e6fdc..90536d5 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -43,6 +43,8 @@
#include "profile.h"
#define PHONE_ALERT_STATUS_SVC_UUID 0x180E
+
+#define ALERT_STATUS_CHR_UUID 0x2A3F
#define RINGER_CP_CHR_UUID 0x2A40
#define RINGER_SETTING_CHR_UUID 0x2A41
@@ -53,6 +55,7 @@ enum {
};
static uint8_t ringer_setting = RINGER_NORMAL;
+static uint8_t alert_status = 0;
static uint8_t ringer_cp_write(struct attribute *a,
struct btd_device *device,
@@ -63,6 +66,21 @@ static uint8_t ringer_cp_write(struct attribute *a,
return 0;
}
+static uint8_t alert_status_read(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+
+ DBG("a = %p", a);
+
+ if (a->data == NULL || a->data[0] != alert_status)
+ attrib_db_update(adapter, a->handle, NULL, &alert_status,
+ sizeof(alert_status), NULL);
+
+ return 0;
+}
+
static uint8_t ringer_setting_read(struct attribute *a,
struct btd_device *device,
gpointer user_data)
@@ -86,6 +104,12 @@ static void register_phone_alert_service(struct btd_adapter *adapter)
/* Phone Alert Status Service */
gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+ /* Alert Status characteristic */
+ GATT_OPT_CHR_UUID, ALERT_STATUS_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ |
+ ATT_CHAR_PROPER_NOTIFY,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ alert_status_read, adapter,
/* Ringer Control Point characteristic */
GATT_OPT_CHR_UUID, RINGER_CP_CHR_UUID,
GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 06/27] alert: Add Ringer Setting characteristic
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
This characteristic allows to read or notify the ringer mode (silent or
normal).
---
profiles/alert/server.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index 8337c38..59e6fdc 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -37,12 +37,22 @@
#include "log.h"
#include "gatt-service.h"
#include "gattrib.h"
+#include "attrib-server.h"
#include "gatt.h"
#include "server.h"
#include "profile.h"
#define PHONE_ALERT_STATUS_SVC_UUID 0x180E
#define RINGER_CP_CHR_UUID 0x2A40
+#define RINGER_SETTING_CHR_UUID 0x2A41
+
+/* Ringer Setting characteristic values */
+enum {
+ RINGER_SILENT,
+ RINGER_NORMAL,
+};
+
+static uint8_t ringer_setting = RINGER_NORMAL;
static uint8_t ringer_cp_write(struct attribute *a,
struct btd_device *device,
@@ -53,6 +63,21 @@ static uint8_t ringer_cp_write(struct attribute *a,
return 0;
}
+static uint8_t ringer_setting_read(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+
+ DBG("a = %p", a);
+
+ if (a->data == NULL || a->data[0] != ringer_setting)
+ attrib_db_update(adapter, a->handle, NULL, &ringer_setting,
+ sizeof(ringer_setting), NULL);
+
+ return 0;
+}
+
static void register_phone_alert_service(struct btd_adapter *adapter)
{
bt_uuid_t uuid;
@@ -66,6 +91,12 @@ static void register_phone_alert_service(struct btd_adapter *adapter)
GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
ringer_cp_write, NULL,
+ /* Ringer Setting characteristic */
+ GATT_OPT_CHR_UUID, RINGER_SETTING_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ |
+ ATT_CHAR_PROPER_NOTIFY,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ ringer_setting_read, adapter,
GATT_OPT_INVALID);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 05/27] alert: Add Ringer Control Point characteristic
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
Ringer CP characteristic is used for configuring "silent mode" or muting
the ringer once.
---
profiles/alert/server.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index b39ef8a..8337c38 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -32,6 +32,9 @@
#include "att.h"
#include "adapter.h"
+#include "device.h"
+#include "att-database.h"
+#include "log.h"
#include "gatt-service.h"
#include "gattrib.h"
#include "gatt.h"
@@ -39,6 +42,16 @@
#include "profile.h"
#define PHONE_ALERT_STATUS_SVC_UUID 0x180E
+#define RINGER_CP_CHR_UUID 0x2A40
+
+static uint8_t ringer_cp_write(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ DBG("a = %p", a);
+
+ return 0;
+}
static void register_phone_alert_service(struct btd_adapter *adapter)
{
@@ -48,6 +61,11 @@ static void register_phone_alert_service(struct btd_adapter *adapter)
/* Phone Alert Status Service */
gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+ /* Ringer Control Point characteristic */
+ GATT_OPT_CHR_UUID, RINGER_CP_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
+ ringer_cp_write, NULL,
GATT_OPT_INVALID);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 04/27] alert: Add Phone Alert Status Service
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
Add Phone Alert Status service for PASP.
---
profiles/alert/server.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index dc844d3..b39ef8a 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -27,14 +27,35 @@
#endif
#include <stdbool.h>
+#include <glib.h>
+#include <bluetooth/uuid.h>
+#include "att.h"
#include "adapter.h"
+#include "gatt-service.h"
+#include "gattrib.h"
+#include "gatt.h"
#include "server.h"
#include "profile.h"
+#define PHONE_ALERT_STATUS_SVC_UUID 0x180E
+
+static void register_phone_alert_service(struct btd_adapter *adapter)
+{
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, PHONE_ALERT_STATUS_SVC_UUID);
+
+ /* Phone Alert Status Service */
+ gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+ GATT_OPT_INVALID);
+}
+
static int alert_server_probe(struct btd_profile *p,
struct btd_adapter *adapter)
{
+ register_phone_alert_service(adapter);
+
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 03/27] alert: Initial profile registration
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
---
profiles/alert/server.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index d91b156..dc844d3 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -26,13 +26,37 @@
#include <config.h>
#endif
+#include <stdbool.h>
+
+#include "adapter.h"
#include "server.h"
+#include "profile.h"
+
+static int alert_server_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ return 0;
+}
+
+static void alert_server_remove(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+}
+
+static struct btd_profile alert_profile = {
+ .name = "gatt-alert-server",
+ .adapter_probe = alert_server_probe,
+ .adapter_remove = alert_server_remove,
+};
int alert_server_init(void)
{
+ btd_profile_register(&alert_profile);
+
return 0;
}
void alert_server_exit(void)
{
+ btd_profile_unregister(&alert_profile);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 02/27] alert: Introduce manager abstraction layer
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
This abstraction layer makes the GATT Phone Alert Status and Alert
Notification implementation consistent with other GATT profiles.
---
Makefile.am | 3 ++-
profiles/alert/main.c | 6 +++---
profiles/alert/manager.c | 40 ++++++++++++++++++++++++++++++++++++++++
profiles/alert/manager.h | 26 ++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 4 deletions(-)
create mode 100644 profiles/alert/manager.c
create mode 100644 profiles/alert/manager.h
diff --git a/Makefile.am b/Makefile.am
index a42544d..e86bd4d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -218,7 +218,8 @@ builtin_sources += profiles/thermometer/main.c \
profiles/thermometer/thermometer.h \
profiles/thermometer/thermometer.c \
profiles/alert/main.c profiles/alert/server.h \
- profiles/alert/server.c \
+ profiles/alert/server.c profiles/alert/manager.h \
+ profiles/alert/manager.c \
profiles/time/main.c profiles/time/server.h \
profiles/time/server.c profiles/time/manager.c \
profiles/time/manager.h \
diff --git a/profiles/alert/main.c b/profiles/alert/main.c
index ec4ab6d..5e6910a 100644
--- a/profiles/alert/main.c
+++ b/profiles/alert/main.c
@@ -33,7 +33,7 @@
#include "plugin.h"
#include "hcid.h"
#include "log.h"
-#include "server.h"
+#include "manager.h"
static int alert_init(void)
{
@@ -42,7 +42,7 @@ static int alert_init(void)
return -ENOTSUP;
}
- return alert_server_init();
+ return alert_manager_init();
}
static void alert_exit(void)
@@ -50,7 +50,7 @@ static void alert_exit(void)
if (!main_opts.gatt_enabled)
return;
- alert_server_exit();
+ alert_manager_exit();
}
BLUETOOTH_PLUGIN_DEFINE(alert, VERSION,
diff --git a/profiles/alert/manager.c b/profiles/alert/manager.c
new file mode 100644
index 0000000..eb2d627
--- /dev/null
+++ b/profiles/alert/manager.c
@@ -0,0 +1,40 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nokia Corporation
+ * Copyright (C) 2012 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "manager.h"
+#include "server.h"
+
+int alert_manager_init(void)
+{
+ return alert_server_init();
+}
+
+void alert_manager_exit(void)
+{
+ alert_server_exit();
+}
diff --git a/profiles/alert/manager.h b/profiles/alert/manager.h
new file mode 100644
index 0000000..e4c6bd0
--- /dev/null
+++ b/profiles/alert/manager.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nokia Corporation
+ * Copyright (C) 2012 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int alert_manager_init(void);
+void alert_manager_exit(void);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 01/27] doc: Introduce Alert API
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>
This API will be implemented and initially used by Phone Alert Status
and Alert Notification GATT profiles (server role).
---
Makefile.am | 2 +-
doc/alert-api.txt | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 1 deletion(-)
create mode 100644 doc/alert-api.txt
diff --git a/Makefile.am b/Makefile.am
index 315077f..a42544d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -385,7 +385,7 @@ EXTRA_DIST += doc/manager-api.txt \
doc/network-api.txt doc/input-api.txt doc/audio-api.txt \
doc/control-api.txt doc/hfp-api.txt doc/health-api.txt \
doc/sap-api.txt doc/media-api.txt doc/assigned-numbers.txt \
- doc/supported-features.txt
+ doc/supported-features.txt doc/alert-api.txt
AM_YFLAGS = -d
diff --git a/doc/alert-api.txt b/doc/alert-api.txt
new file mode 100644
index 0000000..e58430c
--- /dev/null
+++ b/doc/alert-api.txt
@@ -0,0 +1,109 @@
+BlueZ D-Bus Alert API description
+*********************************
+
+Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+
+Introduction
+------------
+
+Currently, there are two different GATT server profiles that depend on
+receiving alerts or notifications from the platform: Phone Alert Status (PASP)
+and Alert Notification (ANP). PASP is very specific to mobile phones, and also
+allows limited control to alerts (i.e. mute once or switch to a silent mode).
+
+This document presents a unified API that allows to register and notify alerts,
+and to control some alerts (using the provided agent object).
+
+
+Alert hierarchy
+===============
+
+Service org.bluez
+Interface org.bluez.Alert
+Object path /org/bluez
+
+Methods void RegisterAlert(string category, object agent)
+
+ Register a new alert category and an agent for it. This
+ means the application will be responsible for notifying
+ BlueZ of any alerts of that category, using the
+ NewAlert() method.
+
+ Supported ANP categories: simple, email, news, call,
+ missed_call, sms_mms, voice_mail, schedule,
+ high_priority, instant_message
+ Supported PASP categories: ringer, vibrate, display
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ void NewAlert(string category, uint16 count, string description)
+
+ Notify BlueZ of new alert(s) for the given category. The
+ description is relative to the last received alert and
+ can be sender name, caller ID, title, or other
+ information specific to the category.
+
+ For ringer, vibrate and display categories, valid
+ descriptions are "active" and "not active". Alerts from
+ ringer category also accept "enabled" and "disabled",
+ depending on whether ringer is in silent mode or not.
+
+ Description must not exceed 18 bytes when encoded in
+ UTF-8 format, otherwise an error is returned. If there
+ is no description, an empty string should be used.
+
+ The count argument contains the number of alerts not
+ yet acknowledged by the user on the UI. To save D-Bus
+ traffic, events that may generate multiple alerts at
+ the same time (like email, sms, news) should trigger a
+ single NewAlert().
+
+ If there are more than 254 new alerts, count must be
+ set to 255. PASP alerts should always set count to 1.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ void UnreadAlert(string category, uint16 count)
+
+ Some services (like SMS and e-mail) keep track of
+ number of unread items. This method allows to update
+ this counter, so peer devices can be notified using
+ Alert Notification Profile.
+
+ If there are more than 254 unread alerts, count must be
+ set to 255.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+Alert Agent hierarchy
+=====================
+
+Service org.bluez
+Interface org.bluez.AlertAgent
+Object path freely definable
+
+Methods void MuteOnce()
+
+ This method is only called if "ringer" alert category
+ is specified when registering the agent.
+
+ Mute the ringer once (e.g. during a incoming call). If
+ ringer is not active, does nothing.
+
+ void SetRinger(string mode)
+
+ This method is only called if "ringer" alert category
+ is specified when registering the agent.
+
+ Set ringer to the specified mode. If mode is "enabled",
+ ringer is set to the default mode, as defined by the
+ current active profile. If mode is "disabled", ringer
+ will not activate on incoming calls, until it is set
+ back to "enabled" mode.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ void Release()
+
+ Release this agent. At this point, it will not be used
+ by BlueZ anymore and can be destroyed by the owner.
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 BlueZ 00/27] Add support for PASP and ANP server profiles
From: Anderson Lizardo @ 2012-09-27 18:36 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1348509661-15967-1-git-send-email-anderson.lizardo@openbossa.org>
Hi,
This series implement most of mandatory features for Phone Alert Status (PASP)
and Alert Notification (ANP) profiles. The only major mandatory feature
currently missing is support for ANP control point (which will be added on a
future series).
Note: for those planning to use ANP/PASP in BlueZ using these patches, it is
necessary to implement an "agent" that forwards platform events (SMS, calls,
e-mail, and ringer/display/vibra status) to BlueZ. See doc/alert-api.txt and
test/test-alert for more details. Alternatively, the components that generate
these events can register themselves and report alerts directly to BlueZ.
This implementation was tested against PTS and all tests passed (except for the
features not yet implemented). The D-Bus API was implemented accordingly to the
previously proposed Alert API (documented on the first patch).
Comments/suggestions are welcome.
Changes since v1:
* Rebase against latest btd_profile changes
* Add test-alert to Makefile.tools and alert-api.txt to Makefile.am
* Add org.bluez.AlertAgent to D-Bus policy file (patch 27/27)
* Implement Release() agent method (patch 26/27)
* Remove Suspend()/Resume() from documentation (they are not implemented, and
they are optimizations that can be added later if necessary).
Anderson Lizardo (13):
doc: Introduce Alert API
alert: Introduce manager abstraction layer
alert: Initial profile registration
alert: Initial Alert Notification
alert: Add initial support for UnreadAlert D-Bus method
alert: Add per adapter attribute handle information
alert: Update Supported New/Unread Category characteristic values
alert: Update new alert characteristic value
alert: Update unread alert characteristic value
alert: Implement MuteOnce command
alert: Update Alert Status and Ringer Setting characteristic values
alert: Implement Release() agent method
alert: Add org.bluez.AlertAgent to D-Bus policy file
Bruna Moreira (4):
alert: Add Phone Alert Status Service
alert: Add Ringer Control Point characteristic
alert: Add Ringer Setting characteristic
alert: Add Alert Status characteristic
Eder Ruiz Maria (10):
alert: Implement category registration in RegisterAlert()
alert: Add initial support for NewAlert D-Bus method
alert: Automatically unregister alert when agent leaves D-Bus
alert: Add support for calling MuteOnce()
alert: Add support for calling SetRinger()
alert: Add test-alert script
alert: Add support for ringer setting notification
alert: Add support for alert status notification
alert: Add support for new alert notification
alert: Add support for unread alert notification
Makefile.am | 5 +-
Makefile.tools | 3 +-
doc/alert-api.txt | 109 ++++++
profiles/alert/main.c | 6 +-
profiles/alert/manager.c | 40 ++
profiles/alert/manager.h | 26 ++
profiles/alert/server.c | 962 ++++++++++++++++++++++++++++++++++++++++++++++
src/bluetooth.conf | 1 +
test/test-alert | 180 +++++++++
9 files changed, 1326 insertions(+), 6 deletions(-)
create mode 100644 doc/alert-api.txt
create mode 100644 profiles/alert/manager.c
create mode 100644 profiles/alert/manager.h
create mode 100755 test/test-alert
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH BlueZ v7 7/9] core: Re-connect for ECONNRESET or ECONNABORTED
From: Claudio Takahasi @ 2012-09-27 18:20 UTC (permalink / raw)
To: João Paulo Rechi Vita, linux-bluetooth, Claudio Takahasi
In-Reply-To: <20120927074101.GA9610@x220>
Hi Johan:
On Thu, Sep 27, 2012 at 4:41 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi,
>
> On Tue, Sep 25, 2012, João Paulo Rechi Vita wrote:
>> + /*
>> + * Keep scanning/re-connection active if disconnection reason
>> + * is page timeout, remote user terminated connection or local
>> + * initiated disconnection.
>> + */
>> + if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
>> + adapter_connect_list_add(device_get_adapter(device), device);
>
> Page timeouts have always been reported through EHOSTDOWN so either the
> comment or the code is wrong here.
>
> Johan
The comment is wrong: s/page/connection
Regards,
Claudio
^ permalink raw reply
* [PATCH] ath3k: Added VID/PID for the Gigabyte GC-WB300D Wifi/Bluetooth card
From: Wouter Thielen @ 2012-09-27 15:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann
[-- Attachment #1.1: Type: text/plain, Size: 2269 bytes --]
This card is supplied with the Gigabyte Sniper 3 motherboard (and some
others). I followed the information on
http://wireless.kernel.org/en/users/Drivers/ath3k and confirmed with lsusb
-v that it is using the AR3012 chipset.
(Marcel Holtmann told me to send this to the linux-bluetooth list, with the
output of /sys/kernel/debug/usb/devices attached. You can find
the Bluetooth USB device on line 60 of the usbdevices.txt file.)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index fc2de55..29a713a 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x04CA, 0x3005) },
+ { USB_DEVICE(0x04CA, 0x3006) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0930, 0x0219) },
@@ -103,6 +104,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 654e248..8a9a3e4 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -132,6 +132,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
Signed-off-by: Wouter Thielen <wouter@morannon.org>
[-- Attachment #1.2: Type: text/html, Size: 2971 bytes --]
[-- Attachment #2: usbdevices.txt --]
[-- Type: text/plain, Size: 9500 bytes --]
T: Bus=04 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=5000 MxCh= 4
B: Alloc= 0/800 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 3.00 Cls=09(hub ) Sub=00 Prot=03 MxPS= 9 #Cfgs= 1
P: Vendor=1d6b ProdID=0003 Rev= 3.05
S: Manufacturer=Linux 3.5.0-15-generic xhci_hcd
S: Product=xHCI Host Controller
S: SerialNumber=0000:00:14.0
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
T: Bus=04 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 2 Spd=5000 MxCh= 4
D: Ver= 3.00 Cls=09(hub ) Sub=00 Prot=03 MxPS= 9 #Cfgs= 1
P: Vendor=2109 ProdID=0810 Rev= 3.95
S: Manufacturer=VIA Labs, Inc.
S: Product=4-Port USB 3.0 Hub
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 2mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=13(Int.) MxPS= 2 Ivl=4096ms
T: Bus=04 Lev=01 Prnt=01 Port=03 Cnt=02 Dev#= 3 Spd=5000 MxCh= 4
D: Ver= 3.00 Cls=09(hub ) Sub=00 Prot=03 MxPS= 9 #Cfgs= 1
P: Vendor=2109 ProdID=0810 Rev= 3.95
S: Manufacturer=VIA Labs, Inc.
S: Product=4-Port USB 3.0 Hub
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 2mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=13(Int.) MxPS= 2 Ivl=4096ms
T: Bus=03 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 4
B: Alloc= 0/800 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev= 3.05
S: Manufacturer=Linux 3.5.0-15-generic xhci_hcd
S: Product=xHCI Host Controller
S: SerialNumber=0000:00:14.0
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 2
B: Alloc= 3/800 us ( 0%), #Int= 2, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev= 3.05
S: Manufacturer=Linux 3.5.0-15-generic ehci_hcd
S: Product=EHCI Host Controller
S: SerialNumber=0000:00:1d.0
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 8
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=8087 ProdID=0024 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 2 Ivl=256ms
T: Bus=02 Lev=02 Prnt=02 Port=04 Cnt=01 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=04ca ProdID=3006 Rev= 0.02
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 2
B: Alloc= 8/800 us ( 1%), #Int= 5, #Iso= 3
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev= 3.05
S: Manufacturer=Linux 3.5.0-15-generic ehci_hcd
S: Product=EHCI Host Controller
S: SerialNumber=0000:00:1a.0
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 6
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=8087 ProdID=0024 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 3 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=046d ProdID=0805 Rev= 0.09
S: SerialNumber=A6263690
C:* #Ifs= 4 Cfg#= 1 Atr=80 MxPwr=500mA
A: FirstIf#= 0 IfCount= 2 Cls=0e(video) Sub=03 Prot=00
A: FirstIf#= 2 IfCount= 2 Cls=01(audio) Sub=02 Prot=00
I:* If#= 0 Alt= 0 #EPs= 1 Cls=0e(video) Sub=01 Prot=00 Driver=uvcvideo
E: Ad=87(I) Atr=03(Int.) MxPS= 16 Ivl=16ms
I:* If#= 1 Alt= 0 #EPs= 0 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
I: If#= 1 Alt= 1 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS= 192 Ivl=125us
I: If#= 1 Alt= 2 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS= 384 Ivl=125us
I: If#= 1 Alt= 3 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS= 512 Ivl=125us
I: If#= 1 Alt= 4 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS= 640 Ivl=125us
I: If#= 1 Alt= 5 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS= 800 Ivl=125us
I: If#= 1 Alt= 6 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS= 944 Ivl=125us
I: If#= 1 Alt= 7 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS=1280 Ivl=125us
I: If#= 1 Alt= 8 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS=1600 Ivl=125us
I: If#= 1 Alt= 9 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS=1984 Ivl=125us
I: If#= 1 Alt=10 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS=2688 Ivl=125us
I: If#= 1 Alt=11 #EPs= 1 Cls=0e(video) Sub=02 Prot=00 Driver=uvcvideo
E: Ad=81(I) Atr=05(Isoc) MxPS=3060 Ivl=125us
I:* If#= 2 Alt= 0 #EPs= 0 Cls=01(audio) Sub=01 Prot=00 Driver=snd-usb-audio
I:* If#= 3 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
I: If#= 3 Alt= 1 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=86(I) Atr=05(Isoc) MxPS= 68 Ivl=1ms
I: If#= 3 Alt= 2 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=86(I) Atr=05(Isoc) MxPS= 100 Ivl=1ms
I: If#= 3 Alt= 3 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=86(I) Atr=05(Isoc) MxPS= 132 Ivl=1ms
I: If#= 3 Alt= 4 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=86(I) Atr=05(Isoc) MxPS= 196 Ivl=1ms
T: Bus=01 Lev=02 Prnt=02 Port=04 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=1532 ProdID=0024 Rev= 2.00
S: Manufacturer=Razer
S: Product=Razer Mamba
C:* #Ifs= 2 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=1ms
I:* If#= 1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=01 Driver=usbhid
E: Ad=82(I) Atr=03(Int.) MxPS= 9 Ivl=1ms
T: Bus=01 Lev=02 Prnt=02 Port=05 Cnt=03 Dev#= 5 Spd=480 MxCh= 4
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=058f ProdID=6254 Rev= 1.00
S: Product=USB2.0Hub
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
T: Bus=01 Lev=03 Prnt=05 Port=00 Cnt=01 Dev#= 6 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0d8c ProdID=0001 Rev= 0.10
S: Manufacturer=C-Media INC.
S: Product=USB Audio
C:* #Ifs= 2 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 0 Cls=01(audio) Sub=01 Prot=00 Driver=snd-usb-audio
I: If#= 1 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
I:* If#= 1 Alt= 1 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=06(O) Atr=09(Isoc) MxPS= 192 Ivl=1ms
T: Bus=01 Lev=03 Prnt=05 Port=02 Cnt=02 Dev#= 7 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=046d ProdID=c52b Rev=12.01
S: Manufacturer=Logitech
S: Product=USB Receiver
C:* #Ifs= 3 Cfg#= 1 Atr=a0 MxPwr= 98mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=01 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=8ms
I:* If#= 1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid
E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=2ms
I:* If#= 2 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid
E: Ad=83(I) Atr=03(Int.) MxPS= 32 Ivl=2ms
T: Bus=01 Lev=03 Prnt=05 Port=03 Cnt=03 Dev#= 8 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=058f ProdID=6366 Rev= 1.00
S: Manufacturer=Generic
S: Product=Mass Storage Device
S: SerialNumber=058F0O1111B1
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
^ permalink raw reply related
* [PATCH 5/5] update sbcinfo for msbc
From: Frédéric Dalleau @ 2012-09-27 14:44 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1348757068-31048-1-git-send-email-frederic.dalleau@linux.intel.com>
---
src/sbcinfo.c | 51 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 15 deletions(-)
diff --git a/src/sbcinfo.c b/src/sbcinfo.c
index 8cfb54a..52ca458 100644
--- a/src/sbcinfo.c
+++ b/src/sbcinfo.c
@@ -61,12 +61,11 @@ struct sbc_frame_hdr {
#error "Unknown byte order"
#endif
-static int calc_frame_len(struct sbc_frame_hdr *hdr)
+static int calc_frame_len(struct sbc_frame_hdr *hdr, int nrof_blocks)
{
- int tmp, nrof_subbands, nrof_blocks;
+ int tmp, nrof_subbands;
nrof_subbands = (hdr->subbands + 1) * 4;
- nrof_blocks = (hdr->blocks + 1) * 4;
switch (hdr->channel_mode) {
case 0x00:
@@ -89,13 +88,12 @@ static int calc_frame_len(struct sbc_frame_hdr *hdr)
return (nrof_subbands + ((tmp + 7) / 8));
}
-static double calc_bit_rate(struct sbc_frame_hdr *hdr)
+static double calc_bit_rate(struct sbc_frame_hdr *hdr, int nrof_blocks)
{
- int nrof_subbands, nrof_blocks;
+ int nrof_subbands;
double f;
nrof_subbands = (hdr->subbands + 1) * 4;
- nrof_blocks = (hdr->blocks + 1) * 4;
switch (hdr->sampling_frequency) {
case 0:
@@ -114,7 +112,7 @@ static double calc_bit_rate(struct sbc_frame_hdr *hdr)
return 0;
}
- return ((8 * (calc_frame_len(hdr) + 4) * f) /
+ return ((8 * (calc_frame_len(hdr, nrof_blocks) + 4) * f) /
(nrof_subbands * nrof_blocks));
}
@@ -175,7 +173,7 @@ static int analyze_file(char *filename)
double rate;
int bitpool[SIZE], frame_len[SIZE];
int subbands, blocks, freq, method;
- int n, p1, p2, fd, size, num;
+ int n, p1, p2, fd, size, num, msbc;
ssize_t len;
unsigned int count;
@@ -191,17 +189,30 @@ static int analyze_file(char *filename)
fd = fileno(stdin);
len = __read(fd, &hdr, sizeof(hdr));
- if (len != sizeof(hdr) || hdr.syncword != 0x9c) {
+ if (len != sizeof(hdr) || !(hdr.syncword == 0x9c ||
+ hdr.syncword == 0xad)) {
fprintf(stderr, "Not a SBC audio file\n");
return -1;
}
+ msbc = (hdr.syncword == 0xad) ? 1 : 0;
+
+ if (msbc) {
+ hdr.subbands = 1; /* 8 */
+ hdr.sampling_frequency = 0x00; /* 16000 */
+ hdr.allocation_method = 0; /* Loudness */
+ hdr.bitpool = 26;
+ hdr.channel_mode = 0x00; /* Mono */
+
+ blocks = 15;
+ } else {
+ blocks = (hdr.blocks + 1) * 4;
+ }
subbands = (hdr.subbands + 1) * 4;
- blocks = (hdr.blocks + 1) * 4;
freq = hdr.sampling_frequency;
method = hdr.allocation_method;
- count = calc_frame_len(&hdr);
+ count = calc_frame_len(&hdr, blocks);
bitpool[0] = hdr.bitpool;
frame_len[0] = count + 4;
@@ -213,7 +224,7 @@ static int analyze_file(char *filename)
if (lseek(fd, 0, SEEK_SET) < 0) {
num = 1;
- rate = calc_bit_rate(&hdr);
+ rate = calc_bit_rate(&hdr, blocks);
while (count) {
size = count > sizeof(buf) ? sizeof(buf) : count;
len = __read(fd, buf, size);
@@ -237,14 +248,23 @@ static int analyze_file(char *filename)
if (len == 0)
break;
- if ((size_t) len < sizeof(hdr) || hdr.syncword != 0x9c) {
+ if ((size_t) len < sizeof(hdr) || !(hdr.syncword == 0x9c ||
+ hdr.syncword == 0xad)) {
fprintf(stderr, "Corrupted SBC stream "
"(len %zd syncword 0x%02x)\n",
len, hdr.syncword);
break;
}
- count = calc_frame_len(&hdr);
+ if (msbc) {
+ hdr.subbands = 1; /* 8 */
+ hdr.sampling_frequency = 0x00; /* 16000 */
+ hdr.allocation_method = 0; /* Loudness */
+ hdr.bitpool = 26;
+ hdr.channel_mode = 0x00; /* Mono */
+ }
+
+ count = calc_frame_len(&hdr, blocks);
len = count + 4;
p1 = -1;
@@ -273,10 +293,11 @@ static int analyze_file(char *filename)
count -= len;
}
- rate += calc_bit_rate(&hdr);
+ rate += calc_bit_rate(&hdr, blocks);
num++;
}
+ printf("mSBC \t\t%d\n", msbc);
printf("Subbands\t\t%d\n", subbands);
printf("Block length\t\t%d\n", blocks);
printf("Sampling frequency\t%s\n", freq2str(freq));
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/5] update sbcenc for msbc
From: Frédéric Dalleau @ 2012-09-27 14:44 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1348757068-31048-1-git-send-email-frederic.dalleau@linux.intel.com>
---
src/sbcenc.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/src/sbcenc.c b/src/sbcenc.c
index a723b03..71ad6bb 100644
--- a/src/sbcenc.c
+++ b/src/sbcenc.c
@@ -45,7 +45,7 @@ static int verbose = 0;
static unsigned char input[BUF_SIZE], output[BUF_SIZE + BUF_SIZE / 4];
static void encode(char *filename, int subbands, int bitpool, int joint,
- int dualchannel, int snr, int blocks)
+ int dualchannel, int snr, int blocks, int msbc)
{
struct au_header au_hdr;
sbc_t sbc;
@@ -87,7 +87,7 @@ static void encode(char *filename, int subbands, int bitpool, int joint,
goto done;
}
- sbc_init(&sbc, 0L);
+ sbc_init(&sbc, msbc ? SBC_MSBC : 0L);
switch (BE_INT(au_hdr.sample_rate)) {
case 16000:
@@ -215,6 +215,7 @@ static void usage(void)
printf("Options:\n"
"\t-h, --help Display help\n"
"\t-v, --verbose Verbose mode\n"
+ "\t-m, --msbc mSBC codec\n"
"\t-s, --subbands Number of subbands to use (4 or 8)\n"
"\t-b, --bitpool Bitpool value (default is 32)\n"
"\t-j, --joint Joint stereo\n"
@@ -227,6 +228,7 @@ static void usage(void)
static struct option main_options[] = {
{ "help", 0, 0, 'h' },
{ "verbose", 0, 0, 'v' },
+ { "msbc", 0, 0, 'm' },
{ "subbands", 1, 0, 's' },
{ "bitpool", 1, 0, 'b' },
{ "joint", 0, 0, 'j' },
@@ -239,9 +241,9 @@ static struct option main_options[] = {
int main(int argc, char *argv[])
{
int i, opt, subbands = 8, bitpool = 32, joint = 0, dualchannel = 0;
- int snr = 0, blocks = 16;
+ int snr = 0, blocks = 16, msbc = 0;
- while ((opt = getopt_long(argc, argv, "+hvs:b:jdSB:",
+ while ((opt = getopt_long(argc, argv, "+hmvs:b:jdSB:",
main_options, NULL)) != -1) {
switch(opt) {
case 'h':
@@ -252,6 +254,10 @@ int main(int argc, char *argv[])
verbose = 1;
break;
+ case 'm':
+ msbc = 1;
+ break;
+
case 's':
subbands = atoi(optarg);
if (subbands != 8 && subbands != 4) {
@@ -300,9 +306,18 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (msbc) {
+ subbands = 8;
+ bitpool = 26;
+ joint = 0;
+ dualchannel = 0;
+ snr = 0;
+ blocks = 15;
+ }
+
for (i = 0; i < argc; i++)
encode(argv[i], subbands, bitpool, joint, dualchannel,
- snr, blocks);
+ snr, blocks, msbc);
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/5] update sbcdec for msbc
From: Frédéric Dalleau @ 2012-09-27 14:44 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1348757068-31048-1-git-send-email-frederic.dalleau@linux.intel.com>
---
src/sbcdec.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/sbcdec.c b/src/sbcdec.c
index 0077a82..37d2e98 100644
--- a/src/sbcdec.c
+++ b/src/sbcdec.c
@@ -44,7 +44,7 @@
static int verbose = 0;
-static void decode(char *filename, char *output, int tofile)
+static void decode(char *filename, char *output, int tofile, int msbc)
{
unsigned char buf[BUF_SIZE], *stream;
struct stat st;
@@ -98,7 +98,7 @@ static void decode(char *filename, char *output, int tofile)
goto free;
}
- sbc_init(&sbc, 0L);
+ sbc_init(&sbc, msbc ? SBC_MSBC : 0L);
sbc.endian = SBC_BE;
framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len);
@@ -228,14 +228,16 @@ static void usage(void)
printf("Options:\n"
"\t-h, --help Display help\n"
- "\t-v, --verbose Verbose mode\n"
"\t-d, --device <dsp> Sound device\n"
+ "\t-v, --verbose Verbose mode\n"
+ "\t-m, --msbc mSBC codec\n"
"\t-f, --file <file> Decode to a file\n"
"\n");
}
static struct option main_options[] = {
{ "help", 0, 0, 'h' },
+ { "msbc", 0, 0, 'm' },
{ "device", 1, 0, 'd' },
{ "verbose", 0, 0, 'v' },
{ "file", 1, 0, 'f' },
@@ -246,8 +248,9 @@ int main(int argc, char *argv[])
{
char *output = NULL;
int i, opt, tofile = 0;
+ int msbc = 0;
- while ((opt = getopt_long(argc, argv, "+hvd:f:",
+ while ((opt = getopt_long(argc, argv, "+hmvd:f:",
main_options, NULL)) != -1) {
switch(opt) {
case 'h':
@@ -258,6 +261,10 @@ int main(int argc, char *argv[])
verbose = 1;
break;
+ case 'm':
+ msbc = 1;
+ break;
+
case 'd':
free(output);
output = strdup(optarg);
@@ -285,7 +292,7 @@ int main(int argc, char *argv[])
}
for (i = 0; i < argc; i++)
- decode(argv[i], output ? output : "/dev/dsp", tofile);
+ decode(argv[i], output ? output : "/dev/dsp", tofile, msbc);
free(output);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/5] Add support for mSBC frame header
From: Frédéric Dalleau @ 2012-09-27 14:44 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1348757068-31048-1-git-send-email-frederic.dalleau@linux.intel.com>
mSBC modifies header so that it contains: OxAD 0x00 0x00.
The first bytes allows to distinguish mSBC packets from standard SBC
packets used in A2DP. The two zero bytes are reserved for future definition.
---
sbc/sbc.c | 104 +++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 63 insertions(+), 41 deletions(-)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index 7e4faa0..131755b 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -407,55 +407,71 @@ static int sbc_unpack_frame(sbc_t *sbc, const uint8_t *data,
if (len < 4)
return -1;
- if (data[0] != SBC_SYNCWORD)
- return -2;
-
- frame->frequency = (data[1] >> 6) & 0x03;
+ if (sbc->flags & SBC_MSBC) {
+ if (data[0] != MSBC_SYNCWORD)
+ return -2;
+ if (data[1] != 0)
+ return -5;
+ if (data[2] != 0)
+ return -6;
- frame->block_mode = (data[1] >> 4) & 0x03;
- switch (frame->block_mode) {
- case SBC_BLK_4:
- frame->blocks = 4;
- break;
- case SBC_BLK_8:
- frame->blocks = 8;
- break;
- case SBC_BLK_12:
- frame->blocks = 12;
- break;
- case SBC_BLK_16:
- frame->blocks = 16;
- break;
- }
- if (sbc->flags & SBC_MSBC)
+ frame->frequency = SBC_FREQ_16000;
+ frame->block_mode = SBC_BLK_4;
frame->blocks = MSBC_BLOCKS;
-
- frame->mode = (data[1] >> 2) & 0x03;
- switch (frame->mode) {
- case MONO:
+ frame->allocation = LOUDNESS;
+ frame->mode = MONO;
frame->channels = 1;
- break;
- case DUAL_CHANNEL: /* fall-through */
- case STEREO:
- case JOINT_STEREO:
- frame->channels = 2;
- break;
- }
+ frame->subband_mode = 1;
+ frame->subbands = 8;
+ frame->bitpool = 26;
+ } else {
+ if (data[0] != SBC_SYNCWORD)
+ return -2;
+
+ frame->frequency = (data[1] >> 6) & 0x03;
+ frame->block_mode = (data[1] >> 4) & 0x03;
+ switch (frame->block_mode) {
+ case SBC_BLK_4:
+ frame->blocks = 4;
+ break;
+ case SBC_BLK_8:
+ frame->blocks = 8;
+ break;
+ case SBC_BLK_12:
+ frame->blocks = 12;
+ break;
+ case SBC_BLK_16:
+ frame->blocks = 16;
+ break;
+ }
+
+ frame->mode = (data[1] >> 2) & 0x03;
+ switch (frame->mode) {
+ case MONO:
+ frame->channels = 1;
+ break;
+ case DUAL_CHANNEL: /* fall-through */
+ case STEREO:
+ case JOINT_STEREO:
+ frame->channels = 2;
+ break;
+ }
- frame->allocation = (data[1] >> 1) & 0x01;
+ frame->allocation = (data[1] >> 1) & 0x01;
- frame->subband_mode = (data[1] & 0x01);
- frame->subbands = frame->subband_mode ? 8 : 4;
+ frame->subband_mode = (data[1] & 0x01);
+ frame->subbands = frame->subband_mode ? 8 : 4;
- frame->bitpool = data[2];
+ frame->bitpool = data[2];
- if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
- frame->bitpool > 16 * frame->subbands)
- return -4;
+ if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+ frame->bitpool > 16 * frame->subbands)
+ return -4;
- if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
- frame->bitpool > 32 * frame->subbands)
- return -4;
+ if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+ frame->bitpool > 32 * frame->subbands)
+ return -4;
+ }
/* data[3] is crc, we're checking it later */
@@ -800,6 +816,11 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(sbc_t *sbc,
uint32_t levels[2][8]; /* levels are derived from that */
uint32_t sb_sample_delta[2][8];
+ if (sbc->flags & SBC_MSBC) {
+ data[0] = MSBC_SYNCWORD;
+ data[1] = 0;
+ data[2] = 0;
+ } else {
data[0] = SBC_SYNCWORD;
data[1] = (frame->frequency & 0x03) << 6;
@@ -831,6 +852,7 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(sbc_t *sbc,
if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
frame->bitpool > frame_subbands << 5)
return -5;
+ }
/* Can't fill in crc yet */
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/5] Add msbc encoding and decoding flag
From: Frédéric Dalleau @ 2012-09-27 14:44 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1348757068-31048-1-git-send-email-frederic.dalleau@linux.intel.com>
Also enable 15 blocks support using stdc sbc primitives
---
Makefile.am | 1 +
sbc/sbc.c | 123 +++++++++--------
sbc/sbc.h | 3 +
sbc/sbc_primitives.c | 8 +-
sbc/sbc_primitives.h | 7 +-
sbc/sbc_primitives_stdc.c | 321 +++++++++++++++++++++++++++++++++++++++++++++
sbc/sbc_primitives_stdc.h | 36 +++++
7 files changed, 443 insertions(+), 56 deletions(-)
create mode 100644 sbc/sbc_primitives_stdc.c
create mode 100644 sbc/sbc_primitives_stdc.h
diff --git a/Makefile.am b/Makefile.am
index cad6a3b..75e3a4a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ sbc_headers = sbc/sbc.h
sbc_sources = sbc/sbc.c sbc/sbc_private.h sbc/sbc_math.h sbc/sbc_tables.h \
sbc/sbc_primitives.h sbc/sbc_primitives.c \
+ sbc/sbc_primitives_stdc.h sbc/sbc_primitives_stdc.c \
sbc/sbc_primitives_mmx.h sbc/sbc_primitives_mmx.c \
sbc/sbc_primitives_iwmmxt.h sbc/sbc_primitives_iwmmxt.c \
sbc/sbc_primitives_neon.h sbc/sbc_primitives_neon.c \
diff --git a/sbc/sbc.c b/sbc/sbc.c
index f0c77c7..7e4faa0 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -6,6 +6,7 @@
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
* Copyright (C) 2005-2008 Brad Midgley <bmidgley@xmission.com>
+ * Copyright (C) 2012 Intel Corporation
*
*
* This library is free software; you can redistribute it and/or
@@ -51,6 +52,17 @@
#include "sbc_primitives.h"
#define SBC_SYNCWORD 0x9C
+#define MSBC_SYNCWORD 0xAD
+#define SBC_BLOCKS(sbc, blocks) (((sbc)->flags & SBC_MSBC) \
+ ? MSBC_BLOCKS : (blocks))
+
+#define MSBC_BLOCKMODE SBC_BLK_16
+#define MSBC_BLOCKS 15
+#define MSBC_BITPOOL 26
+#define MSBC_SUBBAND_MODE 1
+#define MSBC_SUBBANDS 8
+#define MSBC_CHANNEL 1
+#define MSBC_ALLOCATION SBC_AM_LOUDNESS
/* This structure contains an unpacked SBC frame.
Yes, there is probably quite some unused space herein */
@@ -373,9 +385,11 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
* -2 Sync byte incorrect
* -3 CRC8 incorrect
* -4 Bitpool value out of bounds
+ * -5 msbc reserved byte 1 not 0
+ * -6 msbc reserved byte 2 not 0
*/
-static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
- size_t len)
+static int sbc_unpack_frame(sbc_t *sbc, const uint8_t *data,
+ struct sbc_frame *frame, size_t len)
{
unsigned int consumed;
/* Will copy the parts of the header that are relevant to crc
@@ -413,6 +427,8 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
frame->blocks = 16;
break;
}
+ if (sbc->flags & SBC_MSBC)
+ frame->blocks = MSBC_BLOCKS;
frame->mode = (data[1] >> 2) & 0x03;
switch (frame->mode) {
@@ -690,13 +706,13 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
for (ch = 0; ch < frame->channels; ch++) {
x = &state->X[ch][state->position - 16 +
frame->blocks * 4];
- for (blk = 0; blk < frame->blocks; blk += 4) {
+ for (blk = 0; blk < frame->blocks; blk += state->inc) {
state->sbc_analyze_4b_4s(
x,
frame->sb_sample_f[blk][ch],
frame->sb_sample_f[blk + 1][ch] -
frame->sb_sample_f[blk][ch]);
- x -= 16;
+ x -= 4 * state->inc;
}
}
return frame->blocks * 4;
@@ -705,13 +721,13 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
for (ch = 0; ch < frame->channels; ch++) {
x = &state->X[ch][state->position - 32 +
frame->blocks * 8];
- for (blk = 0; blk < frame->blocks; blk += 4) {
+ for (blk = 0; blk < frame->blocks; blk += state->inc) {
state->sbc_analyze_4b_8s(
x,
frame->sb_sample_f[blk][ch],
frame->sb_sample_f[blk + 1][ch] -
frame->sb_sample_f[blk][ch]);
- x -= 32;
+ x -= 8 * state->inc;
}
}
return frame->blocks * 8;
@@ -764,10 +780,9 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
* -99 not implemented
*/
-static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
- struct sbc_frame *frame, size_t len,
- int frame_subbands, int frame_channels,
- int joint)
+static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(sbc_t *sbc,
+ uint8_t *data, struct sbc_frame *frame, size_t len,
+ int frame_subbands, int frame_channels, int joint)
{
/* Bitstream writer starts from the fourth byte */
uint8_t *data_ptr = data + 4;
@@ -785,37 +800,37 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
uint32_t levels[2][8]; /* levels are derived from that */
uint32_t sb_sample_delta[2][8];
- data[0] = SBC_SYNCWORD;
+ data[0] = SBC_SYNCWORD;
- data[1] = (frame->frequency & 0x03) << 6;
+ data[1] = (frame->frequency & 0x03) << 6;
- data[1] |= (frame->block_mode & 0x03) << 4;
+ data[1] |= (frame->block_mode & 0x03) << 4;
- data[1] |= (frame->mode & 0x03) << 2;
+ data[1] |= (frame->mode & 0x03) << 2;
- data[1] |= (frame->allocation & 0x01) << 1;
+ data[1] |= (frame->allocation & 0x01) << 1;
- switch (frame_subbands) {
- case 4:
- /* Nothing to do */
- break;
- case 8:
- data[1] |= 0x01;
- break;
- default:
- return -4;
- break;
- }
+ switch (frame_subbands) {
+ case 4:
+ /* Nothing to do */
+ break;
+ case 8:
+ data[1] |= 0x01;
+ break;
+ default:
+ return -4;
+ break;
+ }
- data[2] = frame->bitpool;
+ data[2] = frame->bitpool;
- if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
- frame->bitpool > frame_subbands << 4)
- return -5;
+ if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+ frame->bitpool > frame_subbands << 4)
+ return -5;
- if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
- frame->bitpool > frame_subbands << 5)
- return -5;
+ if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+ frame->bitpool > frame_subbands << 5)
+ return -5;
/* Can't fill in crc yet */
@@ -881,33 +896,33 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
return data_ptr - data;
}
-static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len,
- int joint)
+static ssize_t sbc_pack_frame(sbc_t *sbc, uint8_t *data,
+ struct sbc_frame *frame, size_t len, int joint)
{
if (frame->subbands == 4) {
if (frame->channels == 1)
return sbc_pack_frame_internal(
- data, frame, len, 4, 1, joint);
+ sbc, data, frame, len, 4, 1, joint);
else
return sbc_pack_frame_internal(
- data, frame, len, 4, 2, joint);
+ sbc, data, frame, len, 4, 2, joint);
} else {
if (frame->channels == 1)
return sbc_pack_frame_internal(
- data, frame, len, 8, 1, joint);
+ sbc, data, frame, len, 8, 1, joint);
else
return sbc_pack_frame_internal(
- data, frame, len, 8, 2, joint);
+ sbc, data, frame, len, 8, 2, joint);
}
}
-static void sbc_encoder_init(struct sbc_encoder_state *state,
+static void sbc_encoder_init(int msbc, struct sbc_encoder_state *state,
const struct sbc_frame *frame)
{
memset(&state->X, 0, sizeof(state->X));
state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
- sbc_init_primitives(state);
+ sbc_init_primitives(msbc, state);
}
struct sbc_priv {
@@ -919,6 +934,7 @@ struct sbc_priv {
static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
{
+ sbc->flags = flags;
sbc->frequency = SBC_FREQ_44100;
sbc->mode = SBC_MODE_STEREO;
sbc->subbands = SBC_SB_8;
@@ -971,7 +987,7 @@ SBC_EXPORT ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
priv = sbc->priv;
- framelen = sbc_unpack_frame(input, &priv->frame, input_len);
+ framelen = sbc_unpack_frame(sbc, input, &priv->frame, input_len);
if (!priv->init) {
sbc_decoder_init(&priv->dec_state, &priv->frame);
@@ -980,7 +996,7 @@ SBC_EXPORT ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
sbc->frequency = priv->frame.frequency;
sbc->mode = priv->frame.mode;
sbc->subbands = priv->frame.subband_mode;
- sbc->blocks = priv->frame.block_mode;
+ sbc->blocks = SBC_BLOCKS(sbc, priv->frame.block_mode);
sbc->allocation = priv->frame.allocation;
sbc->bitpool = priv->frame.bitpool;
@@ -1054,12 +1070,13 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
priv->frame.subband_mode = sbc->subbands;
priv->frame.subbands = sbc->subbands ? 8 : 4;
priv->frame.block_mode = sbc->blocks;
- priv->frame.blocks = 4 + (sbc->blocks * 4);
+ priv->frame.blocks = SBC_BLOCKS(sbc, 4 + (sbc->blocks * 4));
priv->frame.bitpool = sbc->bitpool;
priv->frame.codesize = sbc_get_codesize(sbc);
priv->frame.length = sbc_get_frame_length(sbc);
- sbc_encoder_init(&priv->enc_state, &priv->frame);
+ sbc_encoder_init(sbc->flags & SBC_MSBC,
+ &priv->enc_state, &priv->frame);
priv->init = 1;
} else if (priv->frame.bitpool != sbc->bitpool) {
priv->frame.length = sbc_get_frame_length(sbc);
@@ -1102,13 +1119,15 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
int j = priv->enc_state.sbc_calc_scalefactors_j(
priv->frame.sb_sample_f, priv->frame.scale_factor,
priv->frame.blocks, priv->frame.subbands);
- framelen = sbc_pack_frame(output, &priv->frame, output_len, j);
+ framelen = sbc_pack_frame(sbc, output,
+ &priv->frame, output_len, j);
} else {
priv->enc_state.sbc_calc_scalefactors(
priv->frame.sb_sample_f, priv->frame.scale_factor,
priv->frame.blocks, priv->frame.channels,
priv->frame.subbands);
- framelen = sbc_pack_frame(output, &priv->frame, output_len, 0);
+ framelen = sbc_pack_frame(sbc, output,
+ &priv->frame, output_len, 0);
}
if (written)
@@ -1138,7 +1157,7 @@ SBC_EXPORT size_t sbc_get_frame_length(sbc_t *sbc)
return priv->frame.length;
subbands = sbc->subbands ? 8 : 4;
- blocks = 4 + (sbc->blocks * 4);
+ blocks = SBC_BLOCKS(sbc, 4 + (sbc->blocks * 4));
channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
bitpool = sbc->bitpool;
@@ -1162,10 +1181,10 @@ SBC_EXPORT unsigned sbc_get_frame_duration(sbc_t *sbc)
priv = sbc->priv;
if (!priv->init) {
subbands = sbc->subbands ? 8 : 4;
- blocks = 4 + (sbc->blocks * 4);
+ blocks = SBC_BLOCKS(sbc, 4 + (sbc->blocks * 4));
} else {
subbands = priv->frame.subbands;
- blocks = priv->frame.blocks;
+ blocks = SBC_BLOCKS(sbc, priv->frame.blocks);
}
switch (sbc->frequency) {
@@ -1199,11 +1218,11 @@ SBC_EXPORT size_t sbc_get_codesize(sbc_t *sbc)
priv = sbc->priv;
if (!priv->init) {
subbands = sbc->subbands ? 8 : 4;
- blocks = 4 + (sbc->blocks * 4);
+ blocks = SBC_BLOCKS(sbc, 4 + (sbc->blocks * 4));
channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
} else {
subbands = priv->frame.subbands;
- blocks = priv->frame.blocks;
+ blocks = SBC_BLOCKS(sbc, priv->frame.blocks);
channels = priv->frame.channels;
}
diff --git a/sbc/sbc.h b/sbc/sbc.h
index bbd45da..3511119 100644
--- a/sbc/sbc.h
+++ b/sbc/sbc.h
@@ -64,6 +64,9 @@ extern "C" {
#define SBC_LE 0x00
#define SBC_BE 0x01
+/* Additional features */
+#define SBC_MSBC 0x01
+
struct sbc_struct {
unsigned long flags;
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index ad780d0..1ed61d1 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -32,6 +32,7 @@
#include "sbc_tables.h"
#include "sbc_primitives.h"
+#include "sbc_primitives_stdc.h"
#include "sbc_primitives_mmx.h"
#include "sbc_primitives_iwmmxt.h"
#include "sbc_primitives_neon.h"
@@ -519,8 +520,10 @@ static int sbc_calc_scalefactors_j(
/*
* Detect CPU features and setup function pointers
*/
-void sbc_init_primitives(struct sbc_encoder_state *state)
+void sbc_init_primitives(int msbc, struct sbc_encoder_state *state)
{
+ state->inc = 4;
+
/* Default implementation for analyze functions */
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_simd;
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
@@ -551,4 +554,7 @@ void sbc_init_primitives(struct sbc_encoder_state *state)
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
sbc_init_primitives_neon(state);
#endif
+
+ if (msbc)
+ sbc_init_primitives_stdc(state);
}
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index 17ad4f7..22778ff 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -38,12 +38,13 @@
struct sbc_encoder_state {
int position;
+ int inc;
int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
/* Polyphase analysis filter for 4 subbands configuration,
- * it handles 4 blocks at once */
+ * it handles "inc" blocks at once */
void (*sbc_analyze_4b_4s)(int16_t *x, int32_t *out, int out_stride);
/* Polyphase analysis filter for 8 subbands configuration,
- * it handles 4 blocks at once */
+ * it handles "inc" blocks at once */
void (*sbc_analyze_4b_8s)(int16_t *x, int32_t *out, int out_stride);
/* Process input data (deinterleave, endian conversion, reordering),
* depending on the number of subbands and input data byte order */
@@ -75,6 +76,6 @@ struct sbc_encoder_state {
* of SBC codec. Best implementation is selected based on target CPU
* capabilities.
*/
-void sbc_init_primitives(struct sbc_encoder_state *encoder_state);
+void sbc_init_primitives(int msbc, struct sbc_encoder_state *encoder_state);
#endif
diff --git a/sbc/sbc_primitives_stdc.c b/sbc/sbc_primitives_stdc.c
new file mode 100644
index 0000000..02ad8eb
--- /dev/null
+++ b/sbc/sbc_primitives_stdc.c
@@ -0,0 +1,321 @@
+/*
+ *
+ * Bluetooth low-complexity, subband codec (SBC) library
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
+ * Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
+ * Copyright (C) 2012 Intel Corporation
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include "sbc.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc_primitives.h"
+#include "sbc_primitives_stdc.h"
+
+/*
+ * stdc optimizations
+ */
+
+#ifdef SBC_BUILD_WITH_STDC_SUPPORT
+
+/*
+ * A standard C code of analysis filter.
+ */
+static inline void sbc_analyze_four_stdc(const int16_t *in, int32_t *out)
+{
+ FIXED_A t1[4];
+ FIXED_T t2[4];
+ int i = 0, hop = 0;
+
+ /* rounding coefficient */
+ t1[0] = t1[1] = t1[2] = t1[3] =
+ (FIXED_A) 1 << (SBC_PROTO_FIXED4_SCALE - 1);
+
+ /* low pass polyphase filter */
+ for (hop = 0; hop < 40; hop += 8) {
+ t1[0] += (FIXED_A) in[hop] * _sbc_proto_fixed4[hop];
+ t1[1] += (FIXED_A) in[hop + 1] * _sbc_proto_fixed4[hop + 1];
+ t1[2] += (FIXED_A) in[hop + 2] * _sbc_proto_fixed4[hop + 2];
+ t1[1] += (FIXED_A) in[hop + 3] * _sbc_proto_fixed4[hop + 3];
+ t1[0] += (FIXED_A) in[hop + 4] * _sbc_proto_fixed4[hop + 4];
+ t1[3] += (FIXED_A) in[hop + 5] * _sbc_proto_fixed4[hop + 5];
+ t1[3] += (FIXED_A) in[hop + 7] * _sbc_proto_fixed4[hop + 7];
+ }
+
+ /* scaling */
+ t2[0] = t1[0] >> SBC_PROTO_FIXED4_SCALE;
+ t2[1] = t1[1] >> SBC_PROTO_FIXED4_SCALE;
+ t2[2] = t1[2] >> SBC_PROTO_FIXED4_SCALE;
+ t2[3] = t1[3] >> SBC_PROTO_FIXED4_SCALE;
+
+ /* do the cos transform */
+ for (i = 0, hop = 0; i < 4; hop += 8, i++) {
+ out[i] = ((FIXED_A) t2[0] * cos_table_fixed_4[0 + hop] +
+ (FIXED_A) t2[1] * cos_table_fixed_4[1 + hop] +
+ (FIXED_A) t2[2] * cos_table_fixed_4[2 + hop] +
+ (FIXED_A) t2[3] * cos_table_fixed_4[5 + hop]) >>
+ (SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
+ }
+}
+
+static inline void sbc_analyze_eight_stdc(const int16_t *in, int32_t *out)
+{
+ FIXED_A t1[8];
+ FIXED_T t2[8];
+ int i, hop;
+
+ /* rounding coefficient */
+ t1[0] = t1[1] = t1[2] = t1[3] = t1[4] = t1[5] = t1[6] = t1[7] =
+ (FIXED_A) 1 << (SBC_PROTO_FIXED8_SCALE-1);
+
+ /* low pass polyphase filter */
+ for (hop = 0; hop < 80; hop += 16) {
+ t1[0] += (FIXED_A) in[hop] * _sbc_proto_fixed8[hop];
+ t1[1] += (FIXED_A) in[hop + 1] * _sbc_proto_fixed8[hop + 1];
+ t1[2] += (FIXED_A) in[hop + 2] * _sbc_proto_fixed8[hop + 2];
+ t1[3] += (FIXED_A) in[hop + 3] * _sbc_proto_fixed8[hop + 3];
+ t1[4] += (FIXED_A) in[hop + 4] * _sbc_proto_fixed8[hop + 4];
+ t1[3] += (FIXED_A) in[hop + 5] * _sbc_proto_fixed8[hop + 5];
+ t1[2] += (FIXED_A) in[hop + 6] * _sbc_proto_fixed8[hop + 6];
+ t1[1] += (FIXED_A) in[hop + 7] * _sbc_proto_fixed8[hop + 7];
+ t1[0] += (FIXED_A) in[hop + 8] * _sbc_proto_fixed8[hop + 8];
+ t1[5] += (FIXED_A) in[hop + 9] * _sbc_proto_fixed8[hop + 9];
+ t1[6] += (FIXED_A) in[hop + 10] * _sbc_proto_fixed8[hop + 10];
+ t1[7] += (FIXED_A) in[hop + 11] * _sbc_proto_fixed8[hop + 11];
+ t1[7] += (FIXED_A) in[hop + 13] * _sbc_proto_fixed8[hop + 13];
+ t1[6] += (FIXED_A) in[hop + 14] * _sbc_proto_fixed8[hop + 14];
+ t1[5] += (FIXED_A) in[hop + 15] * _sbc_proto_fixed8[hop + 15];
+ }
+
+ /* scaling */
+ t2[0] = t1[0] >> SBC_PROTO_FIXED8_SCALE;
+ t2[1] = t1[1] >> SBC_PROTO_FIXED8_SCALE;
+ t2[2] = t1[2] >> SBC_PROTO_FIXED8_SCALE;
+ t2[3] = t1[3] >> SBC_PROTO_FIXED8_SCALE;
+ t2[4] = t1[4] >> SBC_PROTO_FIXED8_SCALE;
+ t2[5] = t1[5] >> SBC_PROTO_FIXED8_SCALE;
+ t2[6] = t1[6] >> SBC_PROTO_FIXED8_SCALE;
+ t2[7] = t1[7] >> SBC_PROTO_FIXED8_SCALE;
+
+ /* do the cos transform */
+ for (i = 0, hop = 0; i < 8; hop += 16, i++) {
+ out[i] = ((FIXED_A) t2[0] * cos_table_fixed_8[0 + hop] +
+ (FIXED_A) t2[1] * cos_table_fixed_8[1 + hop] +
+ (FIXED_A) t2[2] * cos_table_fixed_8[2 + hop] +
+ (FIXED_A) t2[3] * cos_table_fixed_8[3 + hop] +
+ (FIXED_A) t2[4] * cos_table_fixed_8[4 + hop] +
+ (FIXED_A) t2[5] * cos_table_fixed_8[9 + hop] +
+ (FIXED_A) t2[6] * cos_table_fixed_8[10 + hop] +
+ (FIXED_A) t2[7] * cos_table_fixed_8[11 + hop]) >>
+ (SBC_COS_TABLE_FIXED8_SCALE - SCALE_OUT_BITS);
+ }
+}
+
+static inline void sbc_analyze_4b_4s_stdc(int16_t *x, int32_t *out,
+ int out_stride)
+{
+ /* Analyze blocks */
+ sbc_analyze_four_stdc(x + 0, out);
+}
+
+static inline void sbc_analyze_4b_8s_stdc(int16_t *x, int32_t *out,
+ int out_stride)
+{
+ /* Analyze blocks */
+ sbc_analyze_eight_stdc(x + 0, out);
+}
+
+static inline int16_t unaligned16_be(const uint8_t *ptr)
+{
+ return (int16_t) ((ptr[0] << 8) | ptr[1]);
+}
+
+static inline int16_t unaligned16_le(const uint8_t *ptr)
+{
+ return (int16_t) (ptr[0] | (ptr[1] << 8));
+}
+
+/*
+ * Internal helper functions for input data processing. In order to get
+ * optimal performance, it is important to have "nsamples", "nchannels"
+ * and "big_endian" arguments used with this inline function as compile
+ * time constants.
+ */
+
+static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s4_stdc(
+ int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels, int big_endian)
+{
+ /* handle X buffer wraparound */
+ if (position < nsamples) {
+ if (nchannels > 0)
+ memcpy(&X[0][SBC_X_BUFFER_SIZE - 40], &X[0][position],
+ 36 * sizeof(int16_t));
+ if (nchannels > 1)
+ memcpy(&X[1][SBC_X_BUFFER_SIZE - 40], &X[1][position],
+ 36 * sizeof(int16_t));
+ position = SBC_X_BUFFER_SIZE - 40;
+ }
+
+ #define PCM(i) (big_endian ? \
+ unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
+
+ /* copy audio samples */
+ while ((nsamples -= 1) >= 0) {
+ position -= 1;
+ if (nchannels > 0) {
+ int16_t *x = &X[0][position];
+ x[0] = PCM(0 + 0 * nchannels);
+ }
+ if (nchannels > 1) {
+ int16_t *x = &X[1][position];
+ x[1] = PCM(1 + 0 * nchannels);
+ }
+ pcm += 2 * nchannels;
+ }
+
+
+ #undef PCM
+
+ return position;
+}
+
+
+static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_stdc(
+ int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels, int big_endian)
+{
+ /* handle X buffer wraparound */
+ if (position < nsamples) {
+ if (nchannels > 0)
+ memcpy(&X[0][SBC_X_BUFFER_SIZE - 72], &X[0][position],
+ 72 * sizeof(int16_t));
+ if (nchannels > 1)
+ memcpy(&X[1][SBC_X_BUFFER_SIZE - 72], &X[1][position],
+ 72 * sizeof(int16_t));
+ position = SBC_X_BUFFER_SIZE - 72;
+ }
+
+ #define PCM(i) (big_endian ? \
+ unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
+
+ /* copy audio samples */
+ while ((nsamples -= 1) >= 0) {
+ position -= 1;
+ if (nchannels > 0) {
+ int16_t *x = &X[0][position];
+ x[0] = PCM(0 + 0 * nchannels);
+ }
+ if (nchannels > 1) {
+ int16_t *x = &X[1][position];
+ x[1] = PCM(1 + 0 * nchannels);
+ }
+ pcm += 2 * nchannels;
+ }
+
+ #undef PCM
+ return position;
+}
+
+/*
+ * Input data processing functions. The data is endian converted if needed,
+ * channels are deintrleaved and audio samples are reordered for use in
+ * SIMD-friendly analysis filter function. The results are put into "X"
+ * array, getting appended to the previous data (or it is better to say
+ * prepended, as the buffer is filled from top to bottom). Old data is
+ * discarded when neededed, but availability of (10 * nrof_subbands)
+ * contiguous samples is always guaranteed for the input to the analysis
+ * filter. This is achieved by copying a sufficient part of old data
+ * to the top of the buffer on buffer wraparound.
+ */
+
+static int sbc_enc_process_input_4s_le_stdc(int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ if (nchannels > 1)
+ return sbc_encoder_process_input_s4_stdc(
+ position, pcm, X, nsamples, 2, 0);
+ else
+ return sbc_encoder_process_input_s4_stdc(
+ position, pcm, X, nsamples, 1, 0);
+}
+
+static int sbc_enc_process_input_4s_be_stdc(int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ if (nchannels > 1)
+ return sbc_encoder_process_input_s4_stdc(
+ position, pcm, X, nsamples, 2, 1);
+ else
+ return sbc_encoder_process_input_s4_stdc(
+ position, pcm, X, nsamples, 1, 1);
+}
+
+static int sbc_enc_process_input_8s_le_stdc(int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ if (nchannels > 1)
+ return sbc_encoder_process_input_s8_stdc(
+ position, pcm, X, nsamples, 2, 0);
+ else
+ return sbc_encoder_process_input_s8_stdc(
+ position, pcm, X, nsamples, 1, 0);
+}
+
+static int sbc_enc_process_input_8s_be_stdc(int position,
+ const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
+ int nsamples, int nchannels)
+{
+ if (nchannels > 1)
+ return sbc_encoder_process_input_s8_stdc(
+ position, pcm, X, nsamples, 2, 1);
+ else
+ return sbc_encoder_process_input_s8_stdc(
+ position, pcm, X, nsamples, 1, 1);
+}
+
+
+void sbc_init_primitives_stdc(struct sbc_encoder_state *state)
+{
+ state->inc = 1;
+ state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_stdc;
+ state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_stdc;
+
+ /* Default implementation for input reordering / deinterleaving */
+ state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le_stdc;
+ state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be_stdc;
+ state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le_stdc;
+ state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be_stdc;
+
+ state->implementation_info = "stdc";
+}
+
+#endif
diff --git a/sbc/sbc_primitives_stdc.h b/sbc/sbc_primitives_stdc.h
new file mode 100644
index 0000000..e313047
--- /dev/null
+++ b/sbc/sbc_primitives_stdc.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Bluetooth low-complexity, subband codec (SBC) library
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
+ * Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __SBC_PRIMITIVES_STDC_H
+#define __SBC_PRIMITIVES_STDC_H
+
+#include "sbc_primitives.h"
+
+#define SBC_BUILD_WITH_STDC_SUPPORT
+
+void sbc_init_primitives_stdc(struct sbc_encoder_state *encoder_state);
+
+#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/5] mSBC tests
From: Frédéric Dalleau @ 2012-09-27 14:44 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Frédéric Dalleau
Hi folks,
I wanted to know more about mSBC and I look into the spec and saw it was just
a set of settings for SBC. So I tried to exercise them using sbcenc and sbcdec
and found it wasn't possible, I ended modifying SBC library and now it should
be possible to use mSBC settings.
Using 15 block doesn't work using SIMD processing because of data
reordering so I recalled some legacy C code from an older release
(sbc_analyse_eight) and put in a separate primitives file.
Work done from the spec, not tested with any reference encoder.
How to use:
sample.au should be an .au audio file 16000hz 16bits 1 channel pcm.
$ src/sbcenc -m -b26 -B16 -s8 sample.au > sample.au.msbc
$ src/sbcinfo sample.au.msbc
$ src/sbcdec -m -f sample.au.msbc.au sample.au.msbc
$ mplayer sample.au.msbc.au
Note sure there is any application yet but I thought I should share.
Regards,
Frederic
Frédéric Dalleau (5):
Add msbc encoding and decoding flag
Add support for mSBC frame header
update sbcdec for msbc
update sbcenc for msbc
update sbcinfo for msbc
Makefile.am | 1 +
sbc/sbc.c | 227 +++++++++++++++++++-------------
sbc/sbc.h | 3 +
sbc/sbc_primitives.c | 8 +-
sbc/sbc_primitives.h | 7 +-
sbc/sbc_primitives_stdc.c | 321 +++++++++++++++++++++++++++++++++++++++++++++
sbc/sbc_primitives_stdc.h | 36 +++++
src/sbcdec.c | 17 ++-
src/sbcenc.c | 25 +++-
src/sbcinfo.c | 51 ++++---
10 files changed, 574 insertions(+), 122 deletions(-)
create mode 100644 sbc/sbc_primitives_stdc.c
create mode 100644 sbc/sbc_primitives_stdc.h
--
1.7.9.5
^ permalink raw reply
* [PATCHv7 19/19] Bluetooth: AMP: Handle Accept phylink command status evt
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving HCI Command Status event for Accept Physical Link
execute HCI Write Remote AMP Assoc with data saved from A2MP Create
Physical Link Request.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 1 +
net/bluetooth/a2mp.c | 32 ++++++++++++++++++++++++++++++++
net/bluetooth/amp.c | 2 +-
net/bluetooth/hci_event.c | 20 ++++++++++++++++++++
4 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 1b06d7b..b1e5490 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -25,6 +25,7 @@ struct amp_ctrl {
};
int amp_ctrl_put(struct amp_ctrl *ctrl);
+void amp_ctrl_get(struct amp_ctrl *ctrl);
struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr);
struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
void amp_ctrl_list_flush(struct amp_mgr *mgr);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index dbfdbbb..47565d2 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -438,6 +438,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_physlink_rsp rsp;
struct hci_dev *hdev;
struct hci_conn *hcon;
+ struct amp_ctrl *ctrl;
if (le16_to_cpu(hdr->len) < sizeof(*req))
return -EINVAL;
@@ -453,6 +454,37 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
goto send_rsp;
}
+ ctrl = amp_ctrl_lookup(mgr, rsp.remote_id);
+ if (!ctrl) {
+ ctrl = amp_ctrl_add(mgr);
+ if (ctrl) {
+ amp_ctrl_get(ctrl);
+ } else {
+ rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+ goto send_rsp;
+ }
+ }
+
+ if (ctrl) {
+ u8 *assoc, assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
+
+ ctrl->id = rsp.remote_id;
+
+ assoc = kzalloc(assoc_len, GFP_KERNEL);
+ if (!assoc) {
+ amp_ctrl_put(ctrl);
+ return -ENOMEM;
+ }
+
+ memcpy(assoc, req->amp_assoc, assoc_len);
+ ctrl->assoc = assoc;
+ ctrl->assoc_len = assoc_len;
+ ctrl->assoc_rem_len = assoc_len;
+ ctrl->assoc_len_so_far = 0;
+
+ amp_ctrl_put(ctrl);
+ }
+
hcon = phylink_add(hdev, mgr, req->local_id);
if (hcon) {
amp_accept_phylink(hdev, mgr, hcon);
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 845e430..5dab2d1 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -19,7 +19,7 @@
#include <crypto/hash.h>
/* Remote AMP Controllers interface */
-static void amp_ctrl_get(struct amp_ctrl *ctrl)
+void amp_ctrl_get(struct amp_ctrl *ctrl)
{
BT_DBG("ctrl %p orig refcnt %d", ctrl,
atomic_read(&ctrl->kref.refcount));
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8f1eccf..65f66bf 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1728,6 +1728,22 @@ static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
amp_write_remote_assoc(hdev, cp->phy_handle);
}
+static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
+{
+ struct hci_cp_accept_phy_link *cp;
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
+ if (!cp)
+ return;
+
+ amp_write_remote_assoc(hdev, cp->phy_handle);
+}
+
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -2550,6 +2566,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_create_phylink(hdev, ev->status);
break;
+ case HCI_OP_ACCEPT_PHY_LINK:
+ hci_cs_accept_phylink(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 18/19] Bluetooth: AMP: Accept Physical Link
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Create Physical Link message execute HCI
Accept Physical Link command to AMP controller.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 2 ++
net/bluetooth/a2mp.c | 5 +----
net/bluetooth/amp.c | 19 +++++++++++++++++++
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 70496c0..1b06d7b 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -41,6 +41,8 @@ void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
struct hci_conn *hcon);
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
struct hci_conn *hcon);
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon);
void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 375a67f..dbfdbbb 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -453,12 +453,9 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
goto send_rsp;
}
- /* TODO process physlink create */
-
hcon = phylink_add(hdev, mgr, req->local_id);
if (hcon) {
- BT_DBG("hcon %p", hcon);
-
+ amp_accept_phylink(hdev, mgr, hcon);
rsp.status = A2MP_STATUS_SUCCESS;
} else {
rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 4f7b264..845e430 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -346,3 +346,22 @@ void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
}
+
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_accept_phy_link cp;
+
+ cp.phy_handle = hcon->handle;
+
+ BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+ hcon->handle);
+
+ if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+ &cp.key_type)) {
+ BT_DBG("Cannot create link key");
+ return;
+ }
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 17/19] Bluetooth: AMP: Process Chan Selected event
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Channel Selected event indicates that link information data is available.
Read it with Read Local AMP Assoc command. The data shall be sent in the
A2MP Create Physical Link Request.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/a2mp.h | 3 +++
include/net/bluetooth/amp.h | 2 ++
include/net/bluetooth/l2cap.h | 2 ++
net/bluetooth/a2mp.c | 41 ++++++++++++++++++++++++++++++++++++++++-
net/bluetooth/amp.c | 15 +++++++++++++++
net/bluetooth/hci_event.c | 21 +++++++++++++++++++++
6 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 9fda7c9..e776ab2 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -22,6 +22,7 @@
enum amp_mgr_state {
READ_LOC_AMP_INFO,
READ_LOC_AMP_ASSOC,
+ READ_LOC_AMP_ASSOC_FINAL,
};
struct amp_mgr {
@@ -134,6 +135,7 @@ extern struct mutex amp_mgr_list_lock;
void amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
+u8 __next_ident(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
@@ -141,5 +143,6 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
void a2mp_discover_amp(struct l2cap_chan *chan);
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 8f80329..70496c0 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -37,6 +37,8 @@ int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+ struct hci_conn *hcon);
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
struct hci_conn *hcon);
void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0967f9e..ab58b81 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -508,6 +508,8 @@ struct l2cap_chan {
__u32 remote_acc_lat;
__u32 remote_flush_to;
+ __u8 ctrl_id;
+
struct delayed_work chan_timer;
struct delayed_work retrans_timer;
struct delayed_work monitor_timer;
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 28d1246..375a67f 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -67,7 +67,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
kfree(cmd);
}
-static u8 __next_ident(struct amp_mgr *mgr)
+u8 __next_ident(struct amp_mgr *mgr)
{
if (++mgr->ident == 0)
mgr->ident = 1;
@@ -420,6 +420,8 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
+ mgr->bredr_chan->ctrl_id = rsp->id;
+
amp_create_phylink(hdev, mgr, hcon);
done:
@@ -876,6 +878,43 @@ void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
kfree(rsp);
}
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
+{
+ struct amp_mgr *mgr;
+ struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+ struct a2mp_physlink_req *req;
+ struct l2cap_chan *bredr_chan;
+ size_t len;
+
+ mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
+ if (!mgr)
+ return;
+
+ len = sizeof(*req) + loc_assoc->len;
+
+ BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
+
+ req = kzalloc(len, GFP_KERNEL);
+ if (!req) {
+ amp_mgr_put(mgr);
+ return;
+ }
+
+ bredr_chan = mgr->bredr_chan;
+ if (!bredr_chan)
+ goto clean;
+
+ req->local_id = hdev->id;
+ req->remote_id = bredr_chan->ctrl_id;
+ memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
+
+ a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
+
+clean:
+ amp_mgr_put(mgr);
+ kfree(req);
+}
+
void a2mp_discover_amp(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 5895ad0..4f7b264 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -233,6 +233,21 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
}
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_read_local_amp_assoc cp;
+ struct amp_mgr *mgr = hcon->amp_mgr;
+
+ cp.phy_handle = hcon->handle;
+ cp.len_so_far = cpu_to_le16(0);
+ cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+
+ mgr->state = READ_LOC_AMP_ASSOC_FINAL;
+
+ /* Read Local AMP Assoc final link information data */
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+}
/* Write AMP Assoc data fragments, returns true with last fragment written*/
static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2c7e27a..8f1eccf 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -901,6 +901,7 @@ static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
a2mp_rsp:
/* Send A2MP Rsp when all fragments are received */
a2mp_send_getampassoc_rsp(hdev, rp->status);
+ a2mp_send_create_phy_link_req(hdev, rp->status);
}
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
@@ -3640,6 +3641,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
}
}
+static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_ev_channel_selected *ev = (void *) skb->data;
+ struct hci_conn *hcon;
+
+ BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+
+ skb_pull(skb, sizeof(*ev));
+
+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+ if (!hcon)
+ return;
+
+ amp_read_loc_assoc_final_data(hdev, hcon);
+}
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
@@ -3804,6 +3821,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_meta_evt(hdev, skb);
break;
+ case HCI_EV_CHANNEL_SELECTED:
+ hci_chan_selected_evt(hdev, skb);
+ break;
+
case HCI_EV_REMOTE_OOB_DATA_REQUEST:
hci_remote_oob_data_request_evt(hdev, skb);
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 16/19] Bluetooth: A2MP: Add fallback to normal l2cap init sequence
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When there is no remote AMP controller found fallback to normal
L2CAP sequence.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/a2mp.c | 28 ++++++++++++++++++++++++++++
net/bluetooth/l2cap_core.c | 2 +-
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index aba830f..0967f9e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -769,5 +769,6 @@ int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
#endif /* __L2CAP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 773e8fc..28d1246 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -180,6 +180,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
u16 len = le16_to_cpu(hdr->len);
struct a2mp_cl *cl;
u16 ext_feat;
+ bool found = false;
if (len < sizeof(*rsp))
return -EINVAL;
@@ -210,6 +211,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) {
struct a2mp_info_req req;
+ found = true;
req.id = cl->id;
a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
sizeof(req), &req);
@@ -219,6 +221,32 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
cl = (void *) skb_pull(skb, sizeof(*cl));
}
+ /* Fall back to L2CAP init sequence */
+ if (!found) {
+ struct l2cap_conn *conn = mgr->l2cap_conn;
+ struct l2cap_chan *chan;
+
+ mutex_lock(&conn->chan_lock);
+
+ list_for_each_entry(chan, &conn->chan_l, list) {
+
+ BT_DBG("chan %p state %s", chan,
+ state_to_string(chan->state));
+
+ if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
+ continue;
+
+ l2cap_chan_lock(chan);
+
+ if (chan->state == BT_CONNECT)
+ l2cap_send_conn_req(chan);
+
+ l2cap_chan_unlock(chan);
+ }
+
+ mutex_unlock(&conn->chan_lock);
+ }
+
return 0;
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 0dc3a98..b4e707b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -958,7 +958,7 @@ static bool __amp_capable(struct l2cap_chan *chan)
return false;
}
-static void l2cap_send_conn_req(struct l2cap_chan *chan)
+void l2cap_send_conn_req(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
struct l2cap_conn_req req;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 15/19] Bluetooth: AMP: Write remote AMP Assoc
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving HCI Command Status after HCI Create Physical Link
execute HCI Write Remote AMP Assoc command to AMP controller.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 2 +
include/net/bluetooth/hci_core.h | 2 +
net/bluetooth/amp.c | 80 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 29 ++++++++++++++
4 files changed, 113 insertions(+)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index cadb3d0..8f80329 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -39,5 +39,7 @@ void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
struct hci_conn *hcon);
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
#endif /* __AMP_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 464eae3..ea1f934 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -127,6 +127,8 @@ struct le_scan_params {
struct amp_assoc {
__u16 len;
__u16 offset;
+ __u16 rem_len;
+ __u16 len_so_far;
__u8 data[HCI_MAX_AMP_ASSOC_SIZE];
};
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 657ec73..5895ad0 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -233,6 +233,86 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
}
+
+/* Write AMP Assoc data fragments, returns true with last fragment written*/
+static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_write_remote_amp_assoc *cp;
+ struct amp_mgr *mgr = hcon->amp_mgr;
+ struct amp_ctrl *ctrl;
+ u16 frag_len, len;
+
+ ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
+ if (!ctrl)
+ return false;
+
+ if (!ctrl->assoc_rem_len) {
+ BT_DBG("all fragments are written");
+ ctrl->assoc_rem_len = ctrl->assoc_len;
+ ctrl->assoc_len_so_far = 0;
+
+ amp_ctrl_put(ctrl);
+ return true;
+ }
+
+ frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
+ len = frag_len + sizeof(*cp);
+
+ cp = kzalloc(len, GFP_KERNEL);
+ if (!cp) {
+ amp_ctrl_put(ctrl);
+ return false;
+ }
+
+ BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
+ hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
+
+ cp->phy_handle = hcon->handle;
+ cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
+ cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
+ memcpy(cp->frag, ctrl->assoc, frag_len);
+
+ ctrl->assoc_len_so_far += frag_len;
+ ctrl->assoc_rem_len -= frag_len;
+
+ amp_ctrl_put(ctrl);
+
+ hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
+
+ kfree(cp);
+
+ return false;
+}
+
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
+{
+ struct hci_conn *hcon;
+
+ BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, handle);
+ if (!hcon)
+ return;
+
+ amp_write_rem_assoc_frag(hdev, hcon);
+}
+
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
+{
+ struct hci_conn *hcon;
+
+ BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+
+ hcon = hci_conn_hash_lookup_handle(hdev, handle);
+ if (!hcon)
+ return;
+
+ BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
+
+ amp_write_rem_assoc_frag(hdev, hcon);
+}
+
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
struct hci_conn *hcon)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e7d2db4..2c7e27a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1215,6 +1215,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
}
+static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
+ hdev->name, rp->status, rp->phy_handle);
+
+ if (rp->status)
+ return;
+
+ amp_write_rem_assoc_continue(hdev, rp->phy_handle);
+}
+
static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -1699,7 +1713,18 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
{
+ struct hci_cp_create_phy_link *cp;
+
BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+ if (status)
+ return;
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
+ if (!cp)
+ return;
+
+ amp_write_remote_assoc(hdev, cp->phy_handle);
}
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -2435,6 +2460,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cc_write_le_host_supported(hdev, skb);
break;
+ case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
+ hci_cc_write_remote_amp_assoc(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 14/19] Bluetooth: AMP: Create Physical Link
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
When receiving A2MP Get AMP Assoc Response execute HCI Create Physical
Link to AMP controller. Define function which will run when receiving
HCI Command Status.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 2 ++
net/bluetooth/a2mp.c | 2 ++
net/bluetooth/amp.c | 19 +++++++++++++++++++
net/bluetooth/hci_event.c | 9 +++++++++
4 files changed, 32 insertions(+)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 763b463..cadb3d0 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -37,5 +37,7 @@ int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon);
#endif /* __AMP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 93adaad..773e8fc 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -392,6 +392,8 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
+ amp_create_phylink(hdev, mgr, hcon);
+
done:
hci_dev_put(hdev);
skb_pull(skb, len);
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 67bc2c2f..657ec73 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -232,3 +232,22 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
mgr->state = READ_LOC_AMP_ASSOC;
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
}
+
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon)
+{
+ struct hci_cp_create_phy_link cp;
+
+ cp.phy_handle = hcon->handle;
+
+ BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+ hcon->handle);
+
+ if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+ &cp.key_type)) {
+ BT_DBG("Cannot create link key");
+ return;
+ }
+
+ hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0a9e720..e7d2db4 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1697,6 +1697,11 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
BT_DBG("%s status 0x%2.2x", hdev->name, status);
}
+static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("%s status 0x%2.2x", hdev->name, status);
+}
+
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -2511,6 +2516,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_le_start_enc(hdev, ev->status);
break;
+ case HCI_OP_CREATE_PHY_LINK:
+ hci_cs_create_phylink(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
break;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv7 13/19] Bluetooth: AMP: Add AMP key calculation
From: Andrei Emeltchenko @ 2012-09-27 14:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: gustavo, mathewm
In-Reply-To: <1348755984-6403-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Function calculates AMP keys using hmac_sha256 helper. Calculated keys
are Generic AMP Link Key (gamp) and Dedicated AMP Link Key with
keyID "802b" for 802.11 PAL.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
include/net/bluetooth/amp.h | 2 ++
net/bluetooth/Kconfig | 1 +
net/bluetooth/amp.c | 45 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index f57854f..763b463 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -32,6 +32,8 @@ void amp_ctrl_list_flush(struct amp_mgr *mgr);
struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
u8 remote_id);
+int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 3537d38..1c11d0d 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -11,6 +11,7 @@ menuconfig BT
select CRYPTO_BLKCIPHER
select CRYPTO_AES
select CRYPTO_ECB
+ select CRYPTO_SHA256
help
Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index ea4d5ff..67bc2c2f 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -161,6 +161,51 @@ static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
return ret;
}
+int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct link_key *key;
+ u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
+ u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
+ int err;
+
+ if (!hci_conn_check_link_mode(conn))
+ return -EACCES;
+
+ BT_DBG("conn %p key_type %d", conn, conn->key_type);
+
+ /* Legacy key */
+ if (conn->key_type < 3) {
+ BT_ERR("Legacy key type %d", conn->key_type);
+ return -EACCES;
+ }
+
+ *type = conn->key_type;
+ *len = HCI_AMP_LINK_KEY_SIZE;
+
+ key = hci_find_link_key(hdev, &conn->dst);
+
+ /* BR/EDR Link Key concatenated together with itself */
+ memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
+ memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
+
+ /* Derive Generic AMP Link Key (gamp) */
+ err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
+ if (err) {
+ BT_ERR("Could not derive Generic AMP Key: err %d", err);
+ return err;
+ }
+
+ if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
+ BT_DBG("Use Generic AMP Key (gamp)");
+ memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
+ return err;
+ }
+
+ /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
+ return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
+}
+
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
{
struct hci_cp_read_local_amp_assoc cp;
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox