From 68de4f90d5795475016189cff12d7e0011b07d37 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Wed, 14 Dec 2016 18:10:54 +0900 Subject: merge the Settings in CES2017 and bindings from ALPS Change-Id: I00a7a6c5dae1cd579f91d543b0f5fba4616a633b Signed-off-by: Tasuku Suzuki --- binding-bluetooth.pro | 11 + binding.pri | 6 + bluetooth-api.c | 503 +++++++++++++++++++++++++++++++++ bluetooth-api.h | 50 ++++ bluetooth-manager.c | 747 ++++++++++++++++++++++++++++++++++++++++++++++++++ bluetooth-manager.h | 143 ++++++++++ export.map | 1 + 7 files changed, 1461 insertions(+) create mode 100644 binding-bluetooth.pro create mode 100644 binding.pri create mode 100644 bluetooth-api.c create mode 100644 bluetooth-api.h create mode 100644 bluetooth-manager.c create mode 100644 bluetooth-manager.h create mode 100644 export.map diff --git a/binding-bluetooth.pro b/binding-bluetooth.pro new file mode 100644 index 0000000..9dba7a1 --- /dev/null +++ b/binding-bluetooth.pro @@ -0,0 +1,11 @@ +TARGET = settings-bluetooth-binding + +HEADERS = bluetooth-api.h bluetooth-manager.h +SOURCES = bluetooth-api.c bluetooth-manager.c + +LIBS += -Wl,--version-script=$$PWD/export.map + +CONFIG += link_pkgconfig +PKGCONFIG += json-c afb-daemon glib-2.0 gio-2.0 gobject-2.0 zlib + +include(binding.pri) diff --git a/binding.pri b/binding.pri new file mode 100644 index 0000000..3448a56 --- /dev/null +++ b/binding.pri @@ -0,0 +1,6 @@ +TEMPLATE = lib +CONFIG += plugin use_c_linker +CONFIG -= qt +QMAKE_CFLAGS += -Wextra -Wconversion -Wno-unused-parameter -Werror=maybe-uninitialized -Werror=implicit-function-declaration -ffunction-sections -fdata-sections -Wl,--as-needed -Wl,--gc-sections + +DESTDIR = $${OUT_PWD}/../package/root/lib diff --git a/bluetooth-api.c b/bluetooth-api.c new file mode 100644 index 0000000..f7e2d9a --- /dev/null +++ b/bluetooth-api.c @@ -0,0 +1,503 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* 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. +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include "bluetooth-api.h" +#include "bluetooth-manager.h" + + +/* + * the interface to afb-daemon + */ +const struct afb_binding_interface *afbitf; + + +/* ------ PUBLIC PLUGIN FUNCTIONS --------- */ + +/**/ +static void bt_power (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + json_object *jresp = NULL; + int ret = 0; + + jresp = json_object_new_object(); + + /* no "?value=" parameter : return current state */ + if (!value) { + gboolean power_value; + ret = adapter_get_powered(&power_value); + + if (0==ret) + { + (TRUE==power_value)?json_object_object_add (jresp, "power", json_object_new_string ("on")) + : json_object_object_add (jresp, "power", json_object_new_string ("off")); + } + else + { + afb_req_fail (request, "failed", "Unable to get power status"); + return; + } + + } + + /* "?value=" parameter is "1" or "true" */ + else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) + { + if (adapter_set_powered (TRUE)) + { + afb_req_fail (request, "failed", "no more radio devices available"); + return; + } + json_object_object_add (jresp, "power", json_object_new_string ("on")); + } + + /* "?value=" parameter is "0" or "false" */ + else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) + { + if (adapter_set_powered (FALSE)) + { + afb_req_fail (request, "failed", "Unable to release radio device"); + return; + } + + json_object_object_add (jresp, "power", json_object_new_string ("off")); + } + else + { + afb_req_fail (request, "failed", "Invalid value"); + return; + } + + afb_req_success (request, jresp, "Radio - Power set"); +} + +/**/ +static void bt_start_discovery (struct afb_req request) +{ + D_PRINTF("\n"); + int ret = 0; + + ret = adapter_start_discovery(); + + if (ret) + { + afb_req_fail (request, "failed", "Unable to start discovery"); + return; + } + + afb_req_success (request, NULL, NULL); +} + +/**/ +static void bt_stop_discovery (struct afb_req request) +{ + D_PRINTF("\n"); + int ret = 0; + + ret = adapter_stop_discovery(); + + if (ret) + { + afb_req_fail (request, "failed", "Unable to stop discovery"); + return; + } + + afb_req_success (request, NULL, NULL); +} + + +/**/ +static void bt_discovery_result (struct afb_req request) +{ + D_PRINTF("\n"); + GSList *list = NULL; + adapter_update_devices(); + list = adapter_get_devices_list(); + if (NULL == list) + { + afb_req_fail (request, "failed", "No find devices"); + return; + } + + json_object *my_array = json_object_new_array(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + //D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + + json_object *jresp = json_object_new_object(); + json_object *jstring1 = NULL; + json_object *jstring2 = NULL; + json_object *jstring3 = NULL; + json_object *jstring4 = NULL; + json_object *jstring5 = NULL; + json_object *jstring6 = NULL; + + + + if (BDdevice->bdaddr) + { + jstring1 = json_object_new_string(BDdevice->bdaddr); + } + else + { + jstring1 = json_object_new_string(""); + } + + + if (BDdevice->name) + { + jstring2 = json_object_new_string(BDdevice->name); + } + else + { + jstring2 = json_object_new_string(""); + } + + jstring3 = (TRUE == BDdevice->paired) ? json_object_new_string("True"):json_object_new_string("False"); + jstring4 = (TRUE == BDdevice->connected) ? json_object_new_string("True"):json_object_new_string("False"); + jstring5 = (TRUE == isAVPConnected(BDdevice)) ? json_object_new_string("True"):json_object_new_string("False"); + jstring6 = (TRUE == isHFPConnected(BDdevice)) ? json_object_new_string("True"):json_object_new_string("False"); + + + json_object_object_add(jresp, "Address", jstring1); + json_object_object_add(jresp, "Name", jstring2); + json_object_object_add(jresp, "Paired", jstring3); + json_object_object_add(jresp, "Connected", jstring4); + json_object_object_add(jresp, "AVPConnected", jstring5); + json_object_object_add(jresp, "HFPConnected", jstring6); + json_object_array_add(my_array, jresp); + } + + afb_req_success(request, my_array, "BT - Scan Result is Displayed"); +} + +/**/ +static void bt_pair (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_pair(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); + +} + +/**/ +static void bt_cancel_pairing (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_cancelPairing(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); + +} + +/**/ +static void bt_connect (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_connect(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + +/**/ +static void bt_disconnect (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_disconnect(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + +/**/ +static void bt_remove_device (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = adapter_remove_device(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + + +/**/ +static void bt_set_property (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *address = afb_req_value (request, "Address"); + const char *property = afb_req_value (request, "Property"); + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == address || NULL==property || NULL==value) + { + afb_req_fail (request, "failed", "Please Check Input Parameter"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,address)) + { + //D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_set_property(BDdevice, property, value); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device set property failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + + + +/* + * array of the verbs exported to afb-daemon + */ +static const struct afb_verb_desc_v1 binding_verbs[]= { +/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */ +{ .name = "power", .session = AFB_SESSION_NONE, .callback = bt_power, .info = "Set Bluetooth Power ON or OFF" }, +{ .name = "start_discovery", .session = AFB_SESSION_NONE, .callback = bt_start_discovery, .info = "Start discovery" }, +{ .name = "stop_discovery", .session = AFB_SESSION_NONE, .callback = bt_stop_discovery, .info = "Stop discovery" }, +{ .name = "discovery_result", .session = AFB_SESSION_NONE, .callback = bt_discovery_result, .info = "Get discovery result" }, +{ .name = "remove_device", .session = AFB_SESSION_NONE, .callback = bt_remove_device, .info = "Remove the special device" }, +{ .name = "pair", .session = AFB_SESSION_NONE, .callback = bt_pair, .info = "Pair to special device" }, +{ .name = "cancel_pair", .session = AFB_SESSION_NONE, .callback = bt_cancel_pairing, .info = "Cancel the pairing process" }, +{ .name = "connect", .session = AFB_SESSION_NONE, .callback = bt_connect, .info = "Connect to special device" }, +{ .name = "disconnect", .session = AFB_SESSION_NONE, .callback = bt_disconnect, .info = "Disconnect special device" }, +{ .name = "set_property", .session = AFB_SESSION_NONE, .callback = bt_set_property, .info = "Set special device property" }, + +{ .name = NULL } /* marker for end of the array */ +}; + +/* + * description of the binding for afb-daemon + */ +static const struct afb_binding binding_description = +{ + .type = AFB_BINDING_VERSION_1, + .v1 = { + .info = "Application Framework Binder - Bluetooth Manager plugin", + .prefix = "Bluetooth-Manager", + .verbs = binding_verbs + } +}; + +/* + * activation function for registering the binding called by afb-daemon + */ +const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf) +{ + afbitf = itf; // records the interface for accessing afb-daemon + //D_PRINTF("\n"); +#if 1 +//temp solution to fix configure Bluetooth USB Dongle + system("rfkill unblock bluetooth"); + system("hciconfig hci0 up"); +#endif + BluetoothManageInit(); + return &binding_description; +} + +#if 0 +int afbBindingV1ServiceInit(struct afb_service service) +{ + return BluetoothManageInit(); +} +#endif + + +/************************************** The End Of File **************************************/ + diff --git a/bluetooth-api.h b/bluetooth-api.h new file mode 100644 index 0000000..8a7e593 --- /dev/null +++ b/bluetooth-api.h @@ -0,0 +1,50 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* 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. +*/ + + +#ifndef BLUETOOTH_API_H +#define BLUETOOTH_API_H + + + + +//#define _DEBUG +#ifdef _DEBUG +#define D_PRINTF(fmt, args...) \ + printf("[DEBUG][%s:%d:%s]"fmt, __FILE__, __LINE__, __FUNCTION__, ## args) +#define D_PRINTF_RAW(fmt, args...) \ + printf(""fmt, ## args) +#else /* ifdef _DEBUG */ +#define D_PRINTF(fmt, args...) +#define D_PRINTF_RAW(fmt, args...) +#endif /* ifdef _DEBUG */ +#define E_PRINTF(fmt, args...) \ + printf("[ERROR][%s:%d:%s]"fmt, __FILE__, __LINE__, __FUNCTION__, ## args) + + +/* -------------- PLUGIN DEFINITIONS ----------------- */ + +typedef struct { + void *bt_server; /* handle to implementation */ + unsigned int index; /* currently selected media file */ +} BtCtxHandleT; + +#endif /* BLUETOOTH_API_H */ + + + +/************************************** The End Of File **************************************/ + + diff --git a/bluetooth-manager.c b/bluetooth-manager.c new file mode 100644 index 0000000..4c49196 --- /dev/null +++ b/bluetooth-manager.c @@ -0,0 +1,747 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* 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 +#include +#include +#include +#include +#include +#include + +#include "bluetooth-api.h" +#include "bluetooth-manager.h" + +Client cli = { 0 }; + +stBluetoothManage BluetoothManage = { 0 }; + +/* ------ LOCAL FUNCTIONS --------- */ + +/* + register the agent, and register signal watch + */ +void bt_manage_dbus_init(void) { + D_PRINTF("\n"); + + //InitDBusCommunication(); + +} +/* ------ PUBLIC PLUGIN FUNCTIONS --------- */ + +/* + * Init the Bluetooth Manager + * Note: bluetooth-api shall do BluetoothManageInit() first before call other APIs. + */ +int BluetoothManageInit() { + D_PRINTF("\n"); + + BluetoothManage.device = NULL; + g_mutex_init(&(BluetoothManage.m)); + + bt_manage_dbus_init(); + + return 0; +} + +/* + * Set the Bluez Adapter Property "Powered" value + * If success return 0, else return -1; + */ +int adapter_set_powered(gboolean powervalue) { + D_PRINTF("value:%d\n",powervalue); + GDBusConnection *connection; + GError *error = NULL; + + GVariant *value; + gboolean result; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + FREEDESKTOP_PROPERTIES, "Set", + g_variant_new("(ssv)", ADAPTER_INTERFACE, "Powered", + g_variant_new("b", powervalue)), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; +} + +/* + * Get the Bluez Adapter Property "Powered" value + * If success return 0, else return -1; + */ +int adapter_get_powered(gboolean *powervalue) { + D_PRINTF("\n"); + GDBusConnection *connection; + GError *error = NULL; + GVariant *value = NULL; + GVariant *subValue = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + FREEDESKTOP_PROPERTIES, "Get", + g_variant_new("(ss)", ADAPTER_INTERFACE, "Powered"), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + g_variant_get(value, "(v)", &subValue); + g_variant_get(subValue, "b", powervalue); + g_variant_unref(value); + + D_PRINTF("get ret :%d\n",*powervalue); + return 0; +} + +/* + * Call the Bluez Adapter Method "StartDiscovery" + * If success return 0, else return -1; + */ +int adapter_start_discovery() { + D_PRINTF("\n"); + GDBusConnection *connection = NULL; + GError *error = NULL; + GVariant *value = NULL; + GVariant *subValue = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + ADAPTER_INTERFACE, "StartDiscovery", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; +} + +/* + * Call the Bluez Adapter Method "StopDiscovery" + * If success return 0, else return -1; + */ +int adapter_stop_discovery() { + D_PRINTF("\n"); + GDBusConnection *connection = NULL; + GError *error = NULL; + GVariant *value = NULL; + GVariant *subValue = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + ADAPTER_INTERFACE, "StopDiscovery", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + + return 0; +} + +/* + * Call the Bluez Adapter Method "RemoveDevice" + * If success return 0, else return -1; + */ +int adapter_remove_device(struct btd_device * addr) { + D_PRINTF("\n%s\t%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + ADAPTER_INTERFACE, "RemoveDevice", g_variant_new("(o)", addr->path), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * Get the store device list. + */ +//FIXME: gdevices should be added the lock/unlock +GSList* adapter_get_devices_list() { + return BluetoothManage.device; +} + +void lock_devices_list(void) { + g_mutex_lock(&(BluetoothManage.m)); +} + +void unlock_devices_list(void) { + g_mutex_unlock(&(BluetoothManage.m)); +} + +/* + * Update the device list + * Call GetManagedObjects + * reply type is "Dict of {Object Path, Dict of {String, Dict of {String, Variant}}}" + */ +#if 0 +// Test Function +/* recursively iterate a container */ +void iterate_container_recursive (GVariant *container) +{ + GVariantIter iter; + GVariant *child; + + g_variant_iter_init (&iter, container); + while ((child = g_variant_iter_next_value (&iter))) + { + g_print ("type '%s'\n", g_variant_get_type_string (child)); + + if (g_variant_is_container (child)) + iterate_container_recursive (child); + + g_variant_unref (child); + } +} +#endif + +int adapter_update_devices() { + D_PRINTF("\n"); + GDBusConnection *connection = NULL; + GError *error = NULL; + GVariant *value = NULL; + GSList *newDeviceList = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, "/", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL, + NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + GVariant *subValue = NULL; + GVariant *subValue_1 = NULL; + GVariantIter *subValueIter; + + g_variant_get(value, "(*)", &subValue); + + g_variant_get(subValue, "a*", &subValueIter); + while (g_variant_iter_loop(subValueIter, "*", &subValue_1)) { + +#if 0 + iterate_container_recursive(subValue_1); +#else + +//FIXME:Bad solution to get the BT address and name + GVariantIter dbus_object_iter; + GVariant *dbusObjecValue; + GVariant *dbusObjecSubValue; + gchar *dbusObjecPath; + struct btd_device *device; + + g_variant_iter_init(&dbus_object_iter, subValue_1); + + //DBus Object + dbusObjecValue = g_variant_iter_next_value(&dbus_object_iter); + + g_variant_get(dbusObjecValue, "o", &dbusObjecPath); + + //ObjectPath is /org/bluez/hci0/dev_xx_xx_xx_xx_xx_xx + if ((37 != strlen(dbusObjecPath)) + || (NULL + == g_strrstr_len(dbusObjecPath, 19, + "/org/bluez/hci0/dev"))) { + g_variant_unref(dbusObjecValue); + continue; + } + device = g_try_malloc0(sizeof(struct btd_device)); + device->path = g_strdup(dbusObjecPath); + g_variant_unref(dbusObjecValue); + D_PRINTF("Found new device%s\n",device->path ); + + //DBus Interfaces and Method/Properties under Interface + dbusObjecSubValue = g_variant_iter_next_value(&dbus_object_iter); + + GVariantIter *interfaces_iter; + GVariant *interfaces_subValue; + g_variant_get(dbusObjecSubValue, "a*", &interfaces_iter); + + while (g_variant_iter_loop(interfaces_iter, "*", &interfaces_subValue)) { + // D_PRINTF("\t%s\n",g_variant_get_type_string(interfaces_subValue)); + + GVariantIter MethodsSignalProperties_iter; + GVariant *MethodsSignalProperties_name; + GVariant *MethodsSignalProperties_value; + gchar *properties_name; + + g_variant_iter_init(&MethodsSignalProperties_iter, + interfaces_subValue); + + //DBus Interfaces + MethodsSignalProperties_name = g_variant_iter_next_value( + &MethodsSignalProperties_iter); + + g_variant_get(MethodsSignalProperties_name, "s", &properties_name); + //D_PRINTF("\t%s\n",properties_name); + g_variant_unref(MethodsSignalProperties_name); + + if (NULL + == g_strrstr_len(properties_name, 20, + "org.bluez.Device1")) { + continue; + } + + D_PRINTF("\t%s\n",properties_name); + + //DBus XXX + MethodsSignalProperties_value = g_variant_iter_next_value( + &MethodsSignalProperties_iter); + + GVariantIter *subValue_iter; + GVariant *subValueVariant; + g_variant_get(MethodsSignalProperties_value, "a*", &subValue_iter); + + while (g_variant_iter_loop(subValue_iter, "*", &subValueVariant)) { + GVariantIter sub_subValue_iter; + GVariant *sub_subValue_name; + GVariant *sub_subValue_value; + gchar *key_1 = NULL; + gchar *key_2 = NULL; + + g_variant_iter_init(&sub_subValue_iter, subValueVariant); + + //DBus Interfaces + sub_subValue_name = g_variant_iter_next_value( + &sub_subValue_iter); + + g_variant_get(sub_subValue_name, "s", &key_1); + D_PRINTF("\t\t%s\n",key_1); + + //DBus XXX + sub_subValue_value = g_variant_iter_next_value( + &sub_subValue_iter); + + GVariant *dbus_value; + dbus_value = g_variant_get_variant(sub_subValue_value); + + if (g_variant_is_of_type(dbus_value, G_VARIANT_TYPE_STRING)) { + g_variant_get(dbus_value, "s", &key_2); + //D_PRINTF("\t\t\t%s\ts%s\n",key_1,key_2); + + if (g_strrstr_len(key_1, 10, "Address")) { + device->bdaddr = g_strdup(key_2); + } else if (g_strrstr_len(key_1, 10, "Name")) { + device->name = g_strdup(key_2); + } + g_free(key_2); + + } else if (g_variant_is_of_type(dbus_value, + G_VARIANT_TYPE_BOOLEAN)) { + gboolean properties_value; + g_variant_get(dbus_value, "b", &properties_value); + + if (g_strrstr_len(key_1, 10, "Paired")) { + device->paired = properties_value; + } else if (g_strrstr_len(key_1, 10, "Blocked")) { + device->blocked = properties_value; + } else if (g_strrstr_len(key_1, 10, "Connected")) { + device->connected = properties_value; + } else if (g_strrstr_len(key_1, 10, "Trusted")) { + device->trusted = properties_value; + } + + } + g_variant_unref(sub_subValue_name); + g_variant_unref(sub_subValue_value); + + } + g_variant_iter_free(subValue_iter); + + g_variant_unref(MethodsSignalProperties_value); + + } + g_variant_iter_free(interfaces_iter); + + g_variant_unref(dbusObjecSubValue); + +#endif + + newDeviceList = g_slist_append(newDeviceList, device); + + } + + g_variant_iter_free(subValueIter); + + g_variant_unref(value); + + //clean first + GSList * temp = BluetoothManage.device; + while (temp) { + struct btd_device *BDdevice = temp->data; + temp = temp->next; + + BluetoothManage.device = g_slist_remove_all(BluetoothManage.device, + BDdevice); + //D_PRINTF("\n%s\n%s\n",BDdevice->bdaddr,BDdevice->name); + if (BDdevice->bdaddr) { + g_free(BDdevice->bdaddr); + } + if (BDdevice->name) { + g_free(BDdevice->name); + } + if (BDdevice->path) { + g_free(BDdevice->path); + } + g_free(BDdevice); + + } + + BluetoothManage.device = newDeviceList; + +} + +/* + * send pairing command + * If success return 0, else return -1; + */ +int device_pair(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "Pair", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * send cancel pairing command + * If success return 0, else return -1; + */ +int device_cancelPairing(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "CancelPairing", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} +/* + * send connect command + * If success return 0, else return -1; + */ +int device_connect(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "Connect", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * send disconnect command + * If success return 0, else return -1; + */ +int device_disconnect(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "Disconnect", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * set remote device property + * If success return 0, else return -1; + */ +int device_set_property(struct btd_device * addr, const char *property_name, + const char *property_value) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *ret; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + //Only support set "Trusted" + if (strcmp(property_name, "Trusted")) { + D_PRINTF("Not support property name\n"); + return -1; + } + + gboolean value; + if (atoi(property_value) == 1 || !strcasecmp(property_value, "true")) { + value = TRUE; + } else if (atoi(property_value) == 0 + || !strcasecmp(property_value, "false")) { + value = FALSE; + } else { + D_PRINTF("Not support property value\n"); + return -1; + } + + ret = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + FREEDESKTOP_PROPERTIES, "Set", + g_variant_new("(ssv)", DEVICE_INTERFACE, property_name, + g_variant_new("b", value)), NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == ret) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(ret); + return 0; +} + +int isAVPConnected(struct btd_device *addr) { + + GDBusConnection *connection; + + GError *error = NULL; + GVariant *value; + GVariant *variantValue; + gboolean status; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + +// value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, BDdevice->path, FREEDESKTOP_PROPERTIES, +// "Get", g_variant_new("(ss)",MEDIA_CONTROL1_INTERFACE,"Connected"), +// NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + FREEDESKTOP_PROPERTIES, "Get", + g_variant_new("(ss)", MEDIA_CONTROL1_INTERFACE, "Connected"), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + + g_error_free(error); + return -1; + } + + else { + g_variant_get(value, "(v)", &variantValue); + g_variant_get(variantValue, "b", &status); + printf("Address: %s:%i",addr->bdaddr, status); + return status; + } + + return 0; + +} + +int isHFPConnected(struct btd_device *addr) { + + GDBusConnection *connection; + + GError *error = NULL; + GVariant *value; + gchar *ofono_path; + gboolean status; + + GVariantIter *array; + GVariant *var = NULL; + const gchar *key = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + +//path=/hfp/org/bluez/hci0/dev_E0_98_61_7D_D3_1E; interface=org.ofono.Modem; member=GetProperties + + ofono_path = g_strconcat("/hfp", addr->path, NULL); + + + value = g_dbus_connection_call_sync(connection, OFONO_SERVICE, ofono_path, + OFONO_MODEM_INTERFACE, "GetProperties", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + + g_error_free(error); + return -1; + } + + else { + + g_variant_get(value, "(a{sv})", &array); + while (g_variant_iter_loop(array, "{sv}", &key, &var)) { + if (g_strcmp0(key, "Powered") == 0) { + + g_variant_get(var, "b", &status); + + return status; + + } + } + g_variant_iter_free(array); + g_variant_unref(value); + g_free(ofono_path); + + return status; + } + + return 0; + +} + +/************************************** The End Of File **************************************/ + diff --git a/bluetooth-manager.h b/bluetooth-manager.h new file mode 100644 index 0000000..cb018b0 --- /dev/null +++ b/bluetooth-manager.h @@ -0,0 +1,143 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* 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. +*/ + + +#ifndef BLUETOOTH_MANAGER_H +#define BLUETOOTH_MANAGER_H + +#include +#include +//#include +#include +#include +#include +//service +#define AGENT_SERVICE "org.agent" + +//remote service +#define BLUEZ_SERVICE "org.bluez" +#define OFONO_SERVICE "org.ofono" +#define CLIENT_SERVICE "org.bluez.obex" + +//object path +#define OFONO_MANAGER_PATH "/" +#define ADAPTER_PATH "/org/bluez/hci0" +#define OBEX_CLIENT_PATH "/org/bluez/obex" +#define AGENT_PATH "/org/bluez" + +//interface +#define ADAPTER_INTERFACE "org.bluez.Adapter1" +#define DEVICE_INTERFACE "org.bluez.Device1" +#define AGENT_MANAGER_INTERFACE "org.bluez.AgentManager" +#define SERVICE_INTERFACE "org.bluez.Service" +#define AGENT_INTERFACE "org.bluez.Agent" + +#define CLIENT_INTERFACE "org.bluez.obex.Client" +#define TRANSFER_INTERFACE "org.bluez.obex.Transfer" +#define SESSION_INTERFACE "org.bluez.obex.Session" +#define OBEX_ERROR_INTERFACE "org.bluez.obex.Error" +#define BLUEZ_ERROR_INTERFACE "org.bluez.Error" +#define PBAP_INTERFACE "org.bluez.obex.PhonebookAccess" +#define MAP_INTERFACE "org.bluez.obex.MessageAccess" +#define MAP_MSG_INTERFACE "org.bluez.obex.Message" + +#define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer" +#define MEDIA_FOLDER_INTERFACE "org.bluez.MediaFolder" +#define MEDIA_ITEM_INTERFACE "org.bluez.MediaItem" +#define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport" +#define MEDIA_CONTROL1_INTERFACE "org.bluez.MediaControl1" + + +#define OFONO_HANDSFREE_INTERFACE "org.ofono.Handsfree" +#define OFONO_MANAGER_INTERFACE "org.ofono.Manager" +#define OFONO_MODEM_INTERFACE "org.ofono.Modem" +#define OFONO_VOICECALL_INTERFACE "org.ofono.VoiceCall" +#define OFONO_VOICECALL_MANAGER_INTERFACE "org.ofono.VoiceCallManager" +#define OFONO_NETWORK_REGISTRATION_INTERFACE "org.ofono.NetworkRegistration" +#define OFONO_NETWORK_OPERATOR_INTERFACE "org.ofono.NetworkOperator" +#define OFONO_CALL_VOLUME_INTERFACE "org.ofono.CallVolume" + +#define FREEDESKTOP_INTROSPECT "org.freedesktop.DBus.Introspectable" +#define FREEDESKTOP_PROPERTIES "org.freedesktop.DBus.Properties" + + +#define CONVERTER_CONN (cli.sys_conn) +#define AGENT_CONN (cli.agent_conn) +#define OBEX_CONN (cli.obex_conn) + +#define DBUS_REPLY_TIMEOUT (120 * 1000) +#define DBUS_REPLY_TIMEOUT_SHORT (10 * 1000) + +//typedef void(*callback)(void); +typedef void(*callback)(int password_rejected_flag); +void register_callback(callback ptr); + + +typedef struct _client +{ + GDBusConnection *sys_conn; + GDBusConnection *agent_conn; + GDBusConnection *obex_conn; + GMainLoop *clientloop; +// FILE *fd; +// int conn_fd; +} Client; + +//Bluetooth Device Properties +struct btd_device { + gchar *bdaddr; + gchar *path; + gchar *name; + gboolean paired; + gboolean trusted; + gboolean blocked; + gboolean connected; + gboolean avconnected; + gboolean hfpconnected; + GSList *uuids; +}; + +typedef struct { + gboolean inited; + GMutex m; + GSList * device; +} stBluetoothManage; + +int BluetoothManageInit(void); + +int adapter_set_powered(gboolean value); +int adapter_get_powered(gboolean *value); +int adapter_set_discoverable(gboolean value); +int adapter_start_discovery(); +int adapter_stop_discovery(); +int adapter_update_devices(); +GSList* adapter_get_devices_list(); +int adapter_remove_device(struct btd_device * addr); +int device_pair(struct btd_device * addr); +int device_cancelPairing(struct btd_device * addr); +int device_connect(struct btd_device * addr); +//int device_connectProfile(); +int device_disconnect(struct btd_device * addr); +//int device_disconnectProfile(); +int device_set_property(struct btd_device * addr, const char *property, const char *value); + +int isAVPConnected(struct btd_device *BDdevice); +int isHFPConnected(struct btd_device *BDdevice); + +#endif /* BLUETOOTH_MANAGER_H */ + + +/************************************** The End Of File **************************************/ + diff --git a/export.map b/export.map new file mode 100644 index 0000000..0ef1ac7 --- /dev/null +++ b/export.map @@ -0,0 +1 @@ +{ global: afbBindingV1Register; local: *; }; -- cgit 1.2.3-korg