endif
#endif
-if MAINTAINER_MODE
-builtin_modules += gatt_example
-builtin_sources += plugins/gatt-example.c
-endif
-
-if TIZEN_BREDR_PLUGIN
-if EXPERIMENTAL
-if TIZEN_UNUSED_PLUGIN
+if TIZEN_NFC_PLUGIN
builtin_modules += neard
builtin_sources += plugins/neard.c
endif
#noinst_LIBRARIES += profiles/sap/libsap.a
#profiles_sap_libsap_a_SOURCES = profiles/sap/sap.h profiles/sap/sap-u8500.c
endif
-endif
+if TIZEN_BREDR_PLUGIN
+if TIZEN_A2DP_PLUGIN
builtin_modules += a2dp
builtin_sources += profiles/audio/source.h profiles/audio/source.c \
profiles/audio/sink.h profiles/audio/sink.c \
profiles/audio/media.h profiles/audio/media.c \
profiles/audio/transport.h profiles/audio/transport.c \
profiles/audio/a2dp-codecs.h
-
+endif
+if TIZEN_AVRCP_PLUGIN
builtin_modules += avrcp
builtin_sources += profiles/audio/control.h profiles/audio/control.c \
profiles/audio/avctp.h profiles/audio/avctp.c \
profiles/audio/avrcp.h profiles/audio/avrcp.c \
profiles/audio/player.h profiles/audio/player.c
+endif
+if TIZEN_NETWORK_PLUGIN
builtin_modules += network
builtin_sources += profiles/network/manager.c \
profiles/network/bnep.h profiles/network/bnep.c \
profiles/network/connection.h \
profiles/network/connection.c
endif
+endif
#if WEARABLE
#builtin_modules +=
endif
#endif
-if EXPERIMENTAL
if TIZEN_HEALTH_PLUGIN
builtin_modules += health
builtin_sources += profiles/health/mcap.h profiles/health/mcap.c \
profiles/health/hdp.h profiles/health/hdp.c \
profiles/health/hdp_util.h profiles/health/hdp_util.c
endif
-endif
if TIZEN_HEALTH_PLUGIN
builtin_modules += gap
--enable-experimental
- Enable experimental plugins
+ Enable experimental tools
- By default all plugins that are still in development
+ By default all tools that are still in development
are disabled. This option can be used to enable them.
It is not recommended to enable this option for production
- systems. The APIs or behavior of the experimental plugins
- is unstable and might still change.
+ systems. The behavior of the experimental tools is unstable
+ and might still change.
+
+ --enable-nfc
+
+ This option enable NFC pairing support.
+
+ By default the integration with neard is disabled, this gives
+ the option to enable it in system where neard is supported.
+
+ The plugin is built into bluetoothd therefore it does not need
+ to be package separately.
+
+ --enable-sap
+
+ This option enable SAP profile using sap plugin.
+
+ By default sap plugin is disabled since it requires tight
+ integration with systems and is very rarely required.
+
+ The plugin is built into bluetoothd therefore it does not need
+ to be package separately.
+
+ --disable-a2dp
+
+ Disable A2DP profile
+
+ By default bluetoothd supports A2DP profile using a built-in
+ plugin, this option disables it.
+
+ This option is provided for distributions that do not have any
+ audio capabilities.
+
+ --disable-avrcp
+
+ Disable AVRCP profile
+
+ By default bluetoothd supports AVRCP profile using a built-in
+ plugin, this option disables it.
+
+ This option is provided for distributions that do not have any
+ audio capabilities.
+
+ --disable-network
+
+ Disable PANU, NAP, GN profiles
+
+ By default bluetoothd supports PANU, NAP and GN profile using a
+ built-in plugin, this option disables it.
+
+ This option is provided for distributions that do not have any
+ network capabilities.
+
+ --disable-hid
+
+ Disable HID profile
+
+ By default bluetoothd supports HID profile using a built-in
+ plugin, this option disables it.
+
+ This option is provided for distributions that do not have any
+ input capabilities.
+
+ --enable-health
+
+ This option enable health profiles.
+
+ By default health plugin is disabled since its profiles are
+ target for the health industry.
+
+ The plugin is built into bluetoothd therefore it does not need
+ to be package separately.
Information
--enable-manpages \
--enable-backtrace \
--enable-experimental \
+ --enable-nfc \
+ --enable-sap \
+ --enable-health \
--enable-android \
--enable-sixaxis \
--disable-datafiles $*
[enable test/example scripts]), [enable_test=${enableval}])
AM_CONDITIONAL(TEST, test "${enable_test}" = "yes")
+AC_ARG_ENABLE(nfc, AC_HELP_STRING([--enable-nfc],
+ [enable TIZEN_NFC_PLUGIN paring]), [enable_nfc=${enableval}])
+AM_CONDITIONAL(TIZEN_NFC_PLUGIN, test "${enable_nfc}" = "yes")
+
AC_ARG_ENABLE(tools, AC_HELP_STRING([--disable-tools],
[disable Bluetooth tools]), [enable_tools=${enableval}])
AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no")
AM_CONDITIONAL(MANPAGES, test "${enable_manpages}" = "yes")
AC_ARG_ENABLE(experimental, AC_HELP_STRING([--enable-experimental],
- [enable experimental plugins (SAP, NFC, ...)]),
+ [enable experimental tools]),
[enable_experimental=${enableval}])
AM_CONDITIONAL(EXPERIMENTAL, test "${enable_experimental}" = "yes")
[Enable Autopair Plugin]), [enable_autopair=${enableval}])
AM_CONDITIONAL(AUTOPAIR, test "${enable_autopair}" = "yes")
-AC_ARG_ENABLE(hid, AC_HELP_STRING([--enable-hid],
- [Enable HID Plugin]), [enable_hid=${enableval}])
-AM_CONDITIONAL(TIZEN_HID_PLUGIN, test "${enable_hid}" = "yes")
+AC_ARG_ENABLE(hid, AC_HELP_STRING([--disable-hid],
+ [disable HID Plugin]), [enable_hid=${enableval}])
+AM_CONDITIONAL(TIZEN_HID_PLUGIN, test "${enable_hid}" != "no")
+AC_ARG_ENABLE(health, AC_HELP_STRING([--enable-health],
+ [enable HEALTH profiles]), [enable_health=${enableval}])
AM_CONDITIONAL(TIZEN_HEALTH_PLUGIN, test "${enable_health}" = "yes")
AC_ARG_ENABLE(proximity, AC_HELP_STRING([--enable-proximity],
[Enable SAP Plugin]), [enable_sap=${enableval}])
AM_CONDITIONAL(TIZEN_SAP_PLUGIN, test "${enable_sap}" = "yes")
+AC_ARG_ENABLE(a2dp, AC_HELP_STRING([--disable-a2dp],
+ [disable A2DP profile]), [enable_a2dp=${enableval}])
+AM_CONDITIONAL(TIZEN_A2DP_PLUGIN, test "${enable_a2dp}" != "no")
+
+AC_ARG_ENABLE(avrcp, AC_HELP_STRING([--disable-avrcp],
+ [disable AVRCP profile]), [enable_avrcp=${enableval}])
+AM_CONDITIONAL(TIZEN_AVRCP_PLUGIN, test "${enable_avrcp}" != "no")
+
+AC_ARG_ENABLE(network, AC_HELP_STRING([--disable-network],
+ [disable NETWORK profile]), [enable_network=${enableval}])
+AM_CONDITIONAL(TIZEN_NETWORK_PLUGIN, test "${enable_network}" != "no")
+
AC_ARG_ENABLE(bredr, AC_HELP_STRING([--enable-bredr],
[Enable BREDR Plugin]), [enable_bredr=${enableval}])
AM_CONDITIONAL(TIZEN_BREDR_PLUGIN, test "${enable_bredr}" = "yes")
Storage directory structure
===========================
-There is one directory per adapter, named by its Bluetooth address, which
-contains:
+The storage root directory contains an optional addresses file that's
+used for managing adapters that come without a pre-allocated address.
+The format of the addresses file is:
+
+ [Static]
+ <manufacturer id> = <array of addresses>
+
+Each adapter with an assigned address has its own subdirectory under the
+root, named based on the address, which contains:
+
- a settings file for the local adapter
- an attributes file containing attributes of supported LE services
- a cache directory containing:
--enable-library \
--enable-gatt \
--enable-experimental \
- --enable-autopair=no \
+ --enable-autopyypair=no \
--enable-tizenunusedplugin=no
make %{?_smp_mflags} all V=1
+++ /dev/null
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <errno.h>
-
-#include "lib/bluetooth.h"
-#include "lib/sdp.h"
-#include "lib/uuid.h"
-
-#include "src/plugin.h"
-#include "src/adapter.h"
-#include "src/shared/util.h"
-#include "src/log.h"
-#include "attrib/gattrib.h"
-#include "attrib/gatt-service.h"
-#include "attrib/att.h"
-#include "attrib/gatt.h"
-#include "attrib/att-database.h"
-#include "src/attrib-server.h"
-
-/* FIXME: Not defined by SIG? UUID128? */
-#define OPCODES_SUPPORTED_UUID 0xA001
-#define BATTERY_STATE_SVC_UUID 0xA002
-#define BATTERY_STATE_UUID 0xA003
-#define THERM_HUMIDITY_SVC_UUID 0xA004
-#define MANUFACTURER_SVC_UUID 0xA005
-#define TEMPERATURE_UUID 0xA006
-#define FMT_CELSIUS_UUID 0xA007
-#define FMT_OUTSIDE_UUID 0xA008
-#define RELATIVE_HUMIDITY_UUID 0xA009
-#define FMT_PERCENT_UUID 0xA00A
-#define BLUETOOTH_SIG_UUID 0xA00B
-#define MANUFACTURER_NAME_UUID 0xA00C
-#define MANUFACTURER_SERIAL_UUID 0xA00D
-#define VENDOR_SPECIFIC_SVC_UUID 0xA00E
-#define VENDOR_SPECIFIC_TYPE_UUID 0xA00F
-#define FMT_KILOGRAM_UUID 0xA010
-#define FMT_HANGING_UUID 0xA011
-
-struct gatt_example_adapter {
- struct btd_adapter *adapter;
- GSList *sdp_handles;
-};
-
-static GSList *adapters = NULL;
-
-static void gatt_example_adapter_free(struct gatt_example_adapter *gadapter)
-{
- while (gadapter->sdp_handles != NULL) {
- uint32_t handle = GPOINTER_TO_UINT(gadapter->sdp_handles->data);
-
- attrib_free_sdp(gadapter->adapter, handle);
- gadapter->sdp_handles = g_slist_remove(gadapter->sdp_handles,
- gadapter->sdp_handles->data);
- }
-
- if (gadapter->adapter != NULL)
- btd_adapter_unref(gadapter->adapter);
-
- g_free(gadapter);
-}
-
-static int adapter_cmp(gconstpointer a, gconstpointer b)
-{
- const struct gatt_example_adapter *gatt_adapter = a;
- const struct btd_adapter *adapter = b;
-
- if (gatt_adapter->adapter == adapter)
- return 0;
-
- return -1;
-}
-
-static uint8_t battery_state_read(struct attribute *a,
- struct btd_device *device, gpointer user_data)
-{
- struct btd_adapter *adapter = user_data;
- uint8_t value;
-
- value = 0x04;
- attrib_db_update(adapter, a->handle, NULL, &value, sizeof(value), NULL);
-
- return 0;
-}
-
-static gboolean register_battery_service(struct btd_adapter *adapter)
-{
- bt_uuid_t uuid;
-
- bt_uuid16_create(&uuid, BATTERY_STATE_SVC_UUID);
-
- return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
- /* battery state characteristic */
- GATT_OPT_CHR_UUID16, BATTERY_STATE_UUID,
- GATT_OPT_CHR_PROPS, GATT_CHR_PROP_READ |
- GATT_CHR_PROP_NOTIFY,
- GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
- battery_state_read, adapter,
-
- GATT_OPT_INVALID);
-}
-
-static void register_termometer_service(struct gatt_example_adapter *adapter,
- const uint16_t manuf1[2], const uint16_t manuf2[2])
-{
- const char *desc_out_temp = "Outside Temperature";
- const char *desc_out_hum = "Outside Relative Humidity";
- uint16_t start_handle, h;
- const int svc_size = 11;
- uint32_t sdp_handle;
- uint8_t atval[256];
- bt_uuid_t uuid;
- int len;
-
- bt_uuid16_create(&uuid, THERM_HUMIDITY_SVC_UUID);
- start_handle = attrib_db_find_avail(adapter->adapter, &uuid, svc_size);
- if (start_handle == 0) {
- error("Not enough free handles to register service");
- return;
- }
-
- DBG("start_handle=0x%04x manuf1=0x%04x-0x%04x, manuf2=0x%04x-0x%04x",
- start_handle, manuf1[0], manuf1[1], manuf2[0], manuf2[1]);
-
- h = start_handle;
-
- /* Thermometer: primary service definition */
- bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
- put_le16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 2);
-
- bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
-
- /* Thermometer: Include */
- if (manuf1[0] && manuf1[1]) {
- put_le16(manuf1[0], &atval[0]);
- put_le16(manuf1[1], &atval[2]);
- put_le16(MANUFACTURER_SVC_UUID, &atval[4]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE,
- ATT_NOT_PERMITTED, atval, 6);
- }
-
- /* Thermometer: Include */
- if (manuf2[0] && manuf2[1]) {
- put_le16(manuf2[0], &atval[0]);
- put_le16(manuf2[1], &atval[2]);
- put_le16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE,
- ATT_NOT_PERMITTED, atval, 6);
- }
-
- /* Thermometer: temperature characteristic */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(TEMPERATURE_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Thermometer: temperature characteristic value */
- bt_uuid16_create(&uuid, TEMPERATURE_UUID);
- atval[0] = 0x8A;
- atval[1] = 0x02;
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 2);
-
- /* Thermometer: temperature characteristic format */
- bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
- atval[0] = 0x0E;
- atval[1] = 0xFE;
- put_le16(FMT_CELSIUS_UUID, &atval[2]);
- atval[4] = 0x01;
- put_le16(FMT_OUTSIDE_UUID, &atval[5]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 7);
-
- /* Thermometer: characteristic user description */
- bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
- len = strlen(desc_out_temp);
- strncpy((char *) atval, desc_out_temp, len);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
-
- /* Thermometer: relative humidity characteristic */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(RELATIVE_HUMIDITY_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Thermometer: relative humidity value */
- bt_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
- atval[0] = 0x27;
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 1);
-
- /* Thermometer: relative humidity characteristic format */
- bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
- atval[0] = 0x04;
- atval[1] = 0x00;
- put_le16(FMT_PERCENT_UUID, &atval[2]);
- put_le16(BLUETOOTH_SIG_UUID, &atval[4]);
- put_le16(FMT_OUTSIDE_UUID, &atval[6]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 8);
-
- /* Thermometer: characteristic user description */
- bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
- len = strlen(desc_out_hum);
- strncpy((char *) atval, desc_out_hum, len);
- attrib_db_add(adapter->adapter, h, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
-
- g_assert(h - start_handle + 1 == svc_size);
-
- /* Add an SDP record for the above service */
- sdp_handle = attrib_create_sdp(adapter->adapter, start_handle,
- "Thermometer");
- if (sdp_handle)
- adapter->sdp_handles = g_slist_prepend(adapter->sdp_handles,
- GUINT_TO_POINTER(sdp_handle));
-}
-
-static void register_manuf1_service(struct gatt_example_adapter *adapter,
- uint16_t range[2])
-{
- const char *manufacturer_name1 = "ACME Temperature Sensor";
- const char *serial1 = "237495-3282-A";
- uint16_t start_handle, h;
- const int svc_size = 5;
- uint8_t atval[256];
- bt_uuid_t uuid;
- int len;
-
- bt_uuid16_create(&uuid, MANUFACTURER_SVC_UUID);
- start_handle = attrib_db_find_avail(adapter->adapter, &uuid, svc_size);
- if (start_handle == 0) {
- error("Not enough free handles to register service");
- return;
- }
-
- DBG("start_handle=0x%04x", start_handle);
-
- h = start_handle;
-
- /* Secondary Service: Manufacturer Service */
- bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
- put_le16(MANUFACTURER_SVC_UUID, &atval[0]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 2);
-
- /* Manufacturer name characteristic definition */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(MANUFACTURER_NAME_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Manufacturer name characteristic value */
- bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
- len = strlen(manufacturer_name1);
- strncpy((char *) atval, manufacturer_name1, len);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
-
- /* Manufacturer serial number characteristic */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(MANUFACTURER_SERIAL_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Manufacturer serial number characteristic value */
- bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
- len = strlen(serial1);
- strncpy((char *) atval, serial1, len);
- attrib_db_add(adapter->adapter, h, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
-
- g_assert(h - start_handle + 1 == svc_size);
-
- range[0] = start_handle;
- range[1] = start_handle + svc_size - 1;
-}
-
-static void register_manuf2_service(struct gatt_example_adapter *adapter,
- uint16_t range[2])
-{
- const char *manufacturer_name2 = "ACME Weighing Scales";
- const char *serial2 = "11267-2327A00239";
- uint16_t start_handle, h;
- const int svc_size = 5;
- uint8_t atval[256];
- bt_uuid_t uuid;
- int len;
-
- bt_uuid16_create(&uuid, MANUFACTURER_SVC_UUID);
- start_handle = attrib_db_find_avail(adapter->adapter, &uuid, svc_size);
- if (start_handle == 0) {
- error("Not enough free handles to register service");
- return;
- }
-
- DBG("start_handle=0x%04x", start_handle);
-
- h = start_handle;
-
- /* Secondary Service: Manufacturer Service */
- bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
- put_le16(MANUFACTURER_SVC_UUID, &atval[0]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 2);
-
- /* Manufacturer name characteristic definition */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(MANUFACTURER_NAME_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Manufacturer name attribute */
- bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
- len = strlen(manufacturer_name2);
- strncpy((char *) atval, manufacturer_name2, len);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
-
- /* Characteristic: serial number */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(MANUFACTURER_SERIAL_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Serial number characteristic value */
- bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
- len = strlen(serial2);
- strncpy((char *) atval, serial2, len);
- attrib_db_add(adapter->adapter, h, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
-
- g_assert(h - start_handle + 1 == svc_size);
-
- range[0] = start_handle;
- range[1] = start_handle + svc_size - 1;
-}
-
-static void register_vendor_service(struct gatt_example_adapter *adapter,
- uint16_t range[2])
-{
- uint16_t start_handle, h;
- const int svc_size = 3;
- uint8_t atval[256];
- bt_uuid_t uuid;
-
- bt_uuid16_create(&uuid, VENDOR_SPECIFIC_SVC_UUID);
- start_handle = attrib_db_find_avail(adapter->adapter, &uuid, svc_size);
- if (start_handle == 0) {
- error("Not enough free handles to register service");
- return;
- }
-
- DBG("start_handle=0x%04x", start_handle);
-
- h = start_handle;
-
- /* Secondary Service: Vendor Specific Service */
- bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
- put_le16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 2);
-
- /* Vendor Specific Type characteristic definition */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- put_le16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 5);
-
- /* Vendor Specific Type characteristic value */
- bt_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
- atval[0] = 0x56;
- atval[1] = 0x65;
- atval[2] = 0x6E;
- atval[3] = 0x64;
- atval[4] = 0x6F;
- atval[5] = 0x72;
- attrib_db_add(adapter->adapter, h, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 6);
-
- g_assert(h - start_handle + 1 == svc_size);
-
- range[0] = start_handle;
- range[1] = start_handle + svc_size - 1;
-}
-
-static void register_weight_service(struct gatt_example_adapter *adapter,
- const uint16_t vendor[2])
-{
- const char *desc_weight = "Rucksack Weight";
- const uint128_t char_weight_uuid_btorder = {
- .data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B,
- 0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } };
- const uint128_t prim_weight_uuid_btorder = {
- .data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11,
- 0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } };
- uint128_t prim_weight_uuid, char_weight_uuid;
- uint16_t start_handle, h;
- const int svc_size = 6;
- uint32_t sdp_handle;
- uint8_t atval[256];
- bt_uuid_t uuid;
- int len;
-
- btoh128(&char_weight_uuid_btorder, &char_weight_uuid);
- btoh128(&prim_weight_uuid_btorder, &prim_weight_uuid);
- bt_uuid128_create(&uuid, prim_weight_uuid);
- start_handle = attrib_db_find_avail(adapter->adapter, &uuid, svc_size);
- if (start_handle == 0) {
- error("Not enough free handles to register service");
- return;
- }
-
- DBG("start_handle=0x%04x, vendor=0x%04x-0x%04x", start_handle,
- vendor[0], vendor[1]);
-
- h = start_handle;
-
- /* Weight service: primary service definition */
- bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
- memcpy(atval, &prim_weight_uuid_btorder, 16);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 16);
-
- if (vendor[0] && vendor[1]) {
- /* Weight: include */
- bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
- put_le16(vendor[0], &atval[0]);
- put_le16(vendor[1], &atval[2]);
- put_le16(MANUFACTURER_SVC_UUID, &atval[4]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE,
- ATT_NOT_PERMITTED, atval, 6);
- }
-
- /* Weight: characteristic */
- bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
- atval[0] = GATT_CHR_PROP_READ;
- put_le16(h + 1, &atval[1]);
- memcpy(&atval[3], &char_weight_uuid_btorder, 16);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 19);
-
- /* Weight: characteristic value */
- bt_uuid128_create(&uuid, char_weight_uuid);
- atval[0] = 0x82;
- atval[1] = 0x55;
- atval[2] = 0x00;
- atval[3] = 0x00;
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 4);
-
- /* Weight: characteristic format */
- bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
- atval[0] = 0x08;
- atval[1] = 0xFD;
- put_le16(FMT_KILOGRAM_UUID, &atval[2]);
- put_le16(BLUETOOTH_SIG_UUID, &atval[4]);
- put_le16(FMT_HANGING_UUID, &atval[6]);
- attrib_db_add(adapter->adapter, h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, 8);
-
- /* Weight: characteristic user description */
- bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
- len = strlen(desc_weight);
- strncpy((char *) atval, desc_weight, len);
- attrib_db_add(adapter->adapter, h, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
- atval, len);
- g_assert(h - start_handle + 1 == svc_size);
-
- /* Add an SDP record for the above service */
- sdp_handle = attrib_create_sdp(adapter->adapter, start_handle,
- "Weight Service");
- if (sdp_handle)
- adapter->sdp_handles = g_slist_prepend(adapter->sdp_handles,
- GUINT_TO_POINTER(sdp_handle));
-}
-
-static int gatt_example_adapter_probe(struct btd_adapter *adapter)
-{
- uint16_t manuf1_range[2] = {0, 0}, manuf2_range[2] = {0, 0};
- uint16_t vendor_range[2] = {0, 0};
- struct gatt_example_adapter *gadapter;
-
- gadapter = g_new0(struct gatt_example_adapter, 1);
- gadapter->adapter = btd_adapter_ref(adapter);
-
- if (!register_battery_service(adapter)) {
- DBG("Battery service could not be registered");
- gatt_example_adapter_free(gadapter);
- return -EIO;
- }
-
- register_manuf1_service(gadapter, manuf1_range);
- register_manuf2_service(gadapter, manuf2_range);
- register_termometer_service(gadapter, manuf1_range, manuf2_range);
- register_vendor_service(gadapter, vendor_range);
- register_weight_service(gadapter, vendor_range);
-
- adapters = g_slist_append(adapters, gadapter);
-
- return 0;
-}
-
-static void gatt_example_adapter_remove(struct btd_adapter *adapter)
-{
- struct gatt_example_adapter *gadapter;
- GSList *l;
-
- l = g_slist_find_custom(adapters, adapter, adapter_cmp);
- if (l == NULL)
- return;
-
- gadapter = l->data;
- adapters = g_slist_remove(adapters, gadapter);
- gatt_example_adapter_free(gadapter);
-}
-
-static struct btd_adapter_driver gatt_example_adapter_driver = {
- .name = "gatt-example-adapter-driver",
- .probe = gatt_example_adapter_probe,
- .remove = gatt_example_adapter_remove,
-};
-
-static int gatt_example_init(void)
-{
- return btd_register_adapter_driver(&gatt_example_adapter_driver);
-}
-
-static void gatt_example_exit(void)
-{
- btd_unregister_adapter_driver(&gatt_example_adapter_driver);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(gatt_example, VERSION, BLUETOOTH_PLUGIN_PRIORITY_LOW,
- gatt_example_init, gatt_example_exit)
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define AVRCP_STATUS_PARAM_NOT_FOUND 0x02
#define AVRCP_STATUS_INTERNAL_ERROR 0x03
#define AVRCP_STATUS_SUCCESS 0x04
+#define AVRCP_STATUS_UID_CHANGED 0x05
+#define AVRCP_STATUS_DOES_NOT_EXIST 0x09
#define AVRCP_STATUS_OUT_OF_BOUNDS 0x0b
#define AVRCP_STATUS_INVALID_PLAYER_ID 0x11
#define AVRCP_STATUS_PLAYER_NOT_BROWSABLE 0x12
#endif
#else
uint16_t avctp_ver = 0x0103;
- uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
+ uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 |
AVRCP_FEATURE_CATEGORY_2 |
AVRCP_FEATURE_CATEGORY_3 |
AVRCP_FEATURE_CATEGORY_4 |
#endif
#else
uint16_t avctp_ver = 0x0103;
- uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
+ uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 |
AVRCP_FEATURE_CATEGORY_2 |
AVRCP_FEATURE_CATEGORY_3 |
AVRCP_FEATURE_CATEGORY_4 |
AVRCP_FEATURE_BROWSING |
- AVRCP_FEATURE_PLAYER_SETTINGS );
+ AVRCP_FEATURE_PLAYER_SETTINGS);
#endif
record = sdp_record_alloc();
if (!record)
/* retrieve current playback position for interim response */
playback_position = player_get_playback_position(player);
playback_position = (playback_position & 0x000000ff) << 24 |
- (playback_position & 0x0000ff00) << 8 |
- (playback_position & 0x00ff0000) >> 8 |
- (playback_position & 0xff000000) >> 24;
+ (playback_position & 0x0000ff00) << 8 |
+ (playback_position & 0x00ff0000) >> 8 |
+ (playback_position & 0xff000000) >> 24;
memcpy(&pdu->params[1], &playback_position, sizeof(uint32_t));
break;
return 0;
}
+static gboolean avrcp_play_item_rsp(struct avctp *conn, uint8_t code,
+ uint8_t subunit, uint8_t transaction,
+ uint8_t *operands, size_t operand_count,
+ void *user_data)
+{
+ struct avrcp_browsing_header *pdu = (void *) operands;
+ struct avrcp *session = (void *) user_data;
+ struct avrcp_player *player = session->controller->player;
+ struct media_player *mp = player->user_data;
+ int ret = 0;
+
+ if (pdu == NULL) {
+ ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ if (pdu->params[0] != AVRCP_STATUS_SUCCESS) {
+ switch (pdu->params[0]) {
+ case AVRCP_STATUS_UID_CHANGED:
+ case AVRCP_STATUS_DOES_NOT_EXIST:
+ ret = -ENOENT;
+ default:
+ ret = -EINVAL;
+ }
+ goto done;
+ }
+
+done:
+ media_player_play_item_complete(mp, ret);
+
+ return FALSE;
+}
+
static void avrcp_play_item(struct avrcp *session, uint64_t uid)
{
uint8_t buf[AVRCP_HEADER_LENGTH + 11];
avctp_send_vendordep_req(session->conn, AVC_CTYPE_CONTROL,
AVC_SUBUNIT_PANEL, buf, length,
- NULL, session);
+ avrcp_play_item_rsp, session);
}
static int ct_play_item(struct media_player *mp, const char *name,
event = pdu->params[0];
- if (code == AVC_CTYPE_CHANGED) {
+ if (code == AVC_CTYPE_CHANGED)
goto changed;
- }
switch (event) {
case AVRCP_EVENT_VOLUME_CHANGED:
{
switch (event) {
- case AVRCP_EVENT_STATUS_CHANGED:
- return "AVRCP EVENT STATUS CHANGED";
- case AVRCP_EVENT_TRACK_CHANGED:
- return "AVRCP EVENT TRACK CHANGED";
- case AVRCP_EVENT_SETTINGS_CHANGED:
- return "AVRCP EVENT SETTINGS CHANGED";
- case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
- return "AVRCP EVENT ADDRESSED PLAYER CHANGED";
- case AVRCP_EVENT_UIDS_CHANGED:
- return "AVRCP EVENT UIDS CHANGED";
- case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
- return "AVRCP EVENT AVAILABLE PLAYERS CHANGED";
- case AVRCP_EVENT_VOLUME_CHANGED:
- return "AVRCP EVENT VOLUME CHANGED";
- default:
- return "Unknown Event";
- }
+ case AVRCP_EVENT_STATUS_CHANGED:
+ return "AVRCP EVENT STATUS CHANGED";
+ case AVRCP_EVENT_TRACK_CHANGED:
+ return "AVRCP EVENT TRACK CHANGED";
+ case AVRCP_EVENT_SETTINGS_CHANGED:
+ return "AVRCP EVENT SETTINGS CHANGED";
+ case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
+ return "AVRCP EVENT ADDRESSED PLAYER CHANGED";
+ case AVRCP_EVENT_UIDS_CHANGED:
+ return "AVRCP EVENT UIDS CHANGED";
+ case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
+ return "AVRCP EVENT AVAILABLE PLAYERS CHANGED";
+ case AVRCP_EVENT_VOLUME_CHANGED:
+ return "AVRCP EVENT VOLUME CHANGED";
+ default:
+ return "Unknown Event";
+ }
}
static gboolean avrcp_get_playback_status(gpointer user_data)
{
struct media_item *item = data;
struct media_player *mp = item->player;
+ struct media_folder *folder = mp->scope;
struct player_callback *cb = mp->cb;
const char *path;
int err;
if (!item->playable || !cb->cbs->play_item)
return btd_error_not_supported(msg);
- path = mp->search && mp->scope == mp->search ? "/Search" : item->path;
+ if (folder->msg)
+ return btd_error_failed(msg, strerror(EBUSY));
+
+ path = mp->search && folder == mp->search ? "/Search" : item->path;
err = cb->cbs->play_item(mp, path, item->uid, cb->user_data);
if (err < 0)
return btd_error_failed(msg, strerror(-err));
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ folder->msg = dbus_message_ref(msg);
+
+ return NULL;
}
static DBusMessage *media_item_add_to_nowplaying(DBusConnection *conn,
{ }
};
+void media_player_play_item_complete(struct media_player *mp, int err)
+{
+ struct media_folder *folder = mp->scope;
+ DBusMessage *reply;
+
+ if (folder == NULL || folder->msg == NULL)
+ return;
+
+ if (err < 0) {
+ reply = btd_error_failed(folder->msg, strerror(-err));
+ goto done;
+ }
+
+ reply = g_dbus_create_reply(folder->msg, DBUS_TYPE_INVALID);
+
+done:
+ g_dbus_send_message(btd_get_dbus_connection(), reply);
+ dbus_message_unref(folder->msg);
+ folder->msg = NULL;
+}
+
void media_item_set_playable(struct media_item *item, bool value)
{
if (item->playable == value)
player_item_type_t type,
uint64_t uid);
+void media_player_play_item_complete(struct media_player *mp, int err);
void media_item_set_playable(struct media_item *item, bool value);
void media_player_list_complete(struct media_player *mp, GSList *items,
int err);
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
bdaddr_t le_static_addr;
#endif
+ int8_t bdaddr_type; /* address type */
uint32_t dev_class; /* controller class of device */
char *name; /* controller device name */
char *short_name; /* controller short name */
sdp_list_t *services; /* Services associated to adapter */
struct btd_gatt_database *database;
- struct btd_advertising *adv_manager;
+ struct btd_adv_manager *adv_manager;
gboolean initialized;
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return MODE_UNKNOWN;
}
+uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter)
+{
+ return adapter->bdaddr_type;
+}
+
static void store_adapter_info(struct btd_adapter *adapter)
{
GKeyFile *key_file;
adv->slot_id = slot_id;
- adapter->adv_list= g_slist_append(adapter->adv_list, adv);
+ adapter->adv_list = g_slist_append(adapter->adv_list, adv);
return;
}
GSList *dev;
dev = adapter->devices;
- for (; dev; dev = dev->next) {
+ for (; dev; dev = dev->next)
device_print_addr(dev->data);
- }
}
#endif
#else
btd_adapter_gatt_server_stop(adapter);
#endif
-
- btd_advertising_manager_destroy(adapter->adv_manager);
+ btd_adv_manager_destroy(adapter->adv_manager);
adapter->adv_manager = NULL;
g_slist_free(adapter->pin_callbacks);
if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
/* Don't start advertising managers on non-LE controllers. */
if (adapter->supported_settings & MGMT_SETTING_LE) {
- adapter->adv_manager =
- btd_advertising_manager_new(adapter);
+ adapter->adv_manager = btd_adv_manager_new(adapter);
} else {
btd_info(adapter->dev_id,
"LEAdvertisingManager skipped, LE unavailable");
const char *adapter_get_path(struct btd_adapter *adapter);
const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter);
+uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter);
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
const bdaddr_t *btd_adapter_get_le_address(struct btd_adapter *adapter);
uint8_t btd_adapter_get_le_address_type(struct btd_adapter * adapter);
#define LE_ADVERTISING_MGR_IFACE "org.bluez.LEAdvertisingManager1"
#define LE_ADVERTISEMENT_IFACE "org.bluez.LEAdvertisement1"
-struct btd_advertising {
+struct btd_adv_manager {
struct btd_adapter *adapter;
- struct queue *ads;
+ struct queue *clients;
struct mgmt *mgmt;
uint16_t mgmt_index;
uint8_t max_adv_len;
#define AD_TYPE_BROADCAST 0
#define AD_TYPE_PERIPHERAL 1
-struct advertisement {
- struct btd_advertising *manager;
+struct btd_adv_client {
+ struct btd_adv_manager *manager;
char *owner;
char *path;
GDBusClient *client;
const char *path;
};
-static bool match_advertisement(const void *a, const void *b)
+static bool match_client(const void *a, const void *b)
{
- const struct advertisement *ad = a;
+ const struct btd_adv_client *client = a;
const struct dbus_obj_match *match = b;
- if (match->owner && g_strcmp0(ad->owner, match->owner))
+ if (match->owner && g_strcmp0(client->owner, match->owner))
return false;
- if (match->path && g_strcmp0(ad->path, match->path))
+ if (match->path && g_strcmp0(client->path, match->path))
return false;
return true;
}
-static void advertisement_free(void *data)
+static void client_free(void *data)
{
- struct advertisement *ad = data;
+ struct btd_adv_client *client = data;
- if (ad->client) {
- g_dbus_client_set_disconnect_watch(ad->client, NULL, NULL);
- g_dbus_client_unref(ad->client);
+ if (client->client) {
+ g_dbus_client_set_disconnect_watch(client->client, NULL, NULL);
+ g_dbus_client_unref(client->client);
}
- bt_ad_unref(ad->data);
+ if (client->instance)
+ util_clear_uid(&client->manager->instance_bitmap,
+ client->instance);
- g_dbus_proxy_unref(ad->proxy);
+ bt_ad_unref(client->data);
- if (ad->owner)
- g_free(ad->owner);
+ g_dbus_proxy_unref(client->proxy);
- if (ad->path)
- g_free(ad->path);
+ if (client->owner)
+ g_free(client->owner);
- free(ad);
+ if (client->path)
+ g_free(client->path);
+
+ free(client);
}
-static gboolean advertisement_free_idle_cb(void *data)
+static gboolean client_free_idle_cb(void *data)
{
- advertisement_free(data);
+ client_free(data);
return FALSE;
}
-static void advertisement_release(void *data)
+static void client_release(void *data)
{
- struct advertisement *ad = data;
+ struct btd_adv_client *client = data;
DBusMessage *message;
- DBG("Releasing advertisement %s, %s", ad->owner, ad->path);
+ DBG("Releasing advertisement %s, %s", client->owner, client->path);
- message = dbus_message_new_method_call(ad->owner, ad->path,
+ message = dbus_message_new_method_call(client->owner, client->path,
LE_ADVERTISEMENT_IFACE,
"Release");
g_dbus_send_message(btd_get_dbus_connection(), message);
}
-static void advertisement_destroy(void *data)
+static void client_destroy(void *data)
{
- advertisement_release(data);
- advertisement_free(data);
+ client_release(data);
+ client_free(data);
}
-static void advertisement_remove(void *data)
+static void client_remove(void *data)
{
- struct advertisement *ad = data;
+ struct btd_adv_client *client = data;
struct mgmt_cp_remove_advertising cp;
- g_dbus_client_set_disconnect_watch(ad->client, NULL, NULL);
-
- cp.instance = ad->instance;
+ g_dbus_client_set_disconnect_watch(client->client, NULL, NULL);
- mgmt_send(ad->manager->mgmt, MGMT_OP_REMOVE_ADVERTISING,
- ad->manager->mgmt_index, sizeof(cp), &cp, NULL, NULL,
- NULL);
+ cp.instance = client->instance;
- queue_remove(ad->manager->ads, ad);
+ mgmt_send(client->manager->mgmt, MGMT_OP_REMOVE_ADVERTISING,
+ client->manager->mgmt_index, sizeof(cp), &cp,
+ NULL, NULL, NULL);
- util_clear_uid(&ad->manager->instance_bitmap, ad->instance);
+ queue_remove(client->manager->clients, client);
- g_idle_add(advertisement_free_idle_cb, ad);
+ g_idle_add(client_free_idle_cb, client);
}
static void client_disconnect_cb(DBusConnection *conn, void *user_data)
{
DBG("Client disconnected");
- advertisement_remove(user_data);
+ client_remove(user_data);
}
-static bool parse_advertising_type(GDBusProxy *proxy, uint8_t *type)
+static bool parse_type(GDBusProxy *proxy, uint8_t *type)
{
DBusMessageIter iter;
const char *msg_type;
return false;
}
-static bool parse_advertising_service_uuids(GDBusProxy *proxy,
- struct bt_ad *data)
+static bool parse_service_uuids(GDBusProxy *proxy, struct bt_ad *data)
{
DBusMessageIter iter, ariter;
return false;
}
-static bool parse_advertising_solicit_uuids(GDBusProxy *proxy,
- struct bt_ad *data)
+static bool parse_solicit_uuids(GDBusProxy *proxy, struct bt_ad *data)
{
DBusMessageIter iter, ariter;
return false;
}
-static bool parse_advertising_manufacturer_data(GDBusProxy *proxy,
- struct bt_ad *data)
+static bool parse_manufacturer_data(GDBusProxy *proxy, struct bt_ad *data)
{
DBusMessageIter iter, entries;
dbus_message_iter_get_basic(&entry, &manuf_id);
dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ goto fail;
+
dbus_message_iter_recurse(&entry, &value);
if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
return false;
}
-static bool parse_advertising_service_data(GDBusProxy *proxy,
- struct bt_ad *data)
+static bool parse_service_data(GDBusProxy *proxy, struct bt_ad *data)
{
DBusMessageIter iter, entries;
goto fail;
dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ goto fail;
+
dbus_message_iter_recurse(&entry, &value);
if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
return false;
}
-static bool parse_advertising_include_tx_power(GDBusProxy *proxy,
- bool *included)
+static bool parse_include_tx_power(GDBusProxy *proxy, bool *included)
{
DBusMessageIter iter;
dbus_bool_t b;
return true;
}
-static void add_adverting_complete(struct advertisement *ad, uint8_t status)
+static void add_client_complete(struct btd_adv_client *client, uint8_t status)
{
DBusMessage *reply;
if (status) {
error("Failed to add advertisement: %s (0x%02x)",
mgmt_errstr(status), status);
- reply = btd_error_failed(ad->reg,
+ reply = btd_error_failed(client->reg,
"Failed to register advertisement");
- queue_remove(ad->manager->ads, ad);
- g_idle_add(advertisement_free_idle_cb, ad);
+ queue_remove(client->manager->clients, client);
+ g_idle_add(client_free_idle_cb, client);
} else
- reply = dbus_message_new_method_return(ad->reg);
+ reply = dbus_message_new_method_return(client->reg);
g_dbus_send_message(btd_get_dbus_connection(), reply);
- dbus_message_unref(ad->reg);
- ad->reg = NULL;
+ dbus_message_unref(client->reg);
+ client->reg = NULL;
}
-static void add_advertising_callback(uint8_t status, uint16_t length,
+static void add_adv_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
- struct advertisement *ad = user_data;
+ struct btd_adv_client *client = user_data;
const struct mgmt_rp_add_advertising *rp = param;
if (status)
goto done;
}
- ad->instance = rp->instance;
+ client->instance = rp->instance;
- g_dbus_client_set_disconnect_watch(ad->client, client_disconnect_cb,
- ad);
- DBG("Advertisement registered: %s", ad->path);
+ g_dbus_client_set_disconnect_watch(client->client, client_disconnect_cb,
+ client);
+ DBG("Advertisement registered: %s", client->path);
done:
- add_adverting_complete(ad, status);
+ add_client_complete(client, status);
}
-static size_t calc_max_adv_len(struct advertisement *ad, uint32_t flags)
+static size_t calc_max_adv_len(struct btd_adv_client *client, uint32_t flags)
{
- size_t max = ad->manager->max_adv_len;
+ size_t max = client->manager->max_adv_len;
/*
* Flags which reduce the amount of space available for advertising.
return max;
}
-static DBusMessage *refresh_advertisement(struct advertisement *ad)
+static DBusMessage *refresh_advertisement(struct btd_adv_client *client)
{
struct mgmt_cp_add_advertising *cp;
uint8_t param_len;
size_t adv_data_len;
uint32_t flags = 0;
- DBG("Refreshing advertisement: %s", ad->path);
+ DBG("Refreshing advertisement: %s", client->path);
- if (ad->type == AD_TYPE_PERIPHERAL)
+ if (client->type == AD_TYPE_PERIPHERAL)
flags = MGMT_ADV_FLAG_CONNECTABLE | MGMT_ADV_FLAG_DISCOV;
- if (ad->include_tx_power)
+ if (client->include_tx_power)
flags |= MGMT_ADV_FLAG_TX_POWER;
- adv_data = bt_ad_generate(ad->data, &adv_data_len);
+ adv_data = bt_ad_generate(client->data, &adv_data_len);
- if (!adv_data || (adv_data_len > calc_max_adv_len(ad, flags))) {
+ if (!adv_data || (adv_data_len > calc_max_adv_len(client, flags))) {
error("Advertising data too long or couldn't be generated.");
- return g_dbus_create_error(ad->reg, ERROR_INTERFACE
+ return g_dbus_create_error(client->reg, ERROR_INTERFACE
".InvalidLength",
"Advertising data too long.");
}
free(adv_data);
- return btd_error_failed(ad->reg, "Failed");
+ return btd_error_failed(client->reg, "Failed");
}
cp->flags = htobl(flags);
- cp->instance = ad->instance;
+ cp->instance = client->instance;
cp->adv_data_len = adv_data_len;
memcpy(cp->data, adv_data, adv_data_len);
free(adv_data);
- if (!mgmt_send(ad->manager->mgmt, MGMT_OP_ADD_ADVERTISING,
- ad->manager->mgmt_index, param_len, cp,
- add_advertising_callback, ad, NULL)) {
+ if (!mgmt_send(client->manager->mgmt, MGMT_OP_ADD_ADVERTISING,
+ client->manager->mgmt_index, param_len, cp,
+ add_adv_callback, client, NULL)) {
error("Failed to add Advertising Data");
free(cp);
- return btd_error_failed(ad->reg, "Failed");
+ return btd_error_failed(client->reg, "Failed");
}
free(cp);
return NULL;
}
-static DBusMessage *parse_advertisement(struct advertisement *ad)
+static DBusMessage *parse_advertisement(struct btd_adv_client *client)
{
- if (!parse_advertising_type(ad->proxy, &ad->type)) {
+ if (!parse_type(client->proxy, &client->type)) {
error("Failed to read \"Type\" property of advertisement");
goto fail;
}
- if (!parse_advertising_service_uuids(ad->proxy, ad->data)) {
+ if (!parse_service_uuids(client->proxy, client->data)) {
error("Property \"ServiceUUIDs\" failed to parse");
goto fail;
}
- if (!parse_advertising_solicit_uuids(ad->proxy, ad->data)) {
+ if (!parse_solicit_uuids(client->proxy, client->data)) {
error("Property \"SolicitUUIDs\" failed to parse");
goto fail;
}
- if (!parse_advertising_manufacturer_data(ad->proxy, ad->data)) {
+ if (!parse_manufacturer_data(client->proxy, client->data)) {
error("Property \"ManufacturerData\" failed to parse");
goto fail;
}
- if (!parse_advertising_service_data(ad->proxy, ad->data)) {
+ if (!parse_service_data(client->proxy, client->data)) {
error("Property \"ServiceData\" failed to parse");
goto fail;
}
- if (!parse_advertising_include_tx_power(ad->proxy,
- &ad->include_tx_power)) {
+ if (!parse_include_tx_power(client->proxy, &client->include_tx_power)) {
error("Property \"IncludeTxPower\" failed to parse");
goto fail;
}
- return refresh_advertisement(ad);
+ return refresh_advertisement(client);
fail:
- return btd_error_failed(ad->reg, "Failed to parse advertisement.");
+ return btd_error_failed(client->reg, "Failed to parse advertisement.");
}
-static void advertisement_proxy_added(GDBusProxy *proxy, void *data)
+static void client_proxy_added(GDBusProxy *proxy, void *data)
{
- struct advertisement *ad = data;
+ struct btd_adv_client *client = data;
DBusMessage *reply;
- reply = parse_advertisement(ad);
+ reply = parse_advertisement(client);
if (!reply)
return;
/* Failed to publish for some reason, remove. */
- queue_remove(ad->manager->ads, ad);
+ queue_remove(client->manager->clients, client);
- g_idle_add(advertisement_free_idle_cb, ad);
+ g_idle_add(client_free_idle_cb, client);
g_dbus_send_message(btd_get_dbus_connection(), reply);
- dbus_message_unref(ad->reg);
- ad->reg = NULL;
+ dbus_message_unref(client->reg);
+ client->reg = NULL;
}
-static struct advertisement *advertisement_create(DBusConnection *conn,
+static struct btd_adv_client *client_create(struct btd_adv_manager *manager,
+ DBusConnection *conn,
DBusMessage *msg, const char *path)
{
- struct advertisement *ad;
+ struct btd_adv_client *client;
const char *sender = dbus_message_get_sender(msg);
if (!path || !g_str_has_prefix(path, "/"))
return NULL;
- ad = new0(struct advertisement, 1);
- ad->client = g_dbus_client_new_full(conn, sender, path, path);
- if (!ad->client)
+ client = new0(struct btd_adv_client, 1);
+ client->client = g_dbus_client_new_full(conn, sender, path, path);
+ if (!client->client)
goto fail;
- ad->owner = g_strdup(sender);
- if (!ad->owner)
+ client->owner = g_strdup(sender);
+ if (!client->owner)
goto fail;
- ad->path = g_strdup(path);
- if (!ad->path)
+ client->path = g_strdup(path);
+ if (!client->path)
goto fail;
DBG("Adding proxy for %s", path);
- ad->proxy = g_dbus_proxy_new(ad->client, path, LE_ADVERTISEMENT_IFACE);
- if (!ad->proxy)
+ client->proxy = g_dbus_proxy_new(client->client, path,
+ LE_ADVERTISEMENT_IFACE);
+ if (!client->proxy)
goto fail;
- g_dbus_client_set_proxy_handlers(ad->client, advertisement_proxy_added,
- NULL, NULL, ad);
+ g_dbus_client_set_proxy_handlers(client->client, client_proxy_added,
+ NULL, NULL, client);
+
+ client->reg = dbus_message_ref(msg);
- ad->reg = dbus_message_ref(msg);
+ client->data = bt_ad_new();
+ if (!client->data)
+ goto fail;
- ad->data = bt_ad_new();
- if (!ad->data)
+ client->instance = util_get_uid(&manager->instance_bitmap,
+ manager->max_ads);
+ if (!client->instance)
goto fail;
- return ad;
+ client->manager = manager;
+
+ return client;
fail:
- advertisement_free(ad);
+ client_free(client);
return NULL;
}
DBusMessage *msg,
void *user_data)
{
- struct btd_advertising *manager = user_data;
+ struct btd_adv_manager *manager = user_data;
DBusMessageIter args;
- struct advertisement *ad;
+ struct btd_adv_client *client;
struct dbus_obj_match match;
- uint8_t instance;
DBG("RegisterAdvertisement");
match.owner = dbus_message_get_sender(msg);
- if (queue_find(manager->ads, match_advertisement, &match))
+ if (queue_find(manager->clients, match_client, &match))
return btd_error_already_exists(msg);
- instance = util_get_uid(&manager->instance_bitmap, manager->max_ads);
- if (!instance)
- return btd_error_failed(msg, "Maximum advertisements reached");
-
dbus_message_iter_next(&args);
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
return btd_error_invalid_args(msg);
- ad = advertisement_create(conn, msg, match.path);
- if (!ad)
+ client = client_create(manager, conn, msg, match.path);
+ if (!client)
return btd_error_failed(msg,
"Failed to register advertisement");
DBG("Registered advertisement at path %s", match.path);
- ad->instance = instance;
- ad->manager = manager;
-
- queue_push_tail(manager->ads, ad);
+ queue_push_tail(manager->clients, client);
return NULL;
}
DBusMessage *msg,
void *user_data)
{
- struct btd_advertising *manager = user_data;
+ struct btd_adv_manager *manager = user_data;
DBusMessageIter args;
- struct advertisement *ad;
+ struct btd_adv_client *client;
struct dbus_obj_match match;
DBG("UnregisterAdvertisement");
match.owner = dbus_message_get_sender(msg);
- ad = queue_find(manager->ads, match_advertisement, &match);
- if (!ad)
+ client = queue_find(manager->clients, match_client, &match);
+ if (!client)
return btd_error_does_not_exist(msg);
- advertisement_remove(ad);
+ client_remove(client);
return dbus_message_new_method_return(msg);
}
{ }
};
-static void advertising_manager_destroy(void *user_data)
+static void manager_destroy(void *user_data)
{
- struct btd_advertising *manager = user_data;
+ struct btd_adv_manager *manager = user_data;
- queue_destroy(manager->ads, advertisement_destroy);
+ queue_destroy(manager->clients, client_destroy);
mgmt_unref(manager->mgmt);
static void read_adv_features_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
- struct btd_advertising *manager = user_data;
+ struct btd_adv_manager *manager = user_data;
const struct mgmt_rp_read_adv_features *feat = param;
if (status || !param) {
error("Failed to register " LE_ADVERTISING_MGR_IFACE);
}
-static struct btd_advertising *
-advertising_manager_create(struct btd_adapter *adapter)
+static struct btd_adv_manager *manager_create(struct btd_adapter *adapter)
{
- struct btd_advertising *manager;
+ struct btd_adv_manager *manager;
- manager = new0(struct btd_advertising, 1);
+ manager = new0(struct btd_adv_manager, 1);
manager->adapter = adapter;
manager->mgmt = mgmt_new_default();
manager->mgmt_index, 0, NULL,
read_adv_features_callback, manager, NULL)) {
error("Failed to read advertising features");
- advertising_manager_destroy(manager);
+ manager_destroy(manager);
return NULL;
}
- manager->ads = queue_new();
+ manager->clients = queue_new();
return manager;
}
-struct btd_advertising *
-btd_advertising_manager_new(struct btd_adapter *adapter)
+struct btd_adv_manager *btd_adv_manager_new(struct btd_adapter *adapter)
{
- struct btd_advertising *manager;
+ struct btd_adv_manager *manager;
if (!adapter)
return NULL;
- manager = advertising_manager_create(adapter);
+ manager = manager_create(adapter);
if (!manager)
return NULL;
return manager;
}
-void btd_advertising_manager_destroy(struct btd_advertising *manager)
+void btd_adv_manager_destroy(struct btd_adv_manager *manager)
{
if (!manager)
return;
adapter_get_path(manager->adapter),
LE_ADVERTISING_MGR_IFACE);
- advertising_manager_destroy(manager);
+ manager_destroy(manager);
}
*/
struct btd_adapter;
-struct btd_advertising;
+struct btd_adv_manager;
-struct btd_advertising *btd_advertising_manager_new(
- struct btd_adapter *adapter);
-void btd_advertising_manager_destroy(struct btd_advertising *manager);
+struct btd_adv_manager *btd_adv_manager_new(struct btd_adapter *adapter);
+void btd_adv_manager_destroy(struct btd_adv_manager *manager);
server->le_io = bt_io_listen(connect_event, NULL,
&server->le_io, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, addr,
- BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
+ BT_IO_OPT_SOURCE_TYPE,
+ btd_adapter_get_address_type(adapter),
BT_IO_OPT_CID, ATT_CID,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
BT_IO_OPT_INVALID);
GDBUS_ARGS({"max_tx_octets","q"},
{ "max_tx_time", "q" },
{ "max_rx_octets", "q"},
- { "max_rx_time", "q"})) },
+ { "max_rx_time", "q"}))},
{ GDBUS_SIGNAL("IpspStateChanged",
- GDBUS_ARGS({"connected","b"},{"if_name","s"}))},
+ GDBUS_ARGS({"connected","b"}, {"if_name","s"}))},
{ GDBUS_SIGNAL("OtcDisconnected", NULL)},
};
#endif
str = g_key_file_get_string(key_file, "General", "ManufacturerData", NULL);
if (str) {
- if (device->manufacturer_data_len < DEV_MAX_MANUFACTURER_DATA_LEN ) {
+ if (device->manufacturer_data_len < DEV_MAX_MANUFACTURER_DATA_LEN) {
load_manufacturer_data_2digit(str,
device->manufacturer_data_len, buf);
device->manufacturer_data = g_memdup(buf,
browse_request_cancel(device->browse);
-// while (device->services != NULL) {
-// struct btd_service *service = device->services->data;
-//
-// device->services = g_slist_remove(device->services, service);
-// service_remove(service);
-// }
+ // while (device->services != NULL) {
+ // struct btd_service *service = device->services->data;
+ //
+ // device->services = g_slist_remove(device->services, service);
+ // service_remove(service);
+ // }
g_slist_free(device->pending);
device->pending = NULL;
device->alias = NULL;
}
g_dbus_emit_property_changed(dbus_conn, device->path,
- DEVICE_INTERFACE, "Paired");
-// btd_device_unref(device);
+ DEVICE_INTERFACE, "Paired");
+ // btd_device_unref(device);
DBG("-");
- }
+}
void device_remove_stored_folder(struct btd_device *device)
{
io = bt_io_connect(att_connect_cb, dev, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR,
btd_adapter_get_address(adapter),
- BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
+ BT_IO_OPT_SOURCE_TYPE,
+ btd_adapter_get_address_type(adapter),
BT_IO_OPT_DEST_BDADDR, &dev->bdaddr,
BT_IO_OPT_DEST_TYPE, dev->bdaddr_type,
BT_IO_OPT_CID, ATT_CID,
device, NULL, NULL,
BT_IO_OPT_SOURCE_BDADDR,
btd_adapter_get_address(adapter),
- BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
+ BT_IO_OPT_SOURCE_TYPE,
+ btd_adapter_get_address_type(adapter),
BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
BT_IO_OPT_CID, ATT_CID,
database->profiles = queue_new();
database->ccc_callbacks = queue_new();
- database->db_id = gatt_db_register(database->db, gatt_db_service_added,
- gatt_db_service_removed,
- database, NULL);
- if (!database->db_id)
- goto fail;
-
addr = btd_adapter_get_address(adapter);
database->le_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, addr,
- BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
+ BT_IO_OPT_SOURCE_TYPE,
+ btd_adapter_get_address_type(adapter),
BT_IO_OPT_CID, ATT_CID,
BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
BT_IO_OPT_INVALID);
register_core_services(database);
+ database->db_id = gatt_db_register(database->db, gatt_db_service_added,
+ gatt_db_service_removed,
+ database, NULL);
+
+ if (!database->db_id)
+ goto fail;
+
return database;
fail:
}
bool bt_crypto_random_bytes(struct bt_crypto *crypto,
- uint8_t *buf, uint8_t num_bytes)
+ void *buf, uint8_t num_bytes)
{
ssize_t len;
void bt_crypto_unref(struct bt_crypto *crypto);
bool bt_crypto_random_bytes(struct bt_crypto *crypto,
- uint8_t *buf, uint8_t num_bytes);
+ void *buf, uint8_t num_bytes);
bool bt_crypto_e(struct bt_crypto *crypto, const uint8_t key[16],
const uint8_t plaintext[16], uint8_t encrypted[16]);
#include "src/shared/tty.h"
#include "src/shared/hci.h"
-static int open_serial(const char *path, unsigned int speed)
+static int open_serial(const char *path, unsigned int speed, bool flowctl)
{
struct termios ti;
int fd, saved_ldisc, ldisc = N_HCI;
ti.c_cflag |= (speed | CLOCAL | CREAD);
- /* Set flow control */
- ti.c_cflag |= CRTSCTS;
+ if (flowctl) {
+ /* Set flow control */
+ ti.c_cflag |= CRTSCTS;
+ }
if (tcsetattr(fd, TCSANOW, &ti) < 0) {
perror("Failed to set serial port settings");
}
static int attach_proto(const char *path, unsigned int proto,
- unsigned int speed, unsigned int flags)
+ unsigned int speed, bool flowctl, unsigned int flags)
{
int fd, dev_id;
- fd = open_serial(path, speed);
+ fd = open_serial(path, speed, flowctl);
if (fd < 0)
return -1;
"\t-A, --amp <device> Attach AMP controller\n"
"\t-P, --protocol <proto> Specify protocol type\n"
"\t-S, --speed <baudrate> Specify which baudrate to use\n"
+ "\t-N, --noflowctl Disable flow control\n"
"\t-h, --help Show help options\n");
}
{ "amp", required_argument, NULL, 'A' },
{ "protocol", required_argument, NULL, 'P' },
{ "speed", required_argument, NULL, 'S' },
+ { "noflowctl",no_argument, NULL, 'N' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ }
int main(int argc, char *argv[])
{
const char *bredr_path = NULL, *amp_path = NULL, *proto = NULL;
- bool raw_device = false;
+ bool flowctl = true, raw_device = false;
sigset_t mask;
int exit_status, count = 0, proto_id = HCI_UART_H4;
unsigned int speed = B115200;
for (;;) {
int opt;
- opt = getopt_long(argc, argv, "B:A:P:S:Rvh",
+ opt = getopt_long(argc, argv, "B:A:P:S:NRvh",
main_options, NULL);
if (opt < 0)
break;
return EXIT_FAILURE;
}
break;
+ case 'N':
+ flowctl = false;
+ break;
case 'R':
raw_device = true;
break;
if (raw_device)
flags = (1 << HCI_UART_RAW_DEVICE);
- fd = attach_proto(bredr_path, proto_id, speed, flags);
+ fd = attach_proto(bredr_path, proto_id, speed, flowctl, flags);
if (fd >= 0) {
mainloop_add_fd(fd, 0, uart_callback, NULL, NULL);
count++;
if (raw_device)
flags = (1 << HCI_UART_RAW_DEVICE);
- fd = attach_proto(amp_path, proto_id, speed, flags);
+ fd = attach_proto(amp_path, proto_id, speed, flowctl, flags);
if (fd >= 0) {
mainloop_add_fd(fd, 0, uart_callback, NULL, NULL);
count++;
#define test_bredrle_full(name, data, setup, func, timeout) \
do { \
struct test_data *user; \
- user = malloc(sizeof(struct test_data)); \
- if (!user) \
- break; \
+ user = new0(struct test_data, 1); \
user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
user->test_setup = setup; \
user->test_data = data; \
user->expected_manufacturer = 0x003f; \
user->expected_supported_settings = 0x0000bfff; \
user->initial_settings = 0x00000080; \
- user->unmet_conditions = 0; \
tester_add_full(name, data, \
test_pre_setup, test_setup, func, NULL, \
test_post_teardown, timeout, user, free); \
#define test_bredr20(name, data, setup, func) \
do { \
struct test_data *user; \
- user = malloc(sizeof(struct test_data)); \
- if (!user) \
- break; \
+ user = new0(struct test_data, 1); \
user->hciemu_type = HCIEMU_TYPE_LEGACY; \
user->test_setup = setup; \
user->test_data = data; \
user->expected_manufacturer = 0x003f; \
user->expected_supported_settings = 0x000010bf; \
user->initial_settings = 0x00000080; \
- user->unmet_conditions = 0; \
tester_add_full(name, data, \
test_pre_setup, test_setup, func, NULL, \
test_post_teardown, 2, user, free); \
#define test_bredr(name, data, setup, func) \
do { \
struct test_data *user; \
- user = malloc(sizeof(struct test_data)); \
- if (!user) \
- break; \
+ user = new0(struct test_data, 1); \
user->hciemu_type = HCIEMU_TYPE_BREDR; \
user->test_setup = setup; \
user->test_data = data; \
user->expected_manufacturer = 0x003f; \
user->expected_supported_settings = 0x000011ff; \
user->initial_settings = 0x00000080; \
- user->unmet_conditions = 0; \
tester_add_full(name, data, \
test_pre_setup, test_setup, func, NULL, \
test_post_teardown, 2, user, free); \
#define test_le(name, data, setup, func) \
do { \
struct test_data *user; \
- user = malloc(sizeof(struct test_data)); \
- if (!user) \
- break; \
+ user = new0(struct test_data, 1); \
user->hciemu_type = HCIEMU_TYPE_LE; \
user->test_setup = setup; \
user->test_data = data; \
user->expected_manufacturer = 0x003f; \
user->expected_supported_settings = 0x0000be1b; \
user->initial_settings = 0x00000200; \
- user->unmet_conditions = 0; \
tester_add_full(name, data, \
test_pre_setup, test_setup, func, NULL, \
test_post_teardown, 2, user, free); \
test_add_condition(data);
}
-static void test_device_found(const void *test_data)
+static void trigger_device_found(void *user_data)
{
struct test_data *data = tester_get_data();
const struct generic_data *test = data->test_data;
if (data->hciemu_type != HCIEMU_TYPE_LE)
bthost_write_scan_enable(bthost, 0x03);
+ test_condition_complete(data);
+}
+
+static void test_device_found(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
test_command_generic(test_data);
+
+ /* Make sure discovery is enabled before enabling advertising. */
+ tester_wait(1, trigger_device_found, NULL);
+ test_add_condition(data);
}
static void pairing_new_conn(uint16_t handle, void *user_data)