diff options
Diffstat (limited to 'binding-bluetooth/ofono-client.c')
-rw-r--r-- | binding-bluetooth/ofono-client.c | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/binding-bluetooth/ofono-client.c b/binding-bluetooth/ofono-client.c new file mode 100644 index 0000000..4b17dab --- /dev/null +++ b/binding-bluetooth/ofono-client.c @@ -0,0 +1,672 @@ +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> +#include <glib.h> +#include <gio/gio.h> +#include <glib-object.h> + +#include "lib_ofono.h" +#include "lib_ofono_modem.h" +#include "ofono-client.h" + +#ifdef OFONO_THREAD +static GMainLoop *OfonoLoop = NULL; +#endif + +static stOfonoManager OfonoManager = { 0 }; +static Ofono_RegisterCallback_t ofono_RegisterCallback = { 0 }; + + +/* ------ LOCAL FUNCTIONS --------- */ +static OFONOMODEMOrgOfonoModem* modem_create_proxy(struct ofono_modem *modem); + + +/* + * make a copy of each element + * And, to entirely free the new btd_device, you could do: modem_free + */ +struct ofono_modem *modem_copy(struct ofono_modem* modem) +{ + struct ofono_modem * temp; + + if (NULL == modem) { + return NULL; + } + + temp = g_malloc0(sizeof(struct ofono_modem)); + temp->path = g_strdup(modem->path); + + temp->proxy = g_object_ref (modem->proxy); + + temp->powered = modem->powered; + + return temp; +} + +/* + * Frees all of the memory + */ +static void modem_free(struct ofono_modem* modem) +{ + + if (NULL == modem) { + return ; + } + + if (modem->path) { + g_free(modem->path); + modem->path = NULL; + } + + if (modem->proxy){ + g_object_unref(modem->proxy); + modem->proxy = NULL; + } + + g_free(modem); + +} + +#if 0 +//debug print +void modem_print(struct ofono_modem *modem) +{ + gchar *s; + g_print("device %p\n",modem); + g_print("path\t\t:%s\n",modem->path); + g_print("powered\t\t:%d\n",modem->powered); + +} +#endif + +static int modem_path_cmp(struct ofono_modem * modem, const gchar* path ) +{ + return g_strcmp0 (modem->path, path); +} + +static void modem_list_lock(void) +{ + g_mutex_lock(&(OfonoManager.m)); +} + +static void modem_list_unlock(void) +{ + g_mutex_unlock(&(OfonoManager.m)); +} + +#if 0 +//debug print +void modem_list_print() +{ + GSList * temp = OfonoManager.modem; + while (temp) { + struct ofono_modem *modem = temp->data; + temp = temp->next; + g_print("----------------------------------------\n"); + modem_print(modem); + } + g_print("----------------------------------------\n"); +} +#endif + + +/* + * remove all the devices +*/ +static void modem_list_cleanup() +{ + LOGD("\n"); + GSList * temp = OfonoManager.modem; + while (temp) { + struct ofono_modem *modem = temp->data; + temp = temp->next; + + OfonoManager.modem = g_slist_remove_all(OfonoManager.modem, + modem); + + modem_free(modem); + } +} + +/* + * search ofono modem by path + * Returns the first found btd_device or NULL if it is not found + */ +static struct ofono_modem *modem_list_find_modem_by_path(const char* path) +{ + //LOGD("path%s\n",path); + GSList * temp = NULL; + + temp = g_slist_find_custom (OfonoManager.modem, path, + (GCompareFunc)modem_path_cmp); + + if (temp) { + return temp->data; + } + + return NULL; +} + +static void on_modem_property_changed (OFONOMODEMOrgOfonoModem* object, + gchar* property, + GVariant *value, + gpointer userdata) +{ +#ifdef _DEBUG_PRINT_DBUS + gchar *s; + + g_print ("%s\n",property); + s = g_variant_print (value, TRUE); + g_print (" %s\n", s); + g_free (s); +#endif + + struct ofono_modem *modem; + + + if (NULL==property || NULL==value || NULL==userdata){ + LOGD(" receive null data\n"); + return; + } + + modem = userdata; + + if (0 == g_strcmp0(property, "Powered")) + { + + GVariant *temp = g_variant_get_variant (value); + //g_print ("update\n"); + gboolean new_value; + //gboolean old_value; + g_variant_get(temp, "b", &new_value ); + g_variant_unref(temp); + LOGD("Powered %d\n",new_value); + //old_value = modem->powered; + modem->powered = new_value; + + if (NULL != ofono_RegisterCallback.modem_properties_changed) + { + ofono_RegisterCallback.modem_properties_changed(modem); + } + } + + +} + +static void on_modem_added (OFONOOrgOfonoManager* object, + gchar* path, + GVariant *value, + gpointer userdata) +{ +#ifdef _DEBUG_PRINT_DBUS + gchar *s; + + g_print ("on_modom_added\n"); + g_print ("%s\n",path); + s = g_variant_print (value, TRUE); + g_print (" %s\n", s); + g_free (s); +#endif + + + GError *error = NULL; + + if (NULL == path) + return; + + struct ofono_modem *modem = g_malloc0(sizeof(struct ofono_modem)); + + LOGD("new modem path:%s,%p\n", path, modem); + + modem->path = g_strdup(path); + modem->proxy = modem_create_proxy(modem); + + + + GVariant *property_value = NULL; + g_variant_lookup(value, "Powered", + "*", &property_value); + + if (property_value) + { + gboolean bValue = FALSE; + g_variant_get(property_value, "b", &bValue ); + modem->powered = bValue; + + g_variant_unref (property_value); + } + + modem_list_lock(); + OfonoManager.modem = g_slist_prepend(OfonoManager.modem, modem); + modem_list_unlock(); + + if (NULL != ofono_RegisterCallback.modem_added){ + ofono_RegisterCallback.modem_added(modem); + } +} + +static void on_modem_removed (OFONOOrgOfonoManager * object, + gchar* path, + gpointer userdata) +{ +#ifdef _DEBUG_PRINT_DBUS + gchar *s; + g_print ("on_modem_removed\n"); + g_print ("%s\n",path); +#endif + + struct ofono_modem *modem = NULL; + + modem_list_lock(); + + modem = modem_list_find_modem_by_path(path); + + LOGD("remove modem path:%s,%p\n", path, modem); + + if (modem){ + + OfonoManager.modem = g_slist_remove_all(OfonoManager.modem, + modem); + + if (NULL != ofono_RegisterCallback.modem_removed) + { + ofono_RegisterCallback.modem_removed(modem); + } + + modem_free(modem); + } + + modem_list_unlock(); + +} + + +static OFONOMODEMOrgOfonoModem* modem_create_proxy(struct ofono_modem *modem) +{ + GError *error = NULL; + + if (NULL == modem) + { + return NULL; + } + + if (NULL == modem->path) + { + return NULL; + } + + modem->proxy = ofono_modem_org_ofono_modem_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, + modem->path, NULL, &error); + + if (error) + { + LOGW ("Error : %s\n", error->message); + g_error_free(error); + return NULL; + } + + g_signal_connect (modem->proxy, + "property_changed", + G_CALLBACK (on_modem_property_changed), + modem); + + return modem->proxy; + +} + + +/* + * Force Update the modem list + * Call <method>GetModems + * Returns: 0 - success or other errors + */ +int modem_list_update() { + LOGD("\n"); + + GError *error = NULL; + GVariant *result = NULL; + GSList *newDeviceList = NULL; + + + result = g_dbus_connection_call_sync(OfonoManager.system_conn, + OFONO_SERVICE, OFONO_MANAGER_PATH, OFONO_MANAGER_INTERFACE, + "GetModems", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (error) { + LOGW ("Error : %s\n", error->message); + g_error_free(error); + return -1; + } + + GVariant *ArrayValue = NULL; + GVariantIter *ArrayValueIter; + GVariant *Value = NULL; + + g_variant_get(result, "(*)", &ArrayValue); + + g_variant_get(ArrayValue, "a*", &ArrayValueIter); + while (g_variant_iter_loop(ArrayValueIter, "*", &Value)) { + + GVariantIter dbus_object_iter; + GVariant *dbusObjecPath; + GVariant *dbusObjecProperties; + + gchar *pObjecPath = NULL; + struct ofono_modem *modem = NULL; + + g_variant_iter_init(&dbus_object_iter, Value); + + //1st : DBus Object Path + dbusObjecPath = g_variant_iter_next_value(&dbus_object_iter); + + g_variant_get(dbusObjecPath, "o", &pObjecPath); + + LOGD("object path %s\n",pObjecPath); + + //ObjectPath is /hfp/org/bluez/hci0/dev_xx_xx_xx_xx_xx_xx + if ((41 != strlen(pObjecPath)) + || (NULL == g_strstr_len(pObjecPath, 23, + "/hfp"ADAPTER_PATH"/dev"))) { + g_free(pObjecPath); + pObjecPath = NULL; + g_variant_unref(dbusObjecPath); + continue; + } + + modem = g_malloc0(sizeof(struct ofono_modem)); + modem->path = g_strdup(pObjecPath); + g_free(pObjecPath); + pObjecPath = NULL; + g_variant_unref(dbusObjecPath); + + LOGD("Found new device%s\n",modem->path ); + + modem->proxy = modem_create_proxy(modem); + + //2nd : DBus Interfaces under Object Path + dbusObjecProperties = g_variant_iter_next_value(&dbus_object_iter); + + GVariant *property_value = NULL; + g_variant_lookup(dbusObjecProperties, "Powered", + "*", &property_value); + + if (property_value) + { + gboolean bValue = FALSE; + g_variant_get(property_value, "b", &bValue ); + modem->powered = bValue; + + g_variant_unref (property_value); + } + + g_variant_unref(dbusObjecProperties); + + //Save device to newDeviceList + newDeviceList = g_slist_prepend(newDeviceList, modem); + + } + + g_variant_iter_free(ArrayValueIter); + g_variant_unref(ArrayValue); + + g_variant_unref(result); + + + //Force update device, so clean first + modem_list_lock(); + + modem_list_cleanup(); + + OfonoManager.modem = newDeviceList; + + modem_list_unlock(); + + return 0; +} + + +/* + * init cli dbus connection + * Returns: 0 - success or other errors + */ +static int ofono_manager_connect_to_dbus(void) +{ + GError *error = NULL; + + OfonoManager.system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (error) + { + LOGE("errr:%s",error->message); + g_error_free(error); + + return -1; + } + + OfonoManager.proxy = ofono_org_ofono_manager_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, + OFONO_MANAGER_PATH, NULL, &error); + + if (error) { + LOGW("Create Ofono manager client fail\n"); + LOGW("Error:%s\n", error->message); + g_error_free(error); + + g_object_unref(OfonoManager.system_conn); + return -1; + } + + return 0; +} + +/* + * register callback function + * Returns: 0 - success or other errors + */ +static int ofono_manager_register_callback(void) +{ + + g_signal_connect (OfonoManager.proxy, + "modem-added", + G_CALLBACK (on_modem_added), + NULL); + + g_signal_connect (OfonoManager.proxy, + "modem-removed", + G_CALLBACK (on_modem_removed), + NULL); + + return 0; +} + +/* + * init dbus and register callback + */ +static int ofono_mamager_init(void) +{ + int ret = 0; + LOGD("\n"); + ret = ofono_manager_connect_to_dbus(); + + if (0 != ret){ + LOGW("init fail\n"); + return -1; + } + + g_mutex_init(&(OfonoManager.m)); + + ofono_manager_register_callback(); + modem_list_update(); + + OfonoManager.inited = TRUE; + + return 0; +} + +#ifdef AGENT_THREAD +/* + * Ofono Manager Thread + * register callback function and create a new GMainLoop structure + */ +static void *ofono_event_loop_thread() +{ + int ret = 0; + + OfonoLoop = g_main_loop_new(NULL, FALSE);; + + ret = ofono_mamager_init(); + + if (0 == ret){ + LOGD("g_main_loop_run\n"); + g_main_loop_run(OfonoLoop); + + } + + g_main_loop_unref(OfonoLoop); + LOGD("exit...\n"); +} +#endif + +/* --- PUBLIC FUNCTIONS --- */ + +/* + * Get the ofono modem "Powered" property + */ +gboolean getOfonoModemPoweredByPath (gchar* path) +{ + struct ofono_modem *modem = NULL; + gboolean powered = FALSE; + + modem_list_lock(); + + modem = modem_list_find_modem_by_path(path); + + if (modem){ + powered = modem->powered; + } + + LOGD("get modem %p by path:%s,%d\n", modem, path, powered); + + modem_list_unlock(); + + return powered; +} + + +/* + * Init the ofono manager + */ +int OfonoManagerInit(void) +{ + int ret = 0; + + LOGD("\n"); + + if (TRUE == OfonoManager.inited) + { + LOGW("Ofono Manager is already inited\n"); + return -1; + + } + +#ifdef OFONO_THREAD + pthread_t thread_id; + + pthread_create(&thread_id, NULL, ofono_event_loop_thread, NULL); + pthread_setname_np(thread_id, "ofono_manager"); + +#else + + ret = ofono_mamager_init(); + +#endif + + return ret; +} + +/* + * Quit the ofono manager + */ +int OfonoManagerQuit(void) +{ + LOGD("\n"); + + if (TRUE != OfonoManager.inited) + { + LOGW("Ofono Manager is not inited\n"); + return -1; + + } +#ifdef OFONO_THREAD + g_main_loop_quit(OfonoLoop); +#endif + + memset(&ofono_RegisterCallback, 0, sizeof(Ofono_RegisterCallback_t)); + + g_object_unref(OfonoManager.proxy); + + modem_list_lock(); + modem_list_cleanup(); + modem_list_unlock(); + + g_mutex_clear (&(OfonoManager.m)); + + g_object_unref(OfonoManager.system_conn); + + OfonoManager.inited = FALSE; + + return 0; + +} + +/* + * Register ofono Callback function + */ +void OfonoModemAPIRegister(const Ofono_RegisterCallback_t* pstRegisterCallback) +{ + LOGD("\n"); + + if (NULL != pstRegisterCallback) + { + if (NULL != pstRegisterCallback->modem_added) + { + ofono_RegisterCallback.modem_added = + pstRegisterCallback->modem_added; + } + + if (NULL != pstRegisterCallback->modem_removed) + { + ofono_RegisterCallback.modem_removed = + pstRegisterCallback->modem_removed; + } + + if (NULL != pstRegisterCallback->modem_properties_changed) + { + ofono_RegisterCallback.modem_properties_changed = + pstRegisterCallback->modem_properties_changed; + } + + } + +} + |