* [PATCH BlueZ v2 6/8] android/AVRCP: Add implementation of SDP record
From: Luiz Augusto von Dentz @ 2014-01-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390569875-29436-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds the following record:
Service Name: AVRCP TG
Service RecHandle: 0x10002
Service Class ID List:
"AV Remote Target" (0x110c)
Protocol Descriptor List:
"L2CAP" (0x0100)
PSM: 23
"AVCTP" (0x0017)
uint16: 0x103
Profile Descriptor List:
"AV Remote" (0x110e)
Version: 0x0100
---
android/avrcp.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/android/avrcp.c b/android/avrcp.c
index 707506b..e06d136 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -29,22 +29,116 @@
#include <glib.h>
#include "lib/bluetooth.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
#include "log.h"
+#include "bluetooth.h"
#include "avrcp.h"
#include "hal-msg.h"
#include "ipc.h"
+#define L2CAP_PSM_AVCTP 0x17
+
+#define AVRCP_FEATURE_CATEGORY_1 0x0001
+#define AVRCP_FEATURE_CATEGORY_2 0x0002
+#define AVRCP_FEATURE_CATEGORY_3 0x0004
+#define AVRCP_FEATURE_CATEGORY_4 0x0008
+
static bdaddr_t adapter_addr;
+static uint32_t record_id = 0;
static const struct ipc_handler cmd_handlers[] = {
};
+static sdp_record_t *avrcp_record(void)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, l2cap, avctp, avrtg;
+ sdp_profile_desc_t profile[1];
+ sdp_list_t *aproto_control, *proto_control[2];
+ sdp_record_t *record;
+ sdp_data_t *psm, *version, *features;
+ uint16_t lp = L2CAP_PSM_AVCTP;
+ uint16_t avrcp_ver = 0x0100, avctp_ver = 0x0103;
+ uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
+ AVRCP_FEATURE_CATEGORY_2 |
+ AVRCP_FEATURE_CATEGORY_3 |
+ AVRCP_FEATURE_CATEGORY_4);
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ /* Service Class ID List */
+ sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
+ svclass_id = sdp_list_append(NULL, &avrtg);
+ sdp_set_service_classes(record, svclass_id);
+
+ /* Protocol Descriptor List */
+ sdp_uuid16_create(&l2cap, L2CAP_UUID);
+ proto_control[0] = sdp_list_append(NULL, &l2cap);
+ psm = sdp_data_alloc(SDP_UINT16, &lp);
+ proto_control[0] = sdp_list_append(proto_control[0], psm);
+ apseq = sdp_list_append(NULL, proto_control[0]);
+
+ sdp_uuid16_create(&avctp, AVCTP_UUID);
+ proto_control[1] = sdp_list_append(NULL, &avctp);
+ version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
+ proto_control[1] = sdp_list_append(proto_control[1], version);
+ apseq = sdp_list_append(apseq, proto_control[1]);
+
+ aproto_control = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(record, aproto_control);
+
+ /* Bluetooth Profile Descriptor List */
+ sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
+ profile[0].version = avrcp_ver;
+ pfseq = sdp_list_append(NULL, &profile[0]);
+ sdp_set_profile_descs(record, pfseq);
+
+ features = sdp_data_alloc(SDP_UINT16, &feat);
+ sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+ sdp_set_info_attr(record, "AVRCP TG", 0, 0);
+
+ sdp_data_free(psm);
+ sdp_data_free(version);
+ sdp_list_free(proto_control[0], NULL);
+ sdp_list_free(proto_control[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(aproto_control, NULL);
+ sdp_list_free(pfseq, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
+
+ return record;
+}
+
bool bt_avrcp_register(const bdaddr_t *addr)
{
+ sdp_record_t *rec;
+
DBG("");
bacpy(&adapter_addr, addr);
+ rec = avrcp_record();
+ if (!rec) {
+ error("Failed to allocate AVRCP record");
+ return false;
+ }
+
+ if (bt_adapter_add_record(rec, 0) < 0) {
+ error("Failed to register AVRCP record");
+ sdp_record_free(rec);
+ return false;
+ }
+ record_id = rec->handle;
+
ipc_register(HAL_SERVICE_ID_AVRCP, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
@@ -56,4 +150,7 @@ void bt_avrcp_unregister(void)
DBG("");
ipc_unregister(HAL_SERVICE_ID_AVRCP);
+
+ bt_adapter_remove_record(record_id);
+ record_id = 0;
}
--
1.8.4.2
^ permalink raw reply related
* [PATCH BlueZ v2 5/8] android/haltest: Add init and cleanup calls to rc methods
From: Luiz Augusto von Dentz @ 2014-01-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390569875-29436-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
android/Android.mk | 1 +
android/Makefile.am | 1 +
android/client/haltest.c | 2 ++
android/client/if-bt.c | 2 +-
android/client/if-main.h | 2 ++
android/client/{if-audio.c => if-rc.c} | 44 +++++++++++++---------------------
6 files changed, 23 insertions(+), 29 deletions(-)
copy android/client/{if-audio.c => if-rc.c} (57%)
diff --git a/android/Android.mk b/android/Android.mk
index 160a1d4..b83d1fe 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -131,6 +131,7 @@ LOCAL_SRC_FILES := \
bluez/android/client/tabcompletion.c \
bluez/android/client/if-audio.c \
bluez/android/client/if-av.c \
+ bluez/android/client/if-rc.c \
bluez/android/client/if-bt.c \
bluez/android/client/if-hf.c \
bluez/android/client/if-hh.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 664524f..e065c0c 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -85,6 +85,7 @@ android_haltest_SOURCES = android/client/haltest.c \
android/client/tabcompletion.c \
android/client/if-main.h \
android/client/if-av.c \
+ android/client/if-rc.c \
android/client/if-bt.c \
android/client/if-gatt.c \
android/client/if-hf.c \
diff --git a/android/client/haltest.c b/android/client/haltest.c
index f4d1ade..114fe31 100644
--- a/android/client/haltest.c
+++ b/android/client/haltest.c
@@ -34,6 +34,7 @@ const struct interface *interfaces[] = {
&audio_if,
&bluetooth_if,
&av_if,
+ &rc_if,
&gatt_if,
&gatt_client_if,
&gatt_server_if,
@@ -382,6 +383,7 @@ static void init(void)
static const char * const inames[] = {
BT_PROFILE_HANDSFREE_ID,
BT_PROFILE_ADVANCED_AUDIO_ID,
+ BT_PROFILE_AV_RC_ID,
BT_PROFILE_HEALTH_ID,
BT_PROFILE_HIDHOST_ID,
BT_PROFILE_PAN_ID,
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 6bfb439..8dcffea 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -760,7 +760,7 @@ static void get_profile_interface_p(int argc, const char **argv)
else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
pif = (const void **) &if_pan;
else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
- pif = &dummy; /* TODO: change when if_rc is there */
+ pif = (const void **) &if_rc;
else if (strcmp(BT_PROFILE_GATT_ID, id) == 0)
pif = (const void **) &if_gatt;
else
diff --git a/android/client/if-main.h b/android/client/if-main.h
index 2b22fc4..d82358e 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -48,6 +48,7 @@ extern audio_hw_device_t *if_audio;
/* Interfaces from hal that can be populated during application lifetime */
extern const bt_interface_t *if_bluetooth;
extern const btav_interface_t *if_av;
+extern const btrc_interface_t *if_rc;
extern const bthf_interface_t *if_hf;
extern const bthh_interface_t *if_hh;
extern const btpan_interface_t *if_pan;
@@ -68,6 +69,7 @@ struct interface {
extern const struct interface audio_if;
extern const struct interface bluetooth_if;
extern const struct interface av_if;
+extern const struct interface rc_if;
extern const struct interface gatt_if;
extern const struct interface gatt_client_if;
extern const struct interface gatt_server_if;
diff --git a/android/client/if-audio.c b/android/client/if-rc.c
similarity index 57%
copy from android/client/if-audio.c
copy to android/client/if-rc.c
index 203e088..58fb892 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-rc.c
@@ -18,41 +18,29 @@
#include "if-main.h"
#include "../hal-utils.h"
-audio_hw_device_t *if_audio = NULL;
+const btrc_interface_t *if_rc = NULL;
-static void init_p(int argc, const char **argv)
-{
- int err;
- const hw_module_t *module;
- audio_hw_device_t *device;
+static btrc_callbacks_t rc_cbacks = {
+ .size = sizeof(rc_cbacks),
+};
- err = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID,
- AUDIO_HARDWARE_MODULE_ID_A2DP, &module);
- if (err) {
- haltest_error("hw_get_module_by_class returned %d\n", err);
- return;
- }
+/* init */
- err = audio_hw_device_open(module, &device);
- if (err)
- haltest_error("audio_hw_device_open returned %d\n", err);
+static void init_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_rc);
- if_audio = device;
+ EXEC(if_rc->init, &rc_cbacks);
}
+/* cleanup */
+
static void cleanup_p(int argc, const char **argv)
{
- int err;
-
- RETURN_IF_NULL(if_audio);
-
- err = audio_hw_device_close(if_audio);
- if (err < 0) {
- haltest_error("audio_hw_device_close returned %d\n", err);
- return;
- }
+ RETURN_IF_NULL(if_rc);
- if_audio = NULL;
+ EXECV(if_rc->cleanup);
+ if_rc = NULL;
}
static struct method methods[] = {
@@ -61,7 +49,7 @@ static struct method methods[] = {
END_METHOD
};
-const struct interface audio_if = {
- .name = "audio",
+const struct interface rc_if = {
+ .name = "rc",
.methods = methods
};
--
1.8.4.2
^ permalink raw reply related
* [PATCH BlueZ v2 4/8] android: Add initial skeleton for AVRCP in the HAL
From: Luiz Augusto von Dentz @ 2014-01-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390569875-29436-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
android/Android.mk | 1 +
android/Makefile.am | 1 +
android/hal-avrcp.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++
android/hal-bluetooth.c | 3 ++
android/hal.h | 2 ++
5 files changed, 94 insertions(+)
create mode 100644 android/hal-avrcp.c
diff --git a/android/Android.mk b/android/Android.mk
index bc4f7e4..160a1d4 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -97,6 +97,7 @@ LOCAL_SRC_FILES := \
bluez/android/hal-hidhost.c \
bluez/android/hal-pan.c \
bluez/android/hal-a2dp.c \
+ bluez/android/hal-avrcp.c \
bluez/android/hal-utils.c \
LOCAL_C_INCLUDES += \
diff --git a/android/Makefile.am b/android/Makefile.am
index d4a76bb..664524f 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -50,6 +50,7 @@ android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
android/hal-hidhost.c \
android/hal-pan.c \
android/hal-a2dp.c \
+ android/hal-avrcp.c \
android/hardware/bluetooth.h \
android/hardware/bt_av.h \
android/hardware/bt_gatt.h \
diff --git a/android/hal-avrcp.c b/android/hal-avrcp.c
new file mode 100644
index 0000000..01d233b
--- /dev/null
+++ b/android/hal-avrcp.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "hal-log.h"
+#include "hal.h"
+#include "hal-msg.h"
+#include "hal-ipc.h"
+
+static const btrc_callbacks_t *cbs = NULL;
+
+static bool interface_ready(void)
+{
+ return cbs != NULL;
+}
+
+static bt_status_t init(btrc_callbacks_t *callbacks)
+{
+ struct hal_cmd_register_module cmd;
+ int ret;
+
+ DBG("");
+
+ if (interface_ready())
+ return BT_STATUS_DONE;
+
+ cbs = callbacks;
+
+ cmd.service_id = HAL_SERVICE_ID_AVRCP;
+
+ ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ if (ret != BT_STATUS_SUCCESS) {
+ cbs = NULL;
+ hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
+ }
+
+ return ret;
+}
+
+static void cleanup()
+{
+ struct hal_cmd_unregister_module cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return;
+
+ cbs = NULL;
+
+ cmd.service_id = HAL_SERVICE_ID_AVRCP;
+
+ hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
+}
+
+static btrc_interface_t iface = {
+ .size = sizeof(iface),
+ .init = init,
+ .cleanup = cleanup
+};
+
+btrc_interface_t *bt_get_avrcp_interface()
+{
+ return &iface;
+}
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 4f0e7b7..0dac158 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -762,6 +762,9 @@ static const void *get_profile_interface(const char *profile_id)
if (!strcmp(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID))
return bt_get_a2dp_interface();
+ if (!strcmp(profile_id, BT_PROFILE_AV_RC_ID))
+ return bt_get_avrcp_interface();
+
return NULL;
}
diff --git a/android/hal.h b/android/hal.h
index b475411..1ff4fbd 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -20,11 +20,13 @@
#include <hardware/bt_hh.h>
#include <hardware/bt_pan.h>
#include <hardware/bt_av.h>
+#include <hardware/bt_rc.h>
btsock_interface_t *bt_get_sock_interface(void);
bthh_interface_t *bt_get_hidhost_interface(void);
btpan_interface_t *bt_get_pan_interface(void);
btav_interface_t *bt_get_a2dp_interface(void);
+btrc_interface_t *bt_get_avrcp_interface(void);
void bt_thread_associate(void);
void bt_thread_disassociate(void);
--
1.8.4.2
^ permalink raw reply related
* [PATCH BlueZ v2 3/8] android: Add initial skeleton for AVRCP in the daemon
From: Luiz Augusto von Dentz @ 2014-01-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390569875-29436-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
android/Android.mk | 1 +
android/Makefile.am | 1 +
plugins/external-dummy.c => android/avrcp.c | 32 ++++++++++++++++++++++-------
android/{hidhost.h => avrcp.h} | 6 +++---
android/main.c | 11 ++++++++++
5 files changed, 41 insertions(+), 10 deletions(-)
copy plugins/external-dummy.c => android/avrcp.c (62%)
copy android/{hidhost.h => avrcp.h} (84%)
diff --git a/android/Android.mk b/android/Android.mk
index fd76f1d..bc4f7e4 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
bluez/android/avdtp.c \
bluez/android/a2dp.c \
bluez/android/avctp.c \
+ bluez/android/avrcp.c \
bluez/android/pan.c \
bluez/src/log.c \
bluez/src/shared/mgmt.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 88fe667..d4a76bb 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -34,6 +34,7 @@ android_bluetoothd_SOURCES = android/main.c \
android/avdtp.h android/avdtp.c \
android/a2dp.h android/a2dp.c \
android/avctp.h android/avctp.c \
+ android/avrcp.h android/avrcp.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
btio/btio.h btio/btio.c \
diff --git a/plugins/external-dummy.c b/android/avrcp.c
similarity index 62%
copy from plugins/external-dummy.c
copy to android/avrcp.c
index ff31290..707506b 100644
--- a/plugins/external-dummy.c
+++ b/android/avrcp.c
@@ -2,6 +2,9 @@
*
* BlueZ - Bluetooth protocol stack for Linux
*
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
* 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
@@ -22,20 +25,35 @@
#include <config.h>
#endif
-#include "plugin.h"
+#include <stdbool.h>
+#include <glib.h>
+
+#include "lib/bluetooth.h"
#include "log.h"
+#include "avrcp.h"
+#include "hal-msg.h"
+#include "ipc.h"
+
+static bdaddr_t adapter_addr;
+
+static const struct ipc_handler cmd_handlers[] = {
+};
-static int dummy_init(void)
+bool bt_avrcp_register(const bdaddr_t *addr)
{
DBG("");
- return 0;
+ bacpy(&adapter_addr, addr);
+
+ ipc_register(HAL_SERVICE_ID_AVRCP, cmd_handlers,
+ G_N_ELEMENTS(cmd_handlers));
+
+ return true;
}
-static void dummy_exit(void)
+void bt_avrcp_unregister(void)
{
DBG("");
-}
-BLUETOOTH_PLUGIN_DEFINE(external_dummy, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_LOW, dummy_init, dummy_exit)
+ ipc_unregister(HAL_SERVICE_ID_AVRCP);
+}
diff --git a/android/hidhost.h b/android/avrcp.h
similarity index 84%
copy from android/hidhost.h
copy to android/avrcp.h
index ea14446..6fe7fbf 100644
--- a/android/hidhost.h
+++ b/android/avrcp.h
@@ -2,7 +2,7 @@
*
* BlueZ - Bluetooth protocol stack for Linux
*
- * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
@@ -21,5 +21,5 @@
*
*/
-bool bt_hid_register(const bdaddr_t *addr);
-void bt_hid_unregister(void);
+bool bt_avrcp_register(const bdaddr_t *addr);
+void bt_avrcp_unregister(void);
diff --git a/android/main.c b/android/main.c
index 8983a84..c353c4a 100644
--- a/android/main.c
+++ b/android/main.c
@@ -55,6 +55,7 @@
#include "ipc.h"
#include "a2dp.h"
#include "pan.h"
+#include "avrcp.h"
#define STARTUP_GRACE_SECONDS 5
#define SHUTDOWN_GRACE_SECONDS 10
@@ -107,6 +108,13 @@ static void service_register(const void *buf, uint16_t len)
}
break;
+ case HAL_SERVICE_ID_AVRCP:
+ if (!bt_avrcp_register(&adapter_bdaddr)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ break;
default:
DBG("service %u not supported", m->service_id);
status = HAL_STATUS_FAILED;
@@ -149,6 +157,9 @@ static void service_unregister(const void *buf, uint16_t len)
case HAL_SERVICE_ID_PAN:
bt_pan_unregister();
break;
+ case HAL_SERVICE_ID_AVRCP:
+ bt_avrcp_unregister();
+ break;
default:
/* This would indicate bug in HAL, as unregister should not be
* called in init failed */
--
1.8.4.2
^ permalink raw reply related
* [PATCH BlueZ v2 2/8] android/AVCTP: Strip dependencies
From: Luiz Augusto von Dentz @ 2014-01-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390569875-29436-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This strips AVCTP code of any dependency of core and btio to make it
transport agnostic.
---
android/Android.mk | 1 +
android/Makefile.am | 1 +
android/avctp.c | 794 ++++++++--------------------------------------------
android/avctp.h | 40 +--
4 files changed, 134 insertions(+), 702 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index c274295..fd76f1d 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -29,6 +29,7 @@ LOCAL_SRC_FILES := \
bluez/android/audio-ipc.c \
bluez/android/avdtp.c \
bluez/android/a2dp.c \
+ bluez/android/avctp.c \
bluez/android/pan.c \
bluez/src/log.c \
bluez/src/shared/mgmt.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index f85de20..88fe667 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -33,6 +33,7 @@ android_bluetoothd_SOURCES = android/main.c \
android/audio-ipc.h android/audio-ipc.c \
android/avdtp.h android/avdtp.c \
android/a2dp.h android/a2dp.c \
+ android/avctp.h android/avctp.c \
android/socket.h android/socket.c \
android/pan.h android/pan.c \
btio/btio.h btio/btio.c \
diff --git a/android/avctp.c b/android/avctp.c
index 6669ddc..1255c3e 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -34,27 +34,19 @@
#include <unistd.h>
#include <assert.h>
#include <signal.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
-#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
-#include <bluetooth/l2cap.h>
#include <glib.h>
-#include <btio/btio.h>
-
-#include "lib/uuid.h"
-#include "src/adapter.h"
-#include "src/device.h"
#include "log.h"
-#include "error.h"
#include "uinput.h"
#include "avctp.h"
-#include "avrcp.h"
/* AV/C Panel 1.23, page 76:
* command with the pressed value is valid for two seconds
@@ -115,20 +107,6 @@ struct avc_header {
#error "Unknown byte order"
#endif
-struct avctp_state_callback {
- avctp_state_cb cb;
- struct btd_device *dev;
- unsigned int id;
- void *user_data;
-};
-
-struct avctp_server {
- struct btd_adapter *adapter;
- GIOChannel *control_io;
- GIOChannel *browsing_io;
- GSList *sessions;
-};
-
struct avctp_control_req {
struct avctp_pending_req *p;
uint8_t code;
@@ -157,7 +135,7 @@ struct avctp_pending_req {
int err;
avctp_process_cb process;
void *data;
- GDestroyNotify destroy;
+ avctp_destroy_cb_t destroy;
};
struct avctp_channel {
@@ -173,7 +151,7 @@ struct avctp_channel {
GQueue *queue;
GSList *processed;
guint process_id;
- GDestroyNotify destroy;
+ avctp_destroy_cb_t destroy;
};
struct key_pressed {
@@ -182,14 +160,8 @@ struct key_pressed {
};
struct avctp {
- struct avctp_server *server;
- struct btd_device *device;
-
- avctp_state_t state;
-
int uinput;
- guint auth_id;
unsigned int passthrough_id;
unsigned int unit_id;
unsigned int subunit_id;
@@ -201,7 +173,7 @@ struct avctp {
uint8_t key_quirks[256];
struct key_pressed key;
- bool initiator;
+ uint16_t version;
};
struct avctp_passthrough_handler {
@@ -221,7 +193,7 @@ struct avctp_browsing_pdu_handler {
avctp_browsing_pdu_cb cb;
void *user_data;
unsigned int id;
- GDestroyNotify destroy;
+ avctp_destroy_cb_t destroy;
};
static struct {
@@ -259,10 +231,6 @@ static struct {
{ NULL }
};
-static GSList *callbacks = NULL;
-static GSList *servers = NULL;
-
-static void auth_cb(DBusError *derr, void *user_data);
static gboolean process_queue(gpointer user_data);
static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
uint8_t subunit, uint8_t *operands,
@@ -488,83 +456,6 @@ static void avctp_channel_destroy(struct avctp_channel *chan)
g_free(chan);
}
-static void avctp_disconnected(struct avctp *session)
-{
- struct avctp_server *server;
-
- if (!session)
- return;
-
- if (session->browsing)
- avctp_channel_destroy(session->browsing);
-
- if (session->control)
- avctp_channel_destroy(session->control);
-
- if (session->auth_id != 0) {
- btd_cancel_authorization(session->auth_id);
- session->auth_id = 0;
- }
-
- if (session->key.timer > 0)
- g_source_remove(session->key.timer);
-
- if (session->uinput >= 0) {
- char address[18];
-
- ba2str(device_get_address(session->device), address);
- DBG("AVCTP: closing uinput for %s", address);
-
- ioctl(session->uinput, UI_DEV_DESTROY);
- close(session->uinput);
- session->uinput = -1;
- }
-
- server = session->server;
- server->sessions = g_slist_remove(server->sessions, session);
- btd_device_unref(session->device);
- g_free(session);
-}
-
-static void avctp_set_state(struct avctp *session, avctp_state_t new_state)
-{
- GSList *l;
- avctp_state_t old_state = session->state;
-
- session->state = new_state;
-
- for (l = callbacks; l != NULL; l = l->next) {
- struct avctp_state_callback *cb = l->data;
-
- if (cb->dev && cb->dev != session->device)
- continue;
-
- cb->cb(session->device, old_state, new_state, cb->user_data);
- }
-
- switch (new_state) {
- case AVCTP_STATE_DISCONNECTED:
- DBG("AVCTP Disconnected");
- avctp_disconnected(session);
- break;
- case AVCTP_STATE_CONNECTING:
- DBG("AVCTP Connecting");
- break;
- case AVCTP_STATE_CONNECTED:
- DBG("AVCTP Connected");
- break;
- case AVCTP_STATE_BROWSING_CONNECTING:
- DBG("AVCTP Browsing Connecting");
- break;
- case AVCTP_STATE_BROWSING_CONNECTED:
- DBG("AVCTP Browsing Connected");
- break;
- default:
- error("Invalid AVCTP state %d", new_state);
- return;
- }
-}
-
static int avctp_send(struct avctp_channel *control, uint8_t transaction,
uint8_t cr, uint8_t code,
uint8_t subunit, uint8_t opcode,
@@ -874,7 +765,8 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
handler = g_slist_nth_data(browsing->handlers, 0);
if (handler == NULL) {
DBG("handler not found");
- packet_size += avrcp_browsing_general_reject(operands);
+ /* FIXME: Add general reject */
+ /* packet_size += avrcp_browsing_general_reject(operands); */
goto send;
}
@@ -893,7 +785,6 @@ send:
failed:
DBG("AVCTP Browsing: disconnected");
- avctp_set_state(session, AVCTP_STATE_CONNECTED);
if (session->browsing) {
avctp_channel_destroy(session->browsing);
@@ -966,7 +857,9 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
handler = find_handler(control->handlers, avc->opcode);
if (!handler) {
DBG("handler not found for 0x%02x", avc->opcode);
- packet_size += avrcp_handle_vendor_reject(&code, operands);
+ /* FIXME:
+ * packet_size += avrcp_handle_vendor_reject(&code, operands);
+ */
avc->code = code;
goto done;
}
@@ -990,11 +883,11 @@ done:
failed:
DBG("AVCTP session %p got disconnected", session);
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
+ avctp_shutdown(session);
return FALSE;
}
-static int uinput_create(char *name)
+static int uinput_create(const char *name)
{
struct uinput_dev dev;
int fd, err, i;
@@ -1049,11 +942,9 @@ static int uinput_create(char *name)
return fd;
}
-static void init_uinput(struct avctp *session)
+int avctp_init_uinput(struct avctp *session, const char *name,
+ const char *address)
{
- char address[18], name[248 + 1];
-
- device_get_name(session->device, name, sizeof(name));
if (g_str_equal(name, "Nokia CK-20W")) {
session->key_quirks[AVC_FORWARD] |= QUIRK_NO_RELEASE;
session->key_quirks[AVC_BACKWARD] |= QUIRK_NO_RELEASE;
@@ -1061,24 +952,28 @@ static void init_uinput(struct avctp *session)
session->key_quirks[AVC_PAUSE] |= QUIRK_NO_RELEASE;
}
- ba2str(device_get_address(session->device), address);
session->uinput = uinput_create(address);
- if (session->uinput < 0)
- error("AVRCP: failed to init uinput for %s", address);
- else
- DBG("AVRCP: uinput initialized for %s", address);
+ if (session->uinput < 0) {
+ error("AVCTP: failed to init uinput for %s", address);
+ return session->uinput;
+ }
+
+ return 0;
}
-static struct avctp_channel *avctp_channel_create(struct avctp *session,
- GIOChannel *io,
- GDestroyNotify destroy)
+static struct avctp_channel *avctp_channel_create(struct avctp *session, int fd,
+ size_t imtu, size_t omtu,
+ avctp_destroy_cb_t destroy)
{
struct avctp_channel *chan;
chan = g_new0(struct avctp_channel, 1);
chan->session = session;
- chan->io = g_io_channel_ref(io);
+ chan->io = g_io_channel_unix_new(fd);
chan->queue = g_queue_new();
+ chan->imtu = imtu;
+ chan->omtu = omtu;
+ chan->buffer = g_malloc0(MAX(imtu, omtu));
chan->destroy = destroy;
return chan;
@@ -1103,381 +998,10 @@ static void avctp_destroy_browsing(void *data)
chan->handlers = NULL;
}
-static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
- gpointer data)
-{
- struct avctp *session = data;
- struct avctp_channel *browsing = session->browsing;
- char address[18];
- uint16_t imtu, omtu;
- GError *gerr = NULL;
-
- if (err) {
- error("Browsing: %s", err->message);
- goto fail;
- }
-
- bt_io_get(chan, &gerr,
- BT_IO_OPT_DEST, &address,
- BT_IO_OPT_IMTU, &imtu,
- BT_IO_OPT_OMTU, &omtu,
- BT_IO_OPT_INVALID);
- if (gerr) {
- error("%s", gerr->message);
- g_io_channel_shutdown(chan, TRUE, NULL);
- g_io_channel_unref(chan);
- g_error_free(gerr);
- goto fail;
- }
-
- DBG("AVCTP Browsing: connected to %s", address);
-
- if (browsing == NULL) {
- browsing = avctp_channel_create(session, chan,
- avctp_destroy_browsing);
- session->browsing = browsing;
- }
-
- browsing->imtu = imtu;
- browsing->omtu = omtu;
- browsing->buffer = g_malloc0(MAX(imtu, omtu));
- browsing->watch = g_io_add_watch(session->browsing->io,
- G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_browsing_cb, session);
-
- avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTED);
-
- /* Process any request that was pending the connection to complete */
- if (browsing->process_id == 0 && !g_queue_is_empty(browsing->queue))
- browsing->process_id = g_idle_add(process_queue, browsing);
-
- return;
-
-fail:
- avctp_set_state(session, AVCTP_STATE_CONNECTED);
-
- if (session->browsing) {
- avctp_channel_destroy(session->browsing);
- session->browsing = NULL;
- }
-}
-
-static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
-{
- struct avctp *session = data;
- char address[18];
- uint16_t imtu, omtu;
- GError *gerr = NULL;
-
- if (err) {
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
- error("%s", err->message);
- return;
- }
-
- bt_io_get(chan, &gerr,
- BT_IO_OPT_DEST, &address,
- BT_IO_OPT_IMTU, &imtu,
- BT_IO_OPT_IMTU, &omtu,
- BT_IO_OPT_INVALID);
- if (gerr) {
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
- error("%s", gerr->message);
- g_error_free(gerr);
- return;
- }
-
- DBG("AVCTP: connected to %s", address);
-
- if (session->control == NULL)
- session->control = avctp_channel_create(session, chan, NULL);
-
- session->control->imtu = imtu;
- session->control->omtu = omtu;
- session->control->buffer = g_malloc0(MAX(imtu, omtu));
- session->control->watch = g_io_add_watch(session->control->io,
- G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_cb, session);
-
- session->passthrough_id = avctp_register_pdu_handler(session,
- AVC_OP_PASSTHROUGH,
- handle_panel_passthrough,
- NULL);
- session->unit_id = avctp_register_pdu_handler(session,
- AVC_OP_UNITINFO,
- handle_unit_info,
- NULL);
- session->subunit_id = avctp_register_pdu_handler(session,
- AVC_OP_SUBUNITINFO,
- handle_subunit_info,
- NULL);
-
- init_uinput(session);
-
- avctp_set_state(session, AVCTP_STATE_CONNECTED);
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
- struct avctp *session = user_data;
- GError *err = NULL;
-
- session->auth_id = 0;
-
- if (session->control->watch > 0) {
- g_source_remove(session->control->watch);
- session->control->watch = 0;
- }
-
- if (derr && dbus_error_is_set(derr)) {
- error("Access denied: %s", derr->message);
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
- return;
- }
-
- if (!bt_io_accept(session->control->io, avctp_connect_cb, session,
- NULL, &err)) {
- error("bt_io_accept: %s", err->message);
- g_error_free(err);
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
- }
-}
-
-static struct avctp_server *find_server(GSList *list, struct btd_adapter *a)
-{
- for (; list; list = list->next) {
- struct avctp_server *server = list->data;
-
- if (server->adapter == a)
- return server;
- }
-
- return NULL;
-}
-
-static struct avctp *find_session(GSList *list, struct btd_device *device)
-{
- for (; list != NULL; list = g_slist_next(list)) {
- struct avctp *s = list->data;
-
- if (s->device == device)
- return s;
- }
-
- return NULL;
-}
-
-static struct avctp *avctp_get_internal(struct btd_device *device)
-{
- struct avctp_server *server;
- struct avctp *session;
-
- server = find_server(servers, device_get_adapter(device));
- if (server == NULL)
- return NULL;
-
- session = find_session(server->sessions, device);
- if (session)
- return session;
-
- session = g_new0(struct avctp, 1);
-
- session->server = server;
- session->device = btd_device_ref(device);
- session->state = AVCTP_STATE_DISCONNECTED;
- session->uinput = -1;
-
- server->sessions = g_slist_append(server->sessions, session);
-
- return session;
-}
-
-static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
- struct btd_device *dev)
-{
- const bdaddr_t *src;
- const bdaddr_t *dst;
-
- if (session->control != NULL) {
- error("Control: Refusing unexpected connect");
- g_io_channel_shutdown(chan, TRUE, NULL);
- return;
- }
-
- avctp_set_state(session, AVCTP_STATE_CONNECTING);
- session->control = avctp_channel_create(session, chan, NULL);
-
- src = btd_adapter_get_address(device_get_adapter(dev));
- dst = device_get_address(dev);
-
- session->auth_id = btd_request_authorization(src, dst,
- AVRCP_REMOTE_UUID,
- auth_cb, session);
- if (session->auth_id == 0)
- goto drop;
-
- session->control->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
- G_IO_NVAL, session_cb, session);
- return;
-
-drop:
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-}
-
-static void avctp_browsing_confirm(struct avctp *session, GIOChannel *chan,
- struct btd_device *dev)
-{
- GError *err = NULL;
-
- if (session->control == NULL || session->browsing != NULL) {
- error("Browsing: Refusing unexpected connect");
- g_io_channel_shutdown(chan, TRUE, NULL);
- return;
- }
-
- if (bt_io_accept(chan, avctp_connect_browsing_cb, session, NULL,
- &err)) {
- avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING);
- return;
- }
-
- error("Browsing: %s", err->message);
- g_error_free(err);
-
- return;
-}
-
-static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
-{
- struct avctp *session;
- char address[18];
- bdaddr_t src, dst;
- GError *err = NULL;
- uint16_t psm;
- struct btd_device *device;
-
- bt_io_get(chan, &err,
- BT_IO_OPT_SOURCE_BDADDR, &src,
- BT_IO_OPT_DEST_BDADDR, &dst,
- BT_IO_OPT_DEST, address,
- BT_IO_OPT_PSM, &psm,
- BT_IO_OPT_INVALID);
- if (err) {
- error("%s", err->message);
- g_error_free(err);
- g_io_channel_shutdown(chan, TRUE, NULL);
- return;
- }
-
- DBG("AVCTP: incoming connect from %s", address);
-
- device = btd_adapter_find_device(adapter_find(&src), &dst);
- if (!device)
- return;
-
- session = avctp_get_internal(device);
- if (session == NULL)
- return;
-
- if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL)
- btd_device_add_uuid(device, AVRCP_REMOTE_UUID);
-
- if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL)
- btd_device_add_uuid(device, AVRCP_TARGET_UUID);
-
- switch (psm) {
- case AVCTP_CONTROL_PSM:
- avctp_control_confirm(session, chan, device);
- break;
- case AVCTP_BROWSING_PSM:
- avctp_browsing_confirm(session, chan, device);
- break;
- }
-
- return;
-}
-
-static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master,
- uint8_t mode, uint16_t psm)
-{
- GError *err = NULL;
- GIOChannel *io;
-
- io = bt_io_listen(NULL, avctp_confirm_cb, NULL,
- NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
- BT_IO_OPT_PSM, psm,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_MASTER, master,
- BT_IO_OPT_MODE, mode,
- BT_IO_OPT_INVALID);
- if (!io) {
- error("%s", err->message);
- g_error_free(err);
- }
-
- return io;
-}
-
-int avctp_register(struct btd_adapter *adapter, gboolean master)
-{
- struct avctp_server *server;
- const bdaddr_t *src = btd_adapter_get_address(adapter);
-
- server = g_new0(struct avctp_server, 1);
-
- server->control_io = avctp_server_socket(src, master, L2CAP_MODE_BASIC,
- AVCTP_CONTROL_PSM);
- if (!server->control_io) {
- g_free(server);
- return -1;
- }
- server->browsing_io = avctp_server_socket(src, master, L2CAP_MODE_ERTM,
- AVCTP_BROWSING_PSM);
- if (!server->browsing_io) {
- if (server->control_io) {
- g_io_channel_shutdown(server->control_io, TRUE, NULL);
- g_io_channel_unref(server->control_io);
- server->control_io = NULL;
- }
- g_free(server);
- return -1;
- }
-
- server->adapter = btd_adapter_ref(adapter);
-
- servers = g_slist_append(servers, server);
-
- return 0;
-}
-
-void avctp_unregister(struct btd_adapter *adapter)
-{
- struct avctp_server *server;
-
- server = find_server(servers, adapter);
- if (!server)
- return;
-
- while (server->sessions)
- avctp_disconnected(server->sessions->data);
-
- servers = g_slist_remove(servers, server);
-
- g_io_channel_shutdown(server->browsing_io, TRUE, NULL);
- g_io_channel_unref(server->browsing_io);
- server->browsing_io = NULL;
-
- g_io_channel_shutdown(server->control_io, TRUE, NULL);
- g_io_channel_unref(server->control_io);
- btd_adapter_unref(server->adapter);
- g_free(server);
-}
-
static struct avctp_pending_req *pending_create(struct avctp_channel *chan,
avctp_process_cb process,
void *data,
- GDestroyNotify destroy)
+ avctp_destroy_cb_t destroy)
{
struct avctp_pending_req *p;
GSList *l, *tmp;
@@ -1732,39 +1256,6 @@ int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
func, user_data);
}
-unsigned int avctp_add_state_cb(struct btd_device *dev, avctp_state_cb cb,
- void *user_data)
-{
- struct avctp_state_callback *state_cb;
- static unsigned int id = 0;
-
- state_cb = g_new(struct avctp_state_callback, 1);
- state_cb->cb = cb;
- state_cb->dev = dev;
- state_cb->id = ++id;
- state_cb->user_data = user_data;
-
- callbacks = g_slist_append(callbacks, state_cb);
-
- return state_cb->id;
-}
-
-gboolean avctp_remove_state_cb(unsigned int id)
-{
- GSList *l;
-
- for (l = callbacks; l != NULL; l = l->next) {
- struct avctp_state_callback *cb = l->data;
- if (cb && cb->id == id) {
- callbacks = g_slist_remove(callbacks, cb);
- g_free(cb);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
unsigned int avctp_register_passthrough_handler(struct avctp *session,
avctp_passthrough_cb cb,
void *user_data)
@@ -1786,29 +1277,18 @@ unsigned int avctp_register_passthrough_handler(struct avctp *session,
return handler->id;
}
-bool avctp_unregister_passthrough_handler(unsigned int id)
+bool avctp_unregister_passthrough_handler(struct avctp *session,
+ unsigned int id)
{
- GSList *l;
-
- for (l = servers; l; l = l->next) {
- struct avctp_server *server = l->data;
- GSList *s;
+ if (session->handler == NULL)
+ return false;
- for (s = server->sessions; s; s = s->next) {
- struct avctp *session = s->data;
-
- if (session->handler == NULL)
- continue;
-
- if (session->handler->id == id) {
- g_free(session->handler);
- session->handler = NULL;
- return true;
- }
- }
- }
+ if (session->handler->id != id)
+ return false;
- return false;
+ g_free(session->handler);
+ session->handler = NULL;
+ return true;
}
unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode,
@@ -1840,7 +1320,7 @@ unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode,
unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
avctp_browsing_pdu_cb cb,
void *user_data,
- GDestroyNotify destroy)
+ avctp_destroy_cb_t destroy)
{
struct avctp_channel *browsing = session->browsing;
struct avctp_browsing_pdu_handler *handler;
@@ -1863,165 +1343,129 @@ unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
return handler->id;
}
-gboolean avctp_unregister_pdu_handler(unsigned int id)
+bool avctp_unregister_pdu_handler(struct avctp *session, unsigned int id)
{
+ struct avctp_channel *control = session->control;
GSList *l;
- for (l = servers; l; l = l->next) {
- struct avctp_server *server = l->data;
- GSList *s;
-
- for (s = server->sessions; s; s = s->next) {
- struct avctp *session = s->data;
- struct avctp_channel *control = session->control;
- GSList *h;
+ if (!control)
+ return false;
- if (control == NULL)
- continue;
+ for (l = control->handlers; l; l = g_slist_next(l)) {
+ struct avctp_pdu_handler *handler = l->data;
- for (h = control->handlers; h; h = h->next) {
- struct avctp_pdu_handler *handler = h->data;
-
- if (handler->id != id)
- continue;
+ if (handler->id != id)
+ continue;
- control->handlers = g_slist_remove(
- control->handlers,
- handler);
- g_free(handler);
- return TRUE;
- }
- }
+ control->handlers = g_slist_remove(control->handlers, handler);
+ g_free(handler);
+ return true;
}
- return FALSE;
+ return false;
}
-gboolean avctp_unregister_browsing_pdu_handler(unsigned int id)
+bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
+ unsigned int id)
{
+ struct avctp_channel *browsing = session->browsing;
GSList *l;
- for (l = servers; l; l = l->next) {
- struct avctp_server *server = l->data;
- GSList *s;
-
- for (s = server->sessions; s; s = s->next) {
- struct avctp *session = s->data;
- struct avctp_channel *browsing = session->browsing;
- GSList *h;
-
- if (browsing == NULL)
- continue;
+ if (browsing == NULL)
+ return false;
- for (h = browsing->handlers; h; h = h->next) {
- struct avctp_browsing_pdu_handler *handler =
- h->data;
+ for (l = browsing->handlers; l; l = g_slist_next(l)) {
+ struct avctp_browsing_pdu_handler *handler = l->data;
- if (handler->id != id)
- continue;
+ if (handler->id != id)
+ continue;
- browsing->handlers = g_slist_remove(
- browsing->handlers,
- handler);
- g_free(handler);
- return TRUE;
- }
- }
+ browsing->handlers = g_slist_remove(browsing->handlers,
+ handler);
+ g_free(handler);
+ return true;
}
- return FALSE;
+ return false;
}
-struct avctp *avctp_connect(struct btd_device *device)
+struct avctp *avctp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
{
struct avctp *session;
- GError *err = NULL;
- GIOChannel *io;
- const bdaddr_t *src;
-
- session = avctp_get_internal(device);
- if (!session)
- return NULL;
-
- if (session->state > AVCTP_STATE_DISCONNECTED)
- return session;
-
- avctp_set_state(session, AVCTP_STATE_CONNECTING);
+ struct avctp_channel *control;
+ GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- src = btd_adapter_get_address(session->server->adapter);
+ session = g_new0(struct avctp, 1);
+ session->version = version;
- io = bt_io_connect(avctp_connect_cb, session, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
- BT_IO_OPT_DEST_BDADDR,
- device_get_address(session->device),
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_PSM, AVCTP_CONTROL_PSM,
- BT_IO_OPT_INVALID);
- if (err) {
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
- error("%s", err->message);
- g_error_free(err);
+ control = avctp_channel_create(session, fd, imtu, omtu, NULL);
+ if (!control) {
+ g_free(session);
return NULL;
}
- session->control = avctp_channel_create(session, io, NULL);
- session->initiator = true;
- g_io_channel_unref(io);
+ session->control = control;
+ session->passthrough_id = avctp_register_pdu_handler(session,
+ AVC_OP_PASSTHROUGH,
+ handle_panel_passthrough,
+ NULL);
+ session->unit_id = avctp_register_pdu_handler(session,
+ AVC_OP_UNITINFO,
+ handle_unit_info,
+ NULL);
+ session->subunit_id = avctp_register_pdu_handler(session,
+ AVC_OP_SUBUNITINFO,
+ handle_subunit_info,
+ NULL);
+
+ control->watch = g_io_add_watch(session->control->io, cond,
+ (GIOFunc) session_cb, session);
return session;
}
-int avctp_connect_browsing(struct avctp *session)
+int avctp_connect_browsing(struct avctp *session, int fd, size_t imtu,
+ size_t omtu)
{
- const bdaddr_t *src;
- GError *err = NULL;
- GIOChannel *io;
-
- if (session->state != AVCTP_STATE_CONNECTED)
- return -ENOTCONN;
-
- if (session->browsing != NULL)
- return 0;
+ struct avctp_channel *browsing;
+ GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING);
-
- src = btd_adapter_get_address(session->server->adapter);
-
- io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, src,
- BT_IO_OPT_DEST_BDADDR,
- device_get_address(session->device),
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_PSM, AVCTP_BROWSING_PSM,
- BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
- BT_IO_OPT_INVALID);
- if (err) {
- error("%s", err->message);
- g_error_free(err);
- return -EIO;
- }
+ if (session->browsing)
+ return -EISCONN;
- session->browsing = avctp_channel_create(session, io,
+ browsing = avctp_channel_create(session, fd, imtu, omtu,
avctp_destroy_browsing);
- g_io_channel_unref(io);
+ if (!browsing)
+ return -EINVAL;
+
+ session->browsing = browsing;
+ browsing->watch = g_io_add_watch(session->browsing->io, cond,
+ (GIOFunc) session_browsing_cb, session);
return 0;
}
-void avctp_disconnect(struct avctp *session)
+void avctp_shutdown(struct avctp *session)
{
- if (session->state == AVCTP_STATE_DISCONNECTED)
+ if (!session)
return;
- avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-}
+ if (session->browsing)
+ avctp_channel_destroy(session->browsing);
-struct avctp *avctp_get(struct btd_device *device)
-{
- return avctp_get_internal(device);
-}
+ if (session->control)
+ avctp_channel_destroy(session->control);
-bool avctp_is_initiator(struct avctp *session)
-{
- return session->initiator;
+ if (session->key.timer > 0)
+ g_source_remove(session->key.timer);
+
+ if (session->uinput >= 0) {
+ DBG("AVCTP: closing uinput");
+
+ ioctl(session->uinput, UI_DEV_DESTROY);
+ close(session->uinput);
+ session->uinput = -1;
+ }
+
+ g_free(session);
}
diff --git a/android/avctp.h b/android/avctp.h
index f9c665e..99aaf95 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -82,19 +82,6 @@
struct avctp;
-typedef enum {
- AVCTP_STATE_DISCONNECTED = 0,
- AVCTP_STATE_CONNECTING,
- AVCTP_STATE_CONNECTED,
- AVCTP_STATE_BROWSING_CONNECTING,
- AVCTP_STATE_BROWSING_CONNECTED
-} avctp_state_t;
-
-typedef void (*avctp_state_cb) (struct btd_device *dev,
- avctp_state_t old_state,
- avctp_state_t new_state,
- void *user_data);
-
typedef bool (*avctp_passthrough_cb) (struct avctp *session,
uint8_t op, bool pressed,
void *user_data);
@@ -113,34 +100,33 @@ typedef size_t (*avctp_browsing_pdu_cb) (struct avctp *session,
uint8_t *operands, size_t operand_count,
void *user_data);
-unsigned int avctp_add_state_cb(struct btd_device *dev, avctp_state_cb cb,
- void *user_data);
-gboolean avctp_remove_state_cb(unsigned int id);
+typedef void (*avctp_destroy_cb_t) (void *user_data);
-int avctp_register(struct btd_adapter *adapter, gboolean master);
-void avctp_unregister(struct btd_adapter *adapter);
+struct avctp *avctp_new(int fd, size_t imtu, size_t omtu, uint16_t version);
+int avctp_init_uinput(struct avctp *session, const char *name,
+ const char *address);
+int avctp_connect_browsing(struct avctp *session, int fd, size_t imtu,
+ size_t omtu);
-struct avctp *avctp_connect(struct btd_device *device);
-struct avctp *avctp_get(struct btd_device *device);
-bool avctp_is_initiator(struct avctp *session);
-int avctp_connect_browsing(struct avctp *session);
-void avctp_disconnect(struct avctp *session);
+void avctp_shutdown(struct avctp *session);
unsigned int avctp_register_passthrough_handler(struct avctp *session,
avctp_passthrough_cb cb,
void *user_data);
-bool avctp_unregister_passthrough_handler(unsigned int id);
+bool avctp_unregister_passthrough_handler(struct avctp *session,
+ unsigned int id);
unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode,
avctp_control_pdu_cb cb,
void *user_data);
-gboolean avctp_unregister_pdu_handler(unsigned int id);
+bool avctp_unregister_pdu_handler(struct avctp *session, unsigned int id);
unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
avctp_browsing_pdu_cb cb,
void *user_data,
- GDestroyNotify destroy);
-gboolean avctp_unregister_browsing_pdu_handler(unsigned int id);
+ avctp_destroy_cb_t destroy);
+bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
+ unsigned int id);
int avctp_send_passthrough(struct avctp *session, uint8_t op);
int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
--
1.8.4.2
^ permalink raw reply related
* [PATCH BlueZ v2 1/8] android: Add copy of current AVCTP implemention
From: Luiz Augusto von Dentz @ 2014-01-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
These files are not added to any makefile on purpose because they still
have external dependencies.
---
v2: Fix issues with dependencies in Android, adds proper reject for messages
that cannot be handled, fix avctp_new not initializing the handlers properly
and finally fixes using 0 instead of NULL in various places.
{profiles/audio => android}/avctp.c | 0
{profiles/audio => android}/avctp.h | 0
2 files changed, 0 insertions(+), 0 deletions(-)
copy {profiles/audio => android}/avctp.c (100%)
copy {profiles/audio => android}/avctp.h (100%)
diff --git a/profiles/audio/avctp.c b/android/avctp.c
similarity index 100%
copy from profiles/audio/avctp.c
copy to android/avctp.c
diff --git a/profiles/audio/avctp.h b/android/avctp.h
similarity index 100%
copy from profiles/audio/avctp.h
copy to android/avctp.h
--
1.8.4.2
^ permalink raw reply
* Re: [PATCH] avrcp: Use NULL for zero pointers
From: Johan Hedberg @ 2014-01-24 11:58 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1390563743-18889-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Fri, Jan 24, 2014, Andrei Emeltchenko wrote:
> ---
> profiles/audio/avrcp.c | 92 +++++++++++++++++++++++++-------------------------
> 1 file changed, 46 insertions(+), 46 deletions(-)
Applied. Thanks.
Johan
^ permalink raw reply
* [PATCH] avrcp: Use NULL for zero pointers
From: Andrei Emeltchenko @ 2014-01-24 11:42 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
profiles/audio/avrcp.c | 92 +++++++++++++++++++++++++-------------------------
1 file changed, 46 insertions(+), 46 deletions(-)
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 197959f..dbeaf38 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -281,72 +281,72 @@ static sdp_record_t *avrcp_ct_record(void)
return NULL;
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
+ root = sdp_list_append(NULL, &root_uuid);
sdp_set_browse_groups(record, root);
/* Service Class ID List */
sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &avrct);
+ svclass_id = sdp_list_append(NULL, &avrct);
sdp_uuid16_create(&avrctr, AV_REMOTE_CONTROLLER_SVCLASS_ID);
svclass_id = sdp_list_append(svclass_id, &avrctr);
sdp_set_service_classes(record, svclass_id);
/* Protocol Descriptor List */
sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap);
+ proto[0] = sdp_list_append(NULL, &l2cap);
psm[0] = sdp_data_alloc(SDP_UINT16, &lp);
proto[0] = sdp_list_append(proto[0], psm[0]);
- apseq = sdp_list_append(0, proto[0]);
+ apseq = sdp_list_append(NULL, proto[0]);
sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto[1] = sdp_list_append(0, &avctp);
+ proto[1] = sdp_list_append(NULL, &avctp);
version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
proto[1] = sdp_list_append(proto[1], version);
apseq = sdp_list_append(apseq, proto[1]);
- aproto = sdp_list_append(0, apseq);
+ aproto = sdp_list_append(NULL, apseq);
sdp_set_access_protos(record, aproto);
/* Additional Protocol Descriptor List */
sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto1[0] = sdp_list_append(0, &l2cap);
+ proto1[0] = sdp_list_append(NULL, &l2cap);
psm[1] = sdp_data_alloc(SDP_UINT16, &ap);
proto1[0] = sdp_list_append(proto1[0], psm[1]);
- apseq1 = sdp_list_append(0, proto1[0]);
+ apseq1 = sdp_list_append(NULL, proto1[0]);
sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto1[1] = sdp_list_append(0, &avctp);
+ proto1[1] = sdp_list_append(NULL, &avctp);
proto1[1] = sdp_list_append(proto1[1], version);
apseq1 = sdp_list_append(apseq1, proto1[1]);
- aproto1 = sdp_list_append(0, apseq1);
+ aproto1 = sdp_list_append(NULL, apseq1);
sdp_set_add_access_protos(record, aproto1);
/* Bluetooth Profile Descriptor List */
sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
profile[0].version = avrcp_ver;
- pfseq = sdp_list_append(0, &profile[0]);
+ pfseq = sdp_list_append(NULL, &profile[0]);
sdp_set_profile_descs(record, pfseq);
features = sdp_data_alloc(SDP_UINT16, &feat);
sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
- sdp_set_info_attr(record, "AVRCP CT", 0, 0);
+ sdp_set_info_attr(record, "AVRCP CT", NULL, NULL);
free(psm[0]);
free(psm[1]);
free(version);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(proto1[0], 0);
- sdp_list_free(proto1[1], 0);
- sdp_list_free(aproto1, 0);
- sdp_list_free(apseq1, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
+ sdp_list_free(proto[0], NULL);
+ sdp_list_free(proto[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(proto1[0], NULL);
+ sdp_list_free(proto1[1], NULL);
+ sdp_list_free(aproto1, NULL);
+ sdp_list_free(apseq1, NULL);
+ sdp_list_free(pfseq, NULL);
+ sdp_list_free(aproto, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
return record;
}
@@ -375,67 +375,67 @@ static sdp_record_t *avrcp_tg_record(void)
return NULL;
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
+ root = sdp_list_append(NULL, &root_uuid);
sdp_set_browse_groups(record, root);
/* Service Class ID List */
sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &avrtg);
+ svclass_id = sdp_list_append(NULL, &avrtg);
sdp_set_service_classes(record, svclass_id);
/* Protocol Descriptor List */
sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto_control[0] = sdp_list_append(0, &l2cap);
+ proto_control[0] = sdp_list_append(NULL, &l2cap);
psm_control = sdp_data_alloc(SDP_UINT16, &lp);
proto_control[0] = sdp_list_append(proto_control[0], psm_control);
- apseq = sdp_list_append(0, proto_control[0]);
+ apseq = sdp_list_append(NULL, proto_control[0]);
sdp_uuid16_create(&avctp, AVCTP_UUID);
- proto_control[1] = sdp_list_append(0, &avctp);
+ proto_control[1] = sdp_list_append(NULL, &avctp);
version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
proto_control[1] = sdp_list_append(proto_control[1], version);
apseq = sdp_list_append(apseq, proto_control[1]);
- aproto_control = sdp_list_append(0, apseq);
+ aproto_control = sdp_list_append(NULL, apseq);
sdp_set_access_protos(record, aproto_control);
- proto_browsing[0] = sdp_list_append(0, &l2cap);
+ proto_browsing[0] = sdp_list_append(NULL, &l2cap);
psm_browsing = sdp_data_alloc(SDP_UINT16, &lp_browsing);
proto_browsing[0] = sdp_list_append(proto_browsing[0], psm_browsing);
- apseq_browsing = sdp_list_append(0, proto_browsing[0]);
+ apseq_browsing = sdp_list_append(NULL, proto_browsing[0]);
- proto_browsing[1] = sdp_list_append(0, &avctp);
+ proto_browsing[1] = sdp_list_append(NULL, &avctp);
proto_browsing[1] = sdp_list_append(proto_browsing[1], version);
apseq_browsing = sdp_list_append(apseq_browsing, proto_browsing[1]);
- aproto_browsing = sdp_list_append(0, apseq_browsing);
+ aproto_browsing = sdp_list_append(NULL, apseq_browsing);
sdp_set_add_access_protos(record, aproto_browsing);
/* Bluetooth Profile Descriptor List */
sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
profile[0].version = avrcp_ver;
- pfseq = sdp_list_append(0, &profile[0]);
+ pfseq = sdp_list_append(NULL, &profile[0]);
sdp_set_profile_descs(record, pfseq);
features = sdp_data_alloc(SDP_UINT16, &feat);
sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
- sdp_set_info_attr(record, "AVRCP TG", 0, 0);
+ sdp_set_info_attr(record, "AVRCP TG", NULL, NULL);
free(psm_browsing);
- sdp_list_free(proto_browsing[0], 0);
- sdp_list_free(proto_browsing[1], 0);
- sdp_list_free(apseq_browsing, 0);
- sdp_list_free(aproto_browsing, 0);
+ sdp_list_free(proto_browsing[0], NULL);
+ sdp_list_free(proto_browsing[1], NULL);
+ sdp_list_free(apseq_browsing, NULL);
+ sdp_list_free(aproto_browsing, NULL);
free(psm_control);
free(version);
- sdp_list_free(proto_control[0], 0);
- sdp_list_free(proto_control[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(aproto_control, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
+ sdp_list_free(proto_control[0], NULL);
+ sdp_list_free(proto_control[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(aproto_control, NULL);
+ sdp_list_free(pfseq, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
return record;
}
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH BlueZ 6/8] android/AVRCP: Add implementation of SDP record
From: Andrei Emeltchenko @ 2014-01-24 11:27 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1390495198-28400-6-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Thu, Jan 23, 2014 at 06:39:56PM +0200, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This adds the following record:
>
> Service Name: AVRCP TG
> Service RecHandle: 0x10002
> Service Class ID List:
> "AV Remote Target" (0x110c)
> Protocol Descriptor List:
> "L2CAP" (0x0100)
> PSM: 23
> "AVCTP" (0x0017)
> uint16: 0x103
> Profile Descriptor List:
> "AV Remote" (0x110e)
> Version: 0x0100
> ---
> android/avrcp.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/android/avrcp.c b/android/avrcp.c
> index 707506b..02dbb68 100644
> --- a/android/avrcp.c
> +++ b/android/avrcp.c
> @@ -29,22 +29,116 @@
> #include <glib.h>
>
> #include "lib/bluetooth.h"
> +#include "lib/sdp.h"
> +#include "lib/sdp_lib.h"
> #include "log.h"
> +#include "bluetooth.h"
> #include "avrcp.h"
> #include "hal-msg.h"
> #include "ipc.h"
>
> +#define L2CAP_PSM_AVCTP 0x17
> +
> +#define AVRCP_FEATURE_CATEGORY_1 0x0001
> +#define AVRCP_FEATURE_CATEGORY_2 0x0002
> +#define AVRCP_FEATURE_CATEGORY_3 0x0004
> +#define AVRCP_FEATURE_CATEGORY_4 0x0008
> +
> static bdaddr_t adapter_addr;
> +static uint32_t record_id = 0;
>
> static const struct ipc_handler cmd_handlers[] = {
> };
>
> +static sdp_record_t *avrcp_record(void)
> +{
> + sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> + uuid_t root_uuid, l2cap, avctp, avrtg;
> + sdp_profile_desc_t profile[1];
> + sdp_list_t *aproto_control, *proto_control[2];
> + sdp_record_t *record;
> + sdp_data_t *psm, *version, *features;
> + uint16_t lp = L2CAP_PSM_AVCTP;
> + uint16_t avrcp_ver = 0x0100, avctp_ver = 0x0103;
> + uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
> + AVRCP_FEATURE_CATEGORY_2 |
> + AVRCP_FEATURE_CATEGORY_3 |
> + AVRCP_FEATURE_CATEGORY_4);
> +
> + record = sdp_record_alloc();
> + if (!record)
> + return NULL;
> +
> + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> + root = sdp_list_append(0, &root_uuid);
Should be NULL here and below.
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH BlueZ 6/8] android/AVRCP: Add implementation of SDP record
From: Andrei Emeltchenko @ 2014-01-24 11:22 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1390495198-28400-6-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Thu, Jan 23, 2014 at 06:39:56PM +0200, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This adds the following record:
>
> Service Name: AVRCP TG
> Service RecHandle: 0x10002
> Service Class ID List:
> "AV Remote Target" (0x110c)
> Protocol Descriptor List:
> "L2CAP" (0x0100)
> PSM: 23
> "AVCTP" (0x0017)
> uint16: 0x103
> Profile Descriptor List:
> "AV Remote" (0x110e)
> Version: 0x0100
> ---
> android/avrcp.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/android/avrcp.c b/android/avrcp.c
> index 707506b..02dbb68 100644
> --- a/android/avrcp.c
> +++ b/android/avrcp.c
> @@ -29,22 +29,116 @@
> #include <glib.h>
>
> #include "lib/bluetooth.h"
> +#include "lib/sdp.h"
> +#include "lib/sdp_lib.h"
> #include "log.h"
> +#include "bluetooth.h"
> #include "avrcp.h"
> #include "hal-msg.h"
> #include "ipc.h"
>
> +#define L2CAP_PSM_AVCTP 0x17
Can we use the same name like in profiles?
AVCTP_CONTROL_PSM
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH] android/hal-audio: Workaround AudioFlinger issues
From: Szymon Janc @ 2014-01-24 10:09 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1390490712-25124-1-git-send-email-andrzej.kaczmarek@tieto.com>
Hi Andrzej,
On Thursday 23 of January 2014 16:25:12 Andrzej Kaczmarek wrote:
> Audio HAL code calculates accurate input stream buffer size which
> allows to fill media packets with as much data as possible. However,
> in most cases calculated buffer size does not work well with Android
> audio code which causes glitches when playing simultaneously to
> different audio output (like notification) or crashes mediaserver
> when disconnecting with headset.
>
> This patch changes input buffer size to fixed magic value 20*512 which
> is used in Bluedroid Audio HAL. Such change requires that we need to
> drop assumption that each input buffer can be used to fill exactly one
> media packet and need to use it to fill multiple media packets. To
> avoid buffering in Audio HAL, we allow that last media packet can be
> filled in non-optimal way, i.e. has less data that can fit.
> ---
> android/hal-audio.c | 86 ++++++++++++++++++++++++++++++++++-------------------
> 1 file changed, 56 insertions(+), 30 deletions(-)
>
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index 4326ccd..f4a4ee1 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -413,6 +413,42 @@ static void sbc_resume(void *codec_data)
> sbc_data->frames_sent = 0;
> }
>
> +static void write_media_packet(int fd, struct sbc_data *sbc_data,
> + struct media_packet *mp, size_t data_len)
> +{
> + struct timespec cur;
> + struct timespec diff;
> + unsigned expected_frames;
> + int ret;
> +
> + ret = write(fd, mp, sizeof(*mp) + data_len);
> + if (ret < 0) {
> + int err = errno;
> + DBG("error writing data: %d (%s)", err,
> + strerror(err));
> + }
> +
> + sbc_data->frames_sent += mp->payload.frame_count;
> +
> + clock_gettime(CLOCK_MONOTONIC, &cur);
> + timespec_diff(&cur, &sbc_data->start, &diff);
> + expected_frames = (diff.tv_sec * 1000000 + diff.tv_nsec / 1000) /
> + sbc_data->frame_duration;
> +
> + /* AudioFlinger does not seem to provide any *working*
> + * API to provide data in some interval and will just
> + * send another buffer as soon as we process current
> + * one. To prevent overflowing L2CAP socket, we need to
> + * introduce some artificial delay here base on how many
> + * audio frames were sent so far, i.e. if we're not
> + * lagging behind audio stream, we can sleep for
> + * duration of single media packet.
> + */
> + if (sbc_data->frames_sent >= expected_frames)
> + usleep(sbc_data->frame_duration *
> + mp->payload.frame_count);
> +}
> +
> static ssize_t sbc_write_data(void *codec_data, const void *buffer,
> size_t bytes, int fd)
> {
> @@ -421,9 +457,6 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
> size_t encoded = 0;
> struct media_packet *mp = (struct media_packet *) sbc_data->out_buf;
> size_t free_space = sbc_data->out_buf_size - sizeof(*mp);
> - struct timespec cur;
> - struct timespec diff;
> - unsigned expected_frames;
> int ret;
>
> mp->hdr.v = 2;
> @@ -450,39 +483,28 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
> consumed += ret;
> encoded += written;
> free_space -= written;
> - }
>
> - ret = write(fd, mp, sizeof(*mp) + encoded);
> - if (ret < 0) {
> - int err = errno;
> - DBG("error writing data: %d (%s)", err, strerror(err));
> + /* write data if we either filled media packed or encoded all
> + * input data
> + */
> + if (mp->payload.frame_count == sbc_data->frames_per_packet ||
> + bytes == consumed) {
> + write_media_packet(fd, sbc_data, mp, encoded);
> +
> + encoded = 0;
> + free_space = sbc_data->out_buf_size - sizeof(*mp);
> + mp->payload.frame_count = 0;
> + }
> }
>
> - if (consumed != bytes || free_space != 0) {
> - /* we should encode all input data and fill output buffer
> + if (consumed != bytes) {
> + /* we should encode all input data
> * if we did not, something went wrong but we can't really
> * handle this so this is just sanity check
> */
> DBG("some data were not encoded");
> }
>
> - sbc_data->frames_sent += mp->payload.frame_count;
> -
> - clock_gettime(CLOCK_MONOTONIC, &cur);
> - timespec_diff(&cur, &sbc_data->start, &diff);
> - expected_frames = (diff.tv_sec * 1000000 + diff.tv_nsec / 1000) /
> - sbc_data->frame_duration;
> -
> - /* AudioFlinger does not seem to provide any *working* API to provide
> - * data in some interval and will just send another buffer as soon as
> - * we process current one. To prevent overflowing L2CAP socket, we need
> - * to introduce some artificial delay here base on how many audio frames
> - * were sent so far, i.e. if we're not lagging behind audio stream, we
> - * can sleep for duration of single media packet.
> - */
> - if (sbc_data->frames_sent >= expected_frames)
> - usleep(sbc_data->frame_duration * mp->payload.frame_count);
> -
> /* we always assume that all data was processed and sent */
> return bytes;
> }
> @@ -853,11 +875,15 @@ static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
>
> static size_t out_get_buffer_size(const struct audio_stream *stream)
> {
> - struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
> -
> DBG("");
>
> - return out->ep->codec->get_buffer_size(out->ep->codec_data);
> + /* We should return proper buffer size calculated by codec (so each
> + * input buffer is encoded into single media packed) but this does not
> + * work well with AudioFlinger and causes problems. For this reason we
> + * use magic value here and out_write code takes care of splitting
> + * input buffer into multiple media packets.
> + */
> + return 20 * 512;
> }
>
> static uint32_t out_get_channels(const struct audio_stream *stream)
>
Pushed, thanks.
--
Best regards,
Szymon Janc
^ permalink raw reply
* Re: [PATCH v2 2/2] Bluetooth: Switch ATT channels to use L2CAP_CHAN_FIXED
From: Marcel Holtmann @ 2014-01-24 8:46 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390552541-11729-2-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> ATT channels are not connection oriented so having them use
> L2CAP_CHAN_CONN_ORIENTED is quite confusing. Instead, use the new
> L2CAP_CHAN_FIXED type and ensure that the MTU and CID values get
> properly set.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/l2cap_core.c | 21 +++++++++------------
> net/bluetooth/l2cap_sock.c | 9 +++++++++
> 2 files changed, 18 insertions(+), 12 deletions(-)
patch has been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH v2 1/2] Bluetooth: Rename L2CAP_CHAN_CONN_FIX_A2MP to L2CAP_CHAN_FIXED
From: Marcel Holtmann @ 2014-01-24 8:45 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390552541-11729-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> There's no reason why A2MP should need or deserve its on channel type.
> Instead we should be able to group all fixed CID users under a single
> channel type and reuse as much code as possible for them. Where CID
> specific exceptions are needed the chan-scid value can be used.
>
> This patch renames the current A2MP channel type to a generic one and
> thereby paves the way to allow converting ATT and SMP (and any future
> fixed channel protocols) to use the new channel type.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/l2cap.h | 2 +-
> net/bluetooth/a2mp.c | 8 ++++++--
> net/bluetooth/l2cap_core.c | 15 ++++++---------
> 3 files changed, 13 insertions(+), 12 deletions(-)
patch has been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* [PATCH v2 2/2] Bluetooth: Switch ATT channels to use L2CAP_CHAN_FIXED
From: johan.hedberg @ 2014-01-24 8:35 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390552541-11729-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
ATT channels are not connection oriented so having them use
L2CAP_CHAN_CONN_ORIENTED is quite confusing. Instead, use the new
L2CAP_CHAN_FIXED type and ensure that the MTU and CID values get
properly set.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/l2cap_core.c | 21 +++++++++------------
net/bluetooth/l2cap_sock.c | 9 +++++++++
2 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index cd28057d2903..e5c5c7427c41 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -498,18 +498,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
switch (chan->chan_type) {
case L2CAP_CHAN_CONN_ORIENTED:
- if (conn->hcon->type == LE_LINK) {
- if (chan->dcid == L2CAP_CID_ATT) {
- chan->omtu = L2CAP_DEFAULT_MTU;
- chan->scid = L2CAP_CID_ATT;
- } else {
- chan->scid = l2cap_alloc_cid(conn);
- }
- } else {
- /* Alloc CID for connection-oriented socket */
- chan->scid = l2cap_alloc_cid(conn);
+ /* Alloc CID for connection-oriented socket */
+ chan->scid = l2cap_alloc_cid(conn);
+ if (conn->hcon->type == ACL_LINK)
chan->omtu = L2CAP_DEFAULT_MTU;
- }
break;
case L2CAP_CHAN_CONN_LESS:
@@ -7025,7 +7017,12 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
goto done;
}
- if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
+ if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
+ err = -EINVAL;
+ goto done;
+ }
+
+ if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
err = -EINVAL;
goto done;
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 4aa6704f0b33..3f8e2a223474 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -101,6 +101,15 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
return -EINVAL;
+ if (la.l2_cid) {
+ /* When the socket gets created it defaults to
+ * CHAN_CONN_ORIENTED, so we need to overwrite the
+ * default here.
+ */
+ chan->chan_type = L2CAP_CHAN_FIXED;
+ chan->omtu = L2CAP_DEFAULT_MTU;
+ }
+
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
if (!enable_lecoc && la.l2_psm)
return -EINVAL;
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 1/2] Bluetooth: Rename L2CAP_CHAN_CONN_FIX_A2MP to L2CAP_CHAN_FIXED
From: johan.hedberg @ 2014-01-24 8:35 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
There's no reason why A2MP should need or deserve its on channel type.
Instead we should be able to group all fixed CID users under a single
channel type and reuse as much code as possible for them. Where CID
specific exceptions are needed the chan-scid value can be used.
This patch renames the current A2MP channel type to a generic one and
thereby paves the way to allow converting ATT and SMP (and any future
fixed channel protocols) to use the new channel type.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/l2cap.h | 2 +-
net/bluetooth/a2mp.c | 8 ++++++--
net/bluetooth/l2cap_core.c | 15 ++++++---------
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 85cf40acc47e..ae482f41594a 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -651,7 +651,7 @@ struct l2cap_user {
#define L2CAP_CHAN_RAW 1
#define L2CAP_CHAN_CONN_LESS 2
#define L2CAP_CHAN_CONN_ORIENTED 3
-#define L2CAP_CHAN_CONN_FIX_A2MP 4
+#define L2CAP_CHAN_FIXED 4
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index efcd108822c4..f986b9968bdb 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -235,7 +235,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
BT_DBG("chan %p state %s", chan,
state_to_string(chan->state));
- if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
+ if (chan->scid == L2CAP_CID_A2MP)
continue;
l2cap_chan_lock(chan);
@@ -726,7 +726,11 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
BT_DBG("chan %p", chan);
- chan->chan_type = L2CAP_CHAN_CONN_FIX_A2MP;
+ chan->chan_type = L2CAP_CHAN_FIXED;
+ chan->scid = L2CAP_CID_A2MP;
+ chan->dcid = L2CAP_CID_A2MP;
+ chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
+ chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
chan->ops = &a2mp_chan_ops;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 138394ad3e51..cd28057d2903 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -519,11 +519,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
chan->omtu = L2CAP_DEFAULT_MTU;
break;
- case L2CAP_CHAN_CONN_FIX_A2MP:
- chan->scid = L2CAP_CID_A2MP;
- chan->dcid = L2CAP_CID_A2MP;
- chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
- chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
+ case L2CAP_CHAN_FIXED:
+ /* Caller will set CID and CID specific MTU values */
break;
default:
@@ -571,7 +568,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
chan->conn = NULL;
- if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
+ if (chan->scid != L2CAP_CID_A2MP)
hci_conn_drop(conn->hcon);
if (mgr && mgr->bredr_chan == chan)
@@ -1310,7 +1307,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
__clear_ack_timer(chan);
}
- if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
+ if (chan->scid == L2CAP_CID_A2MP) {
l2cap_state_change(chan, BT_DISCONN);
return;
}
@@ -1508,7 +1505,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
l2cap_chan_lock(chan);
- if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
+ if (chan->scid == L2CAP_CID_A2MP) {
l2cap_chan_unlock(chan);
continue;
}
@@ -7245,7 +7242,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
state_to_string(chan->state));
- if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
+ if (chan->scid == L2CAP_CID_A2MP) {
l2cap_chan_unlock(chan);
continue;
}
--
1.8.5.3
^ permalink raw reply related
* Re: [PATCH 1/2] Bluetooth: Rename L2CAP_CHAN_CONN_FIX_A2MP to L2CAP_CHAN_FIXED_CID
From: Johan Hedberg @ 2014-01-24 8:29 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: BlueZ development
In-Reply-To: <9D839443-6517-49AA-81E4-F4D744F82635@holtmann.org>
Hi Marcel,
On Thu, Jan 23, 2014, Marcel Holtmann wrote:
> > There's no reason why A2DP should need or deserve its on channel type.
>
> I assume you mean A2MP here?
>
> > Instead we should be able to group all fixed CID users under a single
> > channel type and reuse as much code as possible for them. Where CID
> > specific exceptions are needed the chan-scid value can be used.
> >
> > This patch renames the current A2DP channel type to a generic one and
>
> Same here.
Yep. Seems like typing A2DP is somehow hardwired into my brain after so
many years.
> > -#define L2CAP_CHAN_CONN_FIX_A2MP 4
> > +#define L2CAP_CHAN_FIXED_CID 4
>
> You want to use FIXED_CID instead of just FIXED. I am fine with
> FIXED_CID, just double checking here.
I was thinking of it as "channel with a fixed CID", however now that I
re-read the Core Spec it talks about "Fixed Channels", so I'll change
this simply to CHAN_FIXED.
Johan
^ permalink raw reply
* Paired LE HoG devices are unable to reconnect to BlueZ host when discovery is active
From: Petri Gynther @ 2014-01-24 5:21 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org development
With BlueZ 5.13, I've noticed that previously paired LE HoG devices
are unable to reconnect to the host when device discovery is active on
the BT interface.
Steps to reproduce:
1. Pair LE HoG device with BlueZ 5.13 host.
2. Verify that keypresses from HoG device are delivered to uHID input pipeline.
3. Let HoG device disconnect from host (due to inactivity timeout).
4. Press key on HoG device. At this point, it reconnects to host fine.
5. Let HoG device disconnect from host again.
6. Start "test-discovery" script.
7. Press key on HoG device => it does not reconnect to host.
8. Kill "test-discovery" script.
9. Press key on HoG device => it now reconnects to host successfully.
It looks to me that the root cause is in src/adapter.c:update_found_devices()
/*
* Only if at least one client has requested discovery, maintain
* list of found devices and name confirming for legacy devices.
* Otherwise, this is an event from passive discovery and we
* should check if the device needs connecting to.
*/
if (!adapter->discovery_list)
goto connect_le;
if (g_slist_find(adapter->discovery_found, dev))
return;
When (active) discovery is on, adapter->discovery_list != NULL, and
g_slist_find(adapter->discovery_found, dev) will obviously find this
device since it is already paired. So, we end up returning from the
function without an attempt to reconnect to the previously paired LE
device.
What would be the right fix here? Stop discovery before attempting to
reconnect to the LE device?
^ permalink raw reply
* Re: [PATCH 2/2] Bluetooth: Switch ATT channels to use L2CAP_CHAN_FIXED_CID
From: Marcel Holtmann @ 2014-01-24 0:52 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390483368-21321-2-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> ATT channels are not connection oriented so having them use
> L2CAP_CHAN_CONN_ORIENTED is quite confusing. Instead, use the new
> L2CAP_CHAN_FIXED_CID type and ensure that the MTU and CID values get
> properly set.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/l2cap_core.c | 21 +++++++++------------
> net/bluetooth/l2cap_sock.c | 6 ++++++
> 2 files changed, 15 insertions(+), 12 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 84714541b48c..c5c47667bfe0 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -498,18 +498,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
>
> switch (chan->chan_type) {
> case L2CAP_CHAN_CONN_ORIENTED:
> - if (conn->hcon->type == LE_LINK) {
> - if (chan->dcid == L2CAP_CID_ATT) {
> - chan->omtu = L2CAP_DEFAULT_MTU;
> - chan->scid = L2CAP_CID_ATT;
> - } else {
> - chan->scid = l2cap_alloc_cid(conn);
> - }
> - } else {
> - /* Alloc CID for connection-oriented socket */
> - chan->scid = l2cap_alloc_cid(conn);
> + /* Alloc CID for connection-oriented socket */
> + chan->scid = l2cap_alloc_cid(conn);
> + if (conn->hcon->type == ACL_LINK)
> chan->omtu = L2CAP_DEFAULT_MTU;
> - }
> break;
>
> case L2CAP_CHAN_CONN_LESS:
> @@ -7025,7 +7017,12 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
> goto done;
> }
>
> - if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
> + if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
> + err = -EINVAL;
> + goto done;
> + }
> +
> + if (chan->chan_type == L2CAP_CHAN_FIXED_CID && !cid) {
> err = -EINVAL;
> goto done;
> }
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index 4aa6704f0b33..45064d130308 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -101,6 +101,12 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
> if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
> return -EINVAL;
>
> + if (la.l2_cid) {
> + /* Update type from the default CONN_ORIENTED */
I think that I understand your comment intention here, but we might want to make it less cryptic and actually spell out that this changed the channel type to overwrite the default.
> + chan->chan_type = L2CAP_CHAN_FIXED_CID;
> + chan->omtu = L2CAP_DEFAULT_MTU;
> + }
> +
> if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
> if (!enable_lecoc && la.l2_psm)
> return -EINVAL;
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/2] Bluetooth: Rename L2CAP_CHAN_CONN_FIX_A2MP to L2CAP_CHAN_FIXED_CID
From: Marcel Holtmann @ 2014-01-24 0:50 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390483368-21321-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> There's no reason why A2DP should need or deserve its on channel type.
I assume you mean A2MP here?
> Instead we should be able to group all fixed CID users under a single
> channel type and reuse as much code as possible for them. Where CID
> specific exceptions are needed the chan-scid value can be used.
>
> This patch renames the current A2DP channel type to a generic one and
Same here.
> thereby paves the way to allow converting ATT and SMP (and any future
> fixed channel protocols) to use the new channel type.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/l2cap.h | 2 +-
> net/bluetooth/a2mp.c | 8 ++++++--
> net/bluetooth/l2cap_core.c | 15 ++++++---------
> 3 files changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 85cf40acc47e..eeb02f414255 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -651,7 +651,7 @@ struct l2cap_user {
> #define L2CAP_CHAN_RAW 1
> #define L2CAP_CHAN_CONN_LESS 2
> #define L2CAP_CHAN_CONN_ORIENTED 3
> -#define L2CAP_CHAN_CONN_FIX_A2MP 4
> +#define L2CAP_CHAN_FIXED_CID 4
You want to use FIXED_CID instead of just FIXED. I am fine with FIXED_CID, just double checking here.
> /* ----- L2CAP socket info ----- */
> #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
> diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
> index efcd108822c4..677b970cede6 100644
> --- a/net/bluetooth/a2mp.c
> +++ b/net/bluetooth/a2mp.c
> @@ -235,7 +235,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
> BT_DBG("chan %p state %s", chan,
> state_to_string(chan->state));
>
> - if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP)
> + if (chan->scid == L2CAP_CID_A2MP)
> continue;
>
> l2cap_chan_lock(chan);
> @@ -726,7 +726,11 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
>
> BT_DBG("chan %p", chan);
>
> - chan->chan_type = L2CAP_CHAN_CONN_FIX_A2MP;
> + chan->chan_type = L2CAP_CHAN_FIXED_CID;
> + chan->scid = L2CAP_CID_A2MP;
> + chan->dcid = L2CAP_CID_A2MP;
> + chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
> + chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
> chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
>
> chan->ops = &a2mp_chan_ops;
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 138394ad3e51..84714541b48c 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -519,11 +519,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
> chan->omtu = L2CAP_DEFAULT_MTU;
> break;
>
> - case L2CAP_CHAN_CONN_FIX_A2MP:
> - chan->scid = L2CAP_CID_A2MP;
> - chan->dcid = L2CAP_CID_A2MP;
> - chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
> - chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
> + case L2CAP_CHAN_FIXED_CID:
> + /* Caller will set CID and CID specific MTU values */
> break;
>
> default:
> @@ -571,7 +568,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
>
> chan->conn = NULL;
>
> - if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
> + if (chan->scid != L2CAP_CID_A2MP)
> hci_conn_drop(conn->hcon);
>
> if (mgr && mgr->bredr_chan == chan)
> @@ -1310,7 +1307,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
> __clear_ack_timer(chan);
> }
>
> - if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
> + if (chan->scid == L2CAP_CID_A2MP) {
> l2cap_state_change(chan, BT_DISCONN);
> return;
> }
> @@ -1508,7 +1505,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
>
> l2cap_chan_lock(chan);
>
> - if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
> + if (chan->scid == L2CAP_CID_A2MP) {
> l2cap_chan_unlock(chan);
> continue;
> }
> @@ -7245,7 +7242,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
> BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
> state_to_string(chan->state));
>
> - if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
> + if (chan->scid == L2CAP_CID_A2MP) {
> l2cap_chan_unlock(chan);
> continue;
> }
Rest look fine to me.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/9] android/ipc-tester: Add cases for SOCK msg size
From: Szymon Janc @ 2014-01-23 23:25 UTC (permalink / raw)
To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1390379124-16426-1-git-send-email-jakub.tyszkowski@tieto.com>
Hi Jakub,
On Wednesday 22 January 2014 09:25:16 Jakub Tyszkowski wrote:
> Add cases testing message size verification for SOCK opcodes.
> ---
> android/ipc-tester.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/android/ipc-tester.c b/android/ipc-tester.c
> index ed0dd10..088c324 100644
> --- a/android/ipc-tester.c
> +++ b/android/ipc-tester.c
> @@ -864,5 +864,23 @@ int main(int argc, char *argv[])
> sizeof(struct hal_cmd_le_test_mode), -1,
> HAL_SERVICE_ID_BLUETOOTH);
>
> + /* check for valid data size for SOCK */
> + test_datasize_valid("SOCK Listen+", HAL_SERVICE_ID_SOCK,
> + HAL_OP_SOCK_LISTEN,
> + sizeof(struct hal_cmd_sock_listen), 1,
> + HAL_SERVICE_ID_BLUETOOTH, HAL_SERVICE_ID_SOCK);
> + test_datasize_valid("SOCK Listen-", HAL_SERVICE_ID_SOCK,
> + HAL_OP_SOCK_LISTEN,
> + sizeof(struct hal_cmd_sock_listen), -1,
> + HAL_SERVICE_ID_BLUETOOTH, HAL_SERVICE_ID_SOCK);
> + test_datasize_valid("SOCK Connect+", HAL_SERVICE_ID_SOCK,
> + HAL_OP_SOCK_CONNECT,
> + sizeof(struct hal_cmd_sock_connect), 1,
> + HAL_SERVICE_ID_BLUETOOTH, HAL_SERVICE_ID_SOCK);
> + test_datasize_valid("SOCK Connect-", HAL_SERVICE_ID_SOCK,
> + HAL_OP_SOCK_CONNECT,
> + sizeof(struct hal_cmd_sock_connect), -1,
> + HAL_SERVICE_ID_BLUETOOTH, HAL_SERVICE_ID_SOCK);
> +
> return tester_run();
> }
All patches in this set have been applied, thanks.
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* [PATCH v3 5/5] android/bluetooth: Rename devices list to cached_devices
From: Szymon Janc @ 2014-01-23 22:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1390515490-29538-1-git-send-email-szymon.janc@gmail.com>
This makes it clear what is the purpose of this list.
---
android/bluetooth.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 126b26a..a9e529f 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -140,7 +140,7 @@ static uint16_t option_index = MGMT_INDEX_NONE;
static struct mgmt *mgmt_if = NULL;
static GSList *bonded_devices = NULL;
-static GSList *devices = NULL;
+static GSList *cached_devices = NULL;
/* This list contains addresses which are asked for records */
static GSList *browse_reqs;
@@ -300,7 +300,7 @@ static struct device *find_device(const bdaddr_t *bdaddr)
if (l)
return l->data;
- l = g_slist_find_custom(devices, bdaddr, device_match);
+ l = g_slist_find_custom(cached_devices, bdaddr, device_match);
if (l)
return l->data;
@@ -320,24 +320,24 @@ static void cache_device(struct device *new_dev)
struct device *dev;
GSList *l;
- l = g_slist_find(devices, new_dev);
+ l = g_slist_find(cached_devices, new_dev);
if (l) {
- devices = g_slist_remove(devices, new_dev);
+ cached_devices = g_slist_remove(cached_devices, new_dev);
goto cache;
}
- if (g_slist_length(devices) < DEVICES_CACHE_MAX)
+ if (g_slist_length(cached_devices) < DEVICES_CACHE_MAX)
goto cache;
- l = g_slist_last(devices);
+ l = g_slist_last(cached_devices);
dev = l->data;
- devices = g_slist_remove(devices, dev);
+ cached_devices = g_slist_remove(cached_devices, dev);
remove_device_info(dev, CACHE_FILE);
free_device(dev);
cache:
- devices = g_slist_prepend(devices, new_dev);
+ cached_devices = g_slist_prepend(cached_devices, new_dev);
new_dev->timestamp = time(NULL);
store_device_info(new_dev, CACHE_FILE);
}
@@ -617,7 +617,7 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
}
break;
case HAL_BOND_STATE_BONDED:
- devices = g_slist_remove(devices, dev);
+ cached_devices = g_slist_remove(cached_devices, dev);
bonded_devices = g_slist_prepend(bonded_devices, dev);
remove_device_info(dev, CACHE_FILE);
store_device_info(dev, DEVICES_FILE);
@@ -1004,7 +1004,7 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
cp.state = HAL_DISCOVERY_STATE_STARTED;
} else {
g_slist_foreach(bonded_devices, clear_device_found, NULL);
- g_slist_foreach(devices, clear_device_found, NULL);
+ g_slist_foreach(cached_devices, clear_device_found, NULL);
cp.state = HAL_DISCOVERY_STATE_STOPPED;
}
@@ -1794,10 +1794,10 @@ static void load_devices_cache(void)
struct device *dev;
dev = create_device_from_info(key_file, devs[i]);
- devices = g_slist_prepend(devices, dev);
+ cached_devices = g_slist_prepend(cached_devices, dev);
}
- devices = g_slist_sort(devices, device_timestamp_cmp);
+ cached_devices = g_slist_sort(cached_devices, device_timestamp_cmp);
g_strfreev(devs);
g_key_file_free(key_file);
@@ -3213,8 +3213,8 @@ void bt_bluetooth_unregister(void)
g_slist_free_full(bonded_devices, (GDestroyNotify) free_device);
bonded_devices = NULL;
- g_slist_free_full(devices, (GDestroyNotify) free_device);
- devices = NULL;
+ g_slist_free_full(cached_devices, (GDestroyNotify) free_device);
+ cached_devices = NULL;
ipc_unregister(HAL_SERVICE_ID_CORE);
}
--
1.8.5.3
^ permalink raw reply related
* [PATCH v3 4/5] android/bluetooth: Add support for loading caches devices from storage
From: Szymon Janc @ 2014-01-23 22:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1390515490-29538-1-git-send-email-szymon.janc@gmail.com>
From: Szymon Janc <szymon.janc@tieto.com>
Info is now stored for all devices and bond state depends on file.
Based on that devices loaded from storage are put either to cache
or to bonded_devices list.
---
android/bluetooth.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 54 insertions(+), 5 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index cf2dc83..126b26a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1679,7 +1679,8 @@ static void clear_uuids(void)
sizeof(cp), &cp, NULL, NULL, NULL);
}
-static void create_device_from_info(GKeyFile *key_file, const char *peer)
+static struct device *create_device_from_info(GKeyFile *key_file,
+ const char *peer)
{
struct device *dev;
uint8_t type;
@@ -1694,7 +1695,11 @@ static void create_device_from_info(GKeyFile *key_file, const char *peer)
str2ba(peer, &bdaddr);
dev = create_device(&bdaddr, type);
- dev->bond_state = HAL_BOND_STATE_BONDED;
+ str = g_key_file_get_string(key_file, peer, "LinkKey", NULL);
+ if (str) {
+ g_free(str);
+ dev->bond_state = HAL_BOND_STATE_BONDED;
+ }
str = g_key_file_get_string(key_file, peer, "Name", NULL);
if (str) {
@@ -1730,6 +1735,8 @@ static void create_device_from_info(GKeyFile *key_file, const char *peer)
g_strfreev(uuids);
}
+
+ return dev;
}
static struct mgmt_link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
@@ -1762,6 +1769,40 @@ failed:
return info;
}
+static int device_timestamp_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct device *deva = a;
+ const struct device *devb = b;
+
+ return deva->timestamp < devb->timestamp;
+}
+
+static void load_devices_cache(void)
+{
+ GKeyFile *key_file;
+ gchar **devs;
+ gsize len = 0;
+ unsigned int i;
+
+ key_file = g_key_file_new();
+
+ g_key_file_load_from_file(key_file, CACHE_FILE, 0, NULL);
+
+ devs = g_key_file_get_groups(key_file, &len);
+
+ for (i = 0; i < len; i++) {
+ struct device *dev;
+
+ dev = create_device_from_info(key_file, devs[i]);
+ devices = g_slist_prepend(devices, dev);
+ }
+
+ devices = g_slist_sort(devices, device_timestamp_cmp);
+
+ g_strfreev(devs);
+ g_key_file_free(key_file);
+}
+
static void load_devices_info(bt_bluetooth_ready cb)
{
GKeyFile *key_file;
@@ -1778,14 +1819,21 @@ static void load_devices_info(bt_bluetooth_ready cb)
for (i = 0; i < len; i++) {
struct mgmt_link_key_info *key_info;
+ struct device *dev;
- create_device_from_info(key_file, devs[i]);
+ dev = create_device_from_info(key_file, devs[i]);
key_info = get_key_info(key_file, devs[i]);
- if (key_info)
- keys = g_slist_prepend(keys, key_info);
+ if (!key_info) {
+ error("Failed to load linkkey for %s, skipping",
+ devs[i]);
+ continue;
+ }
/* TODO ltk */
+
+ keys = g_slist_prepend(keys, key_info);
+ bonded_devices = g_slist_prepend(bonded_devices, dev);
}
load_link_keys(keys, cb);
@@ -1873,6 +1921,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
clear_uuids();
load_devices_info(cb);
+ load_devices_cache();
set_io_capability();
set_device_id();
--
1.8.5.3
^ permalink raw reply related
* [PATCH v3 3/5] android/bluetooth: Add support for caching remote device info
From: Szymon Janc @ 2014-01-23 22:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1390515490-29538-1-git-send-email-szymon.janc@gmail.com>
From: Szymon Janc <szymon.janc@tieto.com>
Cache is limited to DEVICES_CACHE_MAX. Devices are sorted with
timestamp so if cache is full olderst device is removed.
---
android/bluetooth.c | 115 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 82 insertions(+), 33 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index f5ac0e4..cf2dc83 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -56,6 +56,7 @@
#define SETTINGS_FILE ANDROID_STORAGEDIR"/settings"
#define DEVICES_FILE ANDROID_STORAGEDIR"/devices"
+#define CACHE_FILE ANDROID_STORAGEDIR"/cache"
#define DEVICE_ID_SOURCE 0x0002 /* USB */
#define DEVICE_ID_VENDOR 0x1d6b /* Linux Foundation */
@@ -70,6 +71,8 @@
/* Default discoverable timeout 120sec as in Android */
#define DEFAULT_DISCOVERABLE_TIMEOUT 120
+#define DEVICES_CACHE_MAX 300
+
#define BASELEN_PROP_CHANGED (sizeof(struct hal_ev_adapter_props_changed) \
+ (sizeof(struct hal_property)))
@@ -199,7 +202,7 @@ static void load_adapter_config(void)
g_key_file_free(key_file);
}
-static void store_device_info(struct device *dev)
+static void store_device_info(struct device *dev, const char *path)
{
GKeyFile *key_file;
char addr[18];
@@ -207,22 +210,10 @@ static void store_device_info(struct device *dev)
char **uuids = NULL;
char *str;
- /* We only store bonded devices and need to modify the storage
- * if the state is either NONE or BONDED.
- */
- if (dev->bond_state != HAL_BOND_STATE_BONDED &&
- dev->bond_state != HAL_BOND_STATE_NONE)
- return;
-
ba2str(&dev->bdaddr, addr);
key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
-
- if (dev->bond_state == HAL_BOND_STATE_NONE) {
- g_key_file_remove_group(key_file, addr, NULL);
- goto done;
- }
+ g_key_file_load_from_file(key_file, path, 0, NULL);
g_key_file_set_integer(key_file, addr, "Type", dev->bdaddr_type);
@@ -264,15 +255,35 @@ static void store_device_info(struct device *dev)
g_key_file_remove_key(key_file, addr, "Services", NULL);
}
-done:
str = g_key_file_to_data(key_file, &length, NULL);
- g_file_set_contents(DEVICES_FILE, str, length, NULL);
+ g_file_set_contents(path, str, length, NULL);
g_free(str);
g_key_file_free(key_file);
g_strfreev(uuids);
}
+static void remove_device_info(struct device *dev, const char *path)
+{
+ GKeyFile *key_file;
+ gsize length = 0;
+ char addr[18];
+ char *str;
+
+ ba2str(&dev->bdaddr, addr);
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, path, 0, NULL);
+
+ g_key_file_remove_group(key_file, addr, NULL);
+
+ str = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(path, str, length, NULL);
+ g_free(str);
+
+ g_key_file_free(key_file);
+}
+
static int device_match(gconstpointer a, gconstpointer b)
{
const struct device *dev = a;
@@ -296,6 +307,41 @@ static struct device *find_device(const bdaddr_t *bdaddr)
return NULL;
}
+static void free_device(struct device *dev)
+{
+ g_free(dev->name);
+ g_free(dev->friendly_name);
+ g_slist_free_full(dev->uuids, g_free);
+ g_free(dev);
+}
+
+static void cache_device(struct device *new_dev)
+{
+ struct device *dev;
+ GSList *l;
+
+ l = g_slist_find(devices, new_dev);
+ if (l) {
+ devices = g_slist_remove(devices, new_dev);
+ goto cache;
+ }
+
+ if (g_slist_length(devices) < DEVICES_CACHE_MAX)
+ goto cache;
+
+ l = g_slist_last(devices);
+ dev = l->data;
+
+ devices = g_slist_remove(devices, dev);
+ remove_device_info(dev, CACHE_FILE);
+ free_device(dev);
+
+cache:
+ devices = g_slist_prepend(devices, new_dev);
+ new_dev->timestamp = time(NULL);
+ store_device_info(new_dev, CACHE_FILE);
+}
+
static struct device *create_device(const bdaddr_t *bdaddr, uint8_t type)
{
struct device *dev;
@@ -314,19 +360,10 @@ static struct device *create_device(const bdaddr_t *bdaddr, uint8_t type)
/* use address for name, will be change if one is present
* eg. in EIR or set by set_property. */
dev->name = g_strdup(addr);
- devices = g_slist_prepend(devices, dev);
return dev;
}
-static void free_device(struct device *dev)
-{
- g_free(dev->name);
- g_free(dev->friendly_name);
- g_slist_free_full(dev->uuids, g_free);
- g_free(dev);
-}
-
static struct device *get_device(const bdaddr_t *bdaddr, uint8_t type)
{
struct device *dev;
@@ -335,7 +372,11 @@ static struct device *get_device(const bdaddr_t *bdaddr, uint8_t type)
if (dev)
return dev;
- return create_device(bdaddr, type);
+ dev = create_device(bdaddr, type);
+
+ cache_device(dev);
+
+ return dev;
}
static void send_adapter_property(uint8_t type, uint16_t len, const void *val)
@@ -571,12 +612,15 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
case HAL_BOND_STATE_NONE:
if (dev->bond_state == HAL_BOND_STATE_BONDED) {
bonded_devices = g_slist_remove(bonded_devices, dev);
- devices = g_slist_prepend(devices, dev);
+ remove_device_info(dev, DEVICES_FILE);
+ cache_device(dev);
}
break;
case HAL_BOND_STATE_BONDED:
devices = g_slist_remove(devices, dev);
bonded_devices = g_slist_prepend(bonded_devices, dev);
+ remove_device_info(dev, CACHE_FILE);
+ store_device_info(dev, DEVICES_FILE);
break;
case HAL_BOND_STATE_BONDING:
default:
@@ -585,8 +629,6 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
dev->bond_state = state;
- store_device_info(dev);
-
send_bond_state_change(&dev->bdaddr, status, state);
}
@@ -627,7 +669,10 @@ static void set_device_uuids(struct device *dev, GSList *uuids)
g_slist_free_full(dev->uuids, g_free);
dev->uuids = uuids;
- store_device_info(dev);
+ if (dev->bond_state == HAL_BOND_STATE_BONDED)
+ store_device_info(dev, DEVICES_FILE);
+ else
+ store_device_info(dev, CACHE_FILE);
send_device_uuids_notif(dev);
}
@@ -1058,8 +1103,6 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
ev->status = HAL_STATUS_SUCCESS;
bdaddr2android(bdaddr, ev->bdaddr);
-
- dev->timestamp = time(NULL);
}
if (eir.class) {
@@ -1087,6 +1130,9 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,
(*num_prop)++;
}
+ if (dev->bond_state != HAL_BOND_STATE_BONDED)
+ cache_device(dev);
+
if (*num_prop)
ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, opcode, size, buf);
@@ -2860,7 +2906,10 @@ static uint8_t set_device_friendly_name(struct device *dev, const uint8_t *val,
g_free(dev->friendly_name);
dev->friendly_name = g_strndup((const char *) val, len);
- store_device_info(dev);
+ if (dev->bond_state == HAL_BOND_STATE_BONDED)
+ store_device_info(dev, DEVICES_FILE);
+ else
+ store_device_info(dev, CACHE_FILE);
send_device_property(&dev->bdaddr, HAL_PROP_DEVICE_FRIENDLY_NAME,
strlen(dev->friendly_name), dev->friendly_name);
--
1.8.5.3
^ permalink raw reply related
* [PATCH v3 2/5] android/bluetooth: Use defines for settings and devices files paths
From: Szymon Janc @ 2014-01-23 22:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1390515490-29538-1-git-send-email-szymon.janc@gmail.com>
---
android/bluetooth.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 5d222e1..f5ac0e4 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -54,6 +54,9 @@
#define DUT_MODE_FILE "/sys/kernel/debug/bluetooth/hci%u/dut_mode"
+#define SETTINGS_FILE ANDROID_STORAGEDIR"/settings"
+#define DEVICES_FILE ANDROID_STORAGEDIR"/devices"
+
#define DEVICE_ID_SOURCE 0x0002 /* USB */
#define DEVICE_ID_VENDOR 0x1d6b /* Linux Foundation */
#define DEVICE_ID_PRODUCT 0x0247 /* BlueZ for Android */
@@ -148,8 +151,7 @@ static void store_adapter_config(void)
key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings", 0,
- NULL);
+ g_key_file_load_from_file(key_file, SETTINGS_FILE, 0, NULL);
ba2str(&adapter.bdaddr, addr);
@@ -160,7 +162,7 @@ static void store_adapter_config(void)
data = g_key_file_to_data(key_file, &length, NULL);
- g_file_set_contents(ANDROID_STORAGEDIR"/settings", data, length, NULL);
+ g_file_set_contents(SETTINGS_FILE, data, length, NULL);
g_free(data);
g_key_file_free(key_file);
@@ -173,8 +175,7 @@ static void load_adapter_config(void)
char *str;
key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/settings", 0,
- NULL);
+ g_key_file_load_from_file(key_file, SETTINGS_FILE, 0, NULL);
str = g_key_file_get_string(key_file, "General", "Address", NULL);
if (!str) {
@@ -216,8 +217,7 @@ static void store_device_info(struct device *dev)
ba2str(&dev->bdaddr, addr);
key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
- NULL);
+ g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
if (dev->bond_state == HAL_BOND_STATE_NONE) {
g_key_file_remove_group(key_file, addr, NULL);
@@ -266,7 +266,7 @@ static void store_device_info(struct device *dev)
done:
str = g_key_file_to_data(key_file, &length, NULL);
- g_file_set_contents(ANDROID_STORAGEDIR"/devices", str, length, NULL);
+ g_file_set_contents(DEVICES_FILE, str, length, NULL);
g_free(str);
g_key_file_free(key_file);
@@ -521,8 +521,7 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
key_file = g_key_file_new();
- if (!g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices",
- 0, NULL))
+ if (!g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL))
return;
ba2str(dst, addr);
@@ -537,7 +536,7 @@ static void store_link_key(const bdaddr_t *dst, const uint8_t *key,
g_key_file_set_integer(key_file, addr, "LinkKeyPinLength", pin_length);
data = g_key_file_to_data(key_file, &length, NULL);
- g_file_set_contents(ANDROID_STORAGEDIR"/devices", data, length, NULL);
+ g_file_set_contents(DEVICES_FILE, data, length, NULL);
g_free(data);
g_key_file_free(key_file);
@@ -1727,8 +1726,7 @@ static void load_devices_info(bt_bluetooth_ready cb)
key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, ANDROID_STORAGEDIR"/devices", 0,
- NULL);
+ g_key_file_load_from_file(key_file, DEVICES_FILE, 0, NULL);
devs = g_key_file_get_groups(key_file, &len);
--
1.8.5.3
^ permalink raw reply related
* [PATCH v3 1/5] android/bluetooth: Split devices list to devices and bonded_devices
From: Szymon Janc @ 2014-01-23 22:18 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1390515490-29538-1-git-send-email-szymon.janc@gmail.com>
Bonded devices are permament until unbondedn. Non-bonded devices will
be held in (size limited) cache based on timestamp property so split
list to ease separation.
---
android/bluetooth.c | 48 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 36 insertions(+), 12 deletions(-)
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 4849dab..5d222e1 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -132,6 +132,8 @@ static const uint16_t uuid_list[] = {
static uint16_t option_index = MGMT_INDEX_NONE;
static struct mgmt *mgmt_if = NULL;
+
+static GSList *bonded_devices = NULL;
static GSList *devices = NULL;
/* This list contains addresses which are asked for records */
@@ -283,6 +285,10 @@ static struct device *find_device(const bdaddr_t *bdaddr)
{
GSList *l;
+ l = g_slist_find_custom(bonded_devices, bdaddr, device_match);
+ if (l)
+ return l->data;
+
l = g_slist_find_custom(devices, bdaddr, device_match);
if (l)
return l->data;
@@ -559,12 +565,30 @@ static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
if (!dev)
return;
- if (dev->bond_state != state) {
- dev->bond_state = state;
- send_bond_state_change(&dev->bdaddr, status, state);
+ if (dev->bond_state == state)
+ return;
- store_device_info(dev);
+ switch (state) {
+ case HAL_BOND_STATE_NONE:
+ if (dev->bond_state == HAL_BOND_STATE_BONDED) {
+ bonded_devices = g_slist_remove(bonded_devices, dev);
+ devices = g_slist_prepend(devices, dev);
+ }
+ break;
+ case HAL_BOND_STATE_BONDED:
+ devices = g_slist_remove(devices, dev);
+ bonded_devices = g_slist_prepend(bonded_devices, dev);
+ break;
+ case HAL_BOND_STATE_BONDING:
+ default:
+ break;
}
+
+ dev->bond_state = state;
+
+ store_device_info(dev);
+
+ send_bond_state_change(&dev->bdaddr, status, state);
}
static void send_device_property(const bdaddr_t *bdaddr, uint8_t type,
@@ -935,6 +959,7 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
if (adapter.discovering) {
cp.state = HAL_DISCOVERY_STATE_STARTED;
} else {
+ g_slist_foreach(bonded_devices, clear_device_found, NULL);
g_slist_foreach(devices, clear_device_found, NULL);
cp.state = HAL_DISCOVERY_STATE_STOPPED;
}
@@ -2128,18 +2153,15 @@ static uint8_t get_adapter_scan_mode(void)
static uint8_t get_adapter_bonded_devices(void)
{
- uint8_t buf[sizeof(bdaddr_t) * g_slist_length(devices)];
+ uint8_t buf[sizeof(bdaddr_t) * g_slist_length(bonded_devices)];
int i = 0;
GSList *l;
DBG("");
- for (l = devices; l; l = g_slist_next(l)) {
+ for (l = bonded_devices; l; l = g_slist_next(l)) {
struct device *dev = l->data;
- if (dev->bond_state != HAL_BOND_STATE_BONDED)
- continue;
-
bdaddr2android(&dev->bdaddr, buf + (i * sizeof(bdaddr_t)));
i++;
}
@@ -2691,11 +2713,10 @@ static void send_bonded_devices_props(void)
{
GSList *l;
- for (l = devices; l; l = g_slist_next(l)) {
+ for (l = bonded_devices; l; l = g_slist_next(l)) {
struct device *dev = l->data;
- if (dev->bond_state == HAL_BOND_STATE_BONDED)
- get_remote_device_props(dev);
+ get_remote_device_props(dev);
}
}
@@ -3093,6 +3114,9 @@ void bt_bluetooth_unregister(void)
{
DBG("");
+ g_slist_free_full(bonded_devices, (GDestroyNotify) free_device);
+ bonded_devices = NULL;
+
g_slist_free_full(devices, (GDestroyNotify) free_device);
devices = NULL;
--
1.8.5.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox