[Adapt] Implement Device Service Search(SDP) & event handling 94/79494/1
authorAnupam Roy <anupam.r@samsung.com>
Mon, 11 Jul 2016 12:45:18 +0000 (08:45 -0400)
committerAnupam Roy <anupam.r@samsung.com>
Mon, 11 Jul 2016 12:46:01 +0000 (08:46 -0400)
This patch implements Service Search API
in bt-service, OAL and Bluetooth HAL layer.

In order to maintain consistency with other open source stack,
after services are received as single property from OAL, rest of
the device properties are also fetched from stack and one single
event is sent to BT frwk containing all services along with
other bonded device informations.

Change-Id: I7f196d74b964f40b87d32635a5a00e271be4070f
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
14 files changed:
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.c
bt-oal/bluez_hal/src/bt-hal-device-dbus-handler.c
bt-oal/bluez_hal/src/bt-hal-device-dbus-handler.h
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/common/oal-common.c
bt-oal/include/oal-device-mgr.h
bt-oal/oal-device-mgr.c
bt-service-adaptation/services/bt-request-handler.c
bt-service-adaptation/services/bt-service-common.c
bt-service-adaptation/services/bt-service-event-receiver.c
bt-service-adaptation/services/device/bt-service-core-device.c
bt-service-adaptation/services/include/bt-service-common.h
bt-service-adaptation/services/include/bt-service-core-device.h

index e0a9ebb..875c0bf 100644 (file)
@@ -148,12 +148,15 @@ static int set_remote_device_property(bt_bdaddr_t *remote_addr,
 static int get_remote_service_record(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid)
 {
        return BT_STATUS_UNSUPPORTED;
-
 }
 
 static int get_remote_services(bt_bdaddr_t *remote_addr)
 {
-       return BT_STATUS_UNSUPPORTED;
+       if (!remote_addr) {
+               ERR("Invalid param");
+               return BT_STATUS_PARM_INVALID;
+       }
+       return _bt_hal_dbus_get_remote_device_services(remote_addr);
 }
 
 static int start_discovery(void)
index 201dc4a..a20d8a1 100644 (file)
@@ -28,6 +28,7 @@
 #include <termios.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <arpa/inet.h>
 
 #include <dlog.h>
 #include <dbus/dbus-glib-lowlevel.h>
@@ -380,29 +381,29 @@ void _bt_convert_device_path_to_address(const char *device_path,
 }
 
 void _bt_convert_uuid_string_to_type(unsigned char *uuid,
-               const char *device_uuid)
+                const char *device_uuid)
 {
-       int i;
-       int k = 0;
-       uint8_t temp[2];
-       uint8_t temp1[1];
+       uint32_t uuid0, uuid4;
+       uint16_t uuid1, uuid2, uuid3, uuid5;
 
-       if (uuid == NULL || device_uuid == NULL)
-               return;
-       for (i = 0; i < 36; ) {
-               if (device_uuid[i] != '\0') {
-                       if (device_uuid[i] == '-') {
-                               i = i+1;
-                               continue;
-                       }
-                       temp[0] = device_uuid[i];
-                       temp[1] = device_uuid[i+ 1];
-                       sscanf((char*)temp, "%hhx", temp1);  //hexadecimal scanf format for uint8_t
-                       uuid[k] = temp1[0];
-                       i = i + 2;
-                       k++;
-               }
-       }
+       sscanf(device_uuid, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
+                       &uuid0, &uuid1, &uuid2, &uuid3, &uuid4, &uuid5);
+
+       uuid0 = htonl(uuid0);
+       uuid1 = htons(uuid1);
+       uuid2 = htons(uuid2);
+       uuid3 = htons(uuid3);
+       uuid4 = htonl(uuid4);
+       uuid5 = htons(uuid5);
+
+       memcpy(&(uuid[0]), &uuid0, 4);
+       memcpy(&(uuid[4]), &uuid1, 2);
+       memcpy(&(uuid[6]), &uuid2, 2);
+       memcpy(&(uuid[8]), &uuid3, 2);
+       memcpy(&(uuid[10]), &uuid4, 4);
+       memcpy(&(uuid[14]), &uuid5, 2);
+
+       return;
 }
 
 void _bt_convert_addr_string_to_type(unsigned char *addr,
index fd1a486..40684bb 100644 (file)
@@ -55,6 +55,11 @@ static void __bt_hal_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res, gpoint
 
 static void __bt_hal_unbond_device_cb(GDBusProxy *proxy, GAsyncResult *res,
                                         gpointer user_data);
+static void __bt_hal_device_service_search_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                        gpointer user_data);
+int __bt_hal_dbus_enquire_remote_device_services(char *address);
+
+static void __bt_device_parse_services(GVariant *result);
 
 int _bt_hal_device_create_bond(const bt_bdaddr_t *bd_addr, unsigned short transport)
 {
@@ -304,6 +309,265 @@ int _bt_hal_device_ssp_reply(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t varian
        return BT_STATUS_SUCCESS;
 }
 
+int _bt_hal_dbus_get_remote_device_services(const bt_bdaddr_t *remote_addr)
+{
+       char *device_path = NULL;
+       GDBusProxy *device_proxy = NULL;
+       GDBusConnection *conn;
+       GDBusProxy *adapter_proxy;
+       //char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
+       char *address = NULL;
+       int result = BT_STATUS_SUCCESS;
+       DBG("+");
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+
+       _bt_convert_addr_type_to_string(address, remote_addr->address);
+
+       if (remote_addr == NULL) {
+               result = BT_STATUS_PARM_INVALID;
+               goto fail;
+       }
+
+       adapter_proxy = _bt_get_adapter_proxy();
+       if (adapter_proxy == NULL) {
+               result = BT_STATUS_FAIL;
+               goto fail;
+       }
+
+       conn = _bt_get_system_gconn();
+       if (conn == NULL) {
+               ERR("Could not get System DBUS Connection");
+               result = BT_STATUS_FAIL;
+               goto fail;
+       }
+
+       device_path = _bt_get_device_object_path(address);
+
+       if (device_path == NULL) {
+               ERR("Remote device is not paired..can not perform SDP!!!");
+               result = BT_STATUS_FAIL;
+               goto fail;
+       }
+
+       device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME,
+                       device_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
+       g_free(device_path);
+
+       if (device_proxy == NULL) {
+               ERR("Could not create Device Proxy");
+               result = BT_STATUS_FAIL;
+               goto fail;
+       }
+
+
+       g_dbus_proxy_call(device_proxy, "DiscoverServices",
+                       g_variant_new("(s)", ""),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       BT_HAL_MAX_DBUS_TIMEOUT,
+                       NULL,
+                       (GAsyncReadyCallback)__bt_hal_device_service_search_cb,
+                       address);
+
+       return BT_STATUS_SUCCESS;
+
+fail:
+       g_free(address);
+       return result;
+}
+
+static void __bt_hal_device_service_search_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                        gpointer user_data)
+{
+       /* Buffer and propety count management */
+       uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
+       struct hal_ev_remote_device_props *ev = (void*) buf;;
+       size_t size = 0;
+
+       GError *err = NULL;
+       int result = BT_HAL_ERROR_NONE;
+       char *address = (char*) user_data;
+       DBG("+");
+
+       g_dbus_proxy_call_finish(proxy, res, &err);
+
+       g_object_unref(proxy);
+
+       /* Check event pointer */
+       if (!event_cb)
+                event_cb = _bt_hal_get_stack_message_handler();
+        if (!event_cb) {
+                ERR("event_cb is NULL, can not send Service search results to HAL User");
+                goto cleanup;
+        }
+
+       if (err != NULL) {
+               g_dbus_error_strip_remote_error(err);
+               ERR("Error occured in Proxy call [%s]\n", err->message);
+
+               if (g_strrstr("Operation canceled", err->message)) {
+                       result = BT_HAL_ERROR_CANCEL_BY_USER;
+               } else if (g_strrstr("In Progress", err->message)) {
+                       result = BT_HAL_ERROR_IN_PROGRESS;
+               } else if (g_strrstr("Host is down", err->message)) {
+                       result = BT_HAL_ERROR_HOST_DOWN;
+               } else {
+                       result = BT_HAL_ERROR_CONNECTION_ERROR;
+               }
+
+               if (result == BT_HAL_ERROR_HOST_DOWN ||
+                               result == BT_HAL_ERROR_CONNECTION_ERROR) {
+                       ERR("Service search has failed due to Host Down or connection error, attempt to find properties");
+                       if (__bt_hal_dbus_enquire_remote_device_services(address) == BT_STATUS_SUCCESS)
+                               goto cleanup;
+
+               }
+               goto done;
+       }
+
+       DBG("SDP is successful..lets fetch the device properties..");
+       if (__bt_hal_dbus_enquire_remote_device_services(address) == BT_STATUS_SUCCESS)
+               goto cleanup;
+done:
+       ev->status = BT_STATUS_FAIL;
+       ev->num_props = 0;
+       size = sizeof(*ev);
+       ERR("Error: Failed to get Remote device properties after SDP,"
+                       " Num Prop [%d] total size [%d]",ev->num_props, size);
+       event_cb(HAL_EV_REMOTE_DEVICE_PROPS, (void*) buf, size);
+
+cleanup:
+       if (err)
+               g_error_free(err);
+       g_free(address);
+}
+
+static void __bt_device_parse_services(GVariant *result)
+{
+       /* Buffer and propety count management */
+       uint8_t buf[BT_HAL_MAX_PROPERTY_BUF_SIZE];
+       struct hal_ev_remote_device_props *ev = (void*) buf;;
+       size_t size = 0;
+
+       GVariantIter *property_iter;
+
+       const gchar *key;
+       GVariant *value;
+       const gchar *address = NULL;
+
+       memset(buf, 0, sizeof(buf));
+       size = sizeof(*ev);
+       ev->num_props = 0;
+       ev->status = BT_STATUS_SUCCESS;
+
+       g_variant_get(result, "(a{sv})", &property_iter);
+       while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
+               if (!g_strcmp0(key, "Address")) {
+                       address = g_variant_get_string(value, NULL);
+                       DBG("Address [%s]", address);
+                       _bt_convert_addr_string_to_type(ev->bdaddr, address);
+               } else if (!g_strcmp0(key, "UUIDs")) {
+                       char **uuid_value;
+                       int uuid_count = 0;
+                       gsize size1 = 0;
+                       int i =0;
+                       size1 = g_variant_get_size(value);
+                       int num_props_tmp = ev->num_props;
+                       if (size1 > 0) {
+                               uuid_value = (char **)g_variant_get_strv(value, &size1);
+                               for (i = 0; uuid_value[i] != NULL; i++)
+                                       uuid_count++;
+                               /* UUID collection */
+                               uint8_t uuids[BT_HAL_STACK_UUID_SIZE * uuid_count];
+                               for (i = 0; uuid_value[i] != NULL; i++) {
+                                       char *uuid_str = NULL;
+                                       uint8_t uuid[BT_HAL_STACK_UUID_SIZE];
+                                       memset(uuid, 0x00, BT_HAL_STACK_UUID_SIZE);
+                                       uuid_str = g_strdup(uuid_value[i]);
+                                       DBG("UUID string [%s]\n", uuid_str);
+                                       _bt_convert_uuid_string_to_type(uuid, uuid_str);
+                                       memcpy(uuids + i * BT_HAL_STACK_UUID_SIZE, uuid, BT_HAL_STACK_UUID_SIZE);
+                               }
+                               size += __bt_insert_hal_properties(buf + size, HAL_PROP_DEVICE_UUIDS,
+                                               (BT_HAL_STACK_UUID_SIZE * uuid_count), uuids);
+                               ev->num_props = num_props_tmp + 1;
+                               g_free(uuid_value);
+                       }
+               } else {
+                       ERR("Unhandled Property:[%s]", key);
+               }
+       }
+
+       DBG("Send Remote Device services to HAL,"
+                       " Num Prop [%d] total size [%d]",ev->num_props, size);
+       event_cb(HAL_EV_REMOTE_DEVICE_PROPS, (void*) buf, size);
+
+       g_variant_unref(result);
+}
+
+int __bt_hal_dbus_enquire_remote_device_services(char *address)
+{
+       char *device_path = NULL;
+       GError *error = NULL;
+       GDBusProxy *device_proxy;
+       GDBusConnection *conn;
+       GVariant *result;
+
+       device_path = _bt_get_device_object_path(address);
+       if (!device_path) {
+               ERR("Device not paired");
+               return BT_STATUS_FAIL;
+       }
+
+       conn = _bt_get_system_gconn();
+       if (!conn) {
+               ERR("_bt_get_system_gconn failed");
+               return BT_STATUS_FAIL;
+       }
+
+       device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL,
+                       BT_HAL_BLUEZ_NAME,
+                       device_path,
+                       BT_HAL_PROPERTIES_INTERFACE,
+                       NULL, NULL);
+
+       if (!device_proxy) {
+               ERR("Error creating device_proxy");
+               g_free(device_path);
+               return BT_STATUS_FAIL;
+       }
+
+       result = g_dbus_proxy_call_sync(device_proxy,
+                       "GetAll",
+                       g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1,
+                       NULL,
+                       &error);
+
+       if (!result) {
+               ERR("Error occured in Proxy call");
+               if (error != NULL) {
+                       ERR("Error occured in Proxy call (Error: %s)", error->message);
+                       g_clear_error(&error);
+               }
+               g_object_unref(device_proxy);
+               g_free(device_path);
+               return BT_STATUS_FAIL;
+       }
+
+       g_object_unref(device_proxy);
+       g_free(device_path);
+
+       /* Fetch Device Services and send to HAL User */
+       __bt_device_parse_services(result);
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
 static void __bt_hal_bond_device_cb(GDBusProxy *proxy, GAsyncResult *res,
                                         gpointer user_data)
 {
index 880e150..be1eef4 100644 (file)
@@ -52,6 +52,9 @@ int _bt_hal_device_legacy_pin_reply(const bt_bdaddr_t *bd_addr,
 
 int _bt_hal_device_ssp_reply(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
                uint8_t accept, uint32_t passkey);
+
+int _bt_hal_dbus_get_remote_device_services(const bt_bdaddr_t *remote_addr);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index c3ddc87..f4cbd6e 100644 (file)
@@ -283,6 +283,7 @@ static void __bt_hal_adapter_property_changed_event(GVariant *msg)
                                        DBG("##UUID string [%s]\n", uuid_str);
                                        _bt_convert_uuid_string_to_type(uuid, uuid_str);
                                        memcpy(uuids+i*BT_HAL_STACK_UUID_SIZE, uuid, BT_HAL_STACK_UUID_SIZE);
+                                       g_free(uuid_str);
                                }
                                size += __bt_insert_hal_properties(buf + size, HAL_PROP_ADAPTER_UUIDS,
                                                (BT_HAL_STACK_UUID_SIZE * uuid_count),
@@ -1066,7 +1067,9 @@ static void __bt_hal_device_properties_lookup(GVariant *result, char *address)
                {
                        /* UUID collection */
                        int i;
+#ifdef __TEST_
                        int z;
+#endif
                        int num_props_tmp = ev->num_props;
 
                        uint8_t uuids[BT_HAL_STACK_UUID_SIZE * uuid_count];
@@ -1082,9 +1085,10 @@ static void __bt_hal_device_properties_lookup(GVariant *result, char *address)
                                DBG("UUID string [%s]\n", uuid_str);
 
                                _bt_convert_uuid_string_to_type(uuid, uuid_str);
-
+#ifdef __TEST_
                                for(z=0; z < 16; z++)
                                        DBG("[0x%x]", uuid[z]);
+#endif
 
                                memcpy(uuids+i*BT_HAL_STACK_UUID_SIZE, uuid, BT_HAL_STACK_UUID_SIZE);
                                g_free(uuid_str);
index 1b79c8b..ba8b077 100755 (executable)
@@ -105,6 +105,7 @@ void parse_device_properties(int num_properties, bt_property_t *properties,
                }
                case BT_PROPERTY_UUIDS: {
                        uuids  = (service_uuid_t *)properties[i].val;
+                       BT_DBG("Length of properties from HAL [%d]", properties[i].len);
                        uuid_count = properties[i].len/sizeof(bt_uuid_t);
                        table_len += uuid_count;
                        for(; tmp_uuid_cnt < table_len; tmp_uuid_cnt++) {
index 193a631..de29e28 100755 (executable)
@@ -121,6 +121,34 @@ oal_status_t device_stop_bond(bt_address_t * addr);
 oal_status_t device_destroy_bond(bt_address_t * addr);
 
 /**
+ * @brief Request services supported by remote device
+ *
+ * @details List of services in form UUIDs will be provided in event data
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS  Successful
+ *
+ * @pre Adapter must be enabled with adapter_enable() followed by OAL_EVENT_ADAPTER_ENABLED
+ *
+ * @see  OAL_EVENT_DEVICE_SERVICES
+ * @see  event_dev_services_t
+ */
+oal_status_t device_query_services(bt_address_t * addr);
+
+/**
+ * @brief Cancel already in-progress SDP procedure
+ *
+ * @details Based on current progress different events can be recieved.
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS  Successful
+ *
+ * @pre SDP must be in progress by calling device_query_services()
+ *
+ */
+oal_status_t device_stop_query_sevices(bt_address_t * addr);
+
+/**
  * @brief Accept PIN request as part of Bonding procedure
  *
  * @details Positive response to OAL_EVENT_DEVICE_PIN_REQUEST
index 31fb831..6d8bee0 100755 (executable)
@@ -63,6 +63,37 @@ oal_status_t device_query_attributes(bt_address_t *addr)
        return OAL_STATUS_SUCCESS;
 }
 
+oal_status_t device_query_services(bt_address_t * addr)
+{
+       int res;
+       bdstr_t bdstr;
+
+       CHECK_OAL_INITIALIZED();
+
+       OAL_CHECK_PARAMETER(addr, return);
+
+       API_TRACE("[%s]", bdt_bd2str(addr, &bdstr));
+
+       res = blued_api->get_remote_services((bt_bdaddr_t *)addr);
+       if (res != BT_STATUS_SUCCESS) {
+               BT_ERR("get_remote_services error: [%s]", status2string(res));
+               return convert_to_oal_status(res);
+       }
+
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t device_stop_query_sevices(bt_address_t * addr)
+{
+       CHECK_OAL_INITIALIZED();
+
+       OAL_CHECK_PARAMETER(addr, return);
+
+       API_TRACE("Stop SDP search");
+       /* Currently no HAL Interface for Stopping Service Search */
+       return BT_STATUS_UNSUPPORTED;
+}
+
 oal_status_t device_set_alias(bt_address_t * addr, char * alias)
 {
        int res;
@@ -318,11 +349,13 @@ void cb_device_properties(bt_status_t status, bt_bdaddr_t *bd_addr,
                case BT_PROPERTY_UUIDS: {
                        event_dev_services_t *services_info;
                        bt_uuid_t *uuids = (bt_uuid_t *) properties[0].val;
+                       BT_INFO("Properties len [%d] event structure size [%d]", properties[0].len, sizeof(event_dev_services_t));
 
                        services_info = g_malloc(sizeof(event_dev_services_t) + properties[0].len);
                        services_info->address = dev_info->address;
                        memcpy(services_info->service_list, uuids, properties[0].len);
                        services_info->num = properties[0].len/sizeof(bt_uuid_t);
+                       BT_INFO("Number of UUID [%d]", services_info->num);
                        event = OAL_EVENT_DEVICE_SERVICES;
                        event_data = services_info;
                        size = sizeof(event_dev_services_t) + properties[0].len;
index f2ebc8b..022ae2f 100644 (file)
@@ -577,6 +577,28 @@ int __bt_bluez_request(int function_name,
                       result = _bt_cancel_bonding();
                       break;
        }
+       case BT_SEARCH_SERVICE: {
+               bluetooth_device_address_t address = { {0} };
+               __bt_service_get_parameters(in_param1,
+                               &address, sizeof(bluetooth_device_address_t));
+               result = _bt_search_device(&address);
+               /* Save invocation */
+               if (result == BLUETOOTH_ERROR_NONE) {
+                       char * addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
+                       _bt_convert_addr_type_to_string(addr, address.addr);
+                       BT_DBG("BT Device Service Search Request scheduled successfully! save invocation context");
+                       sender = (char*)g_dbus_method_invocation_get_sender(context);
+                       _bt_save_invocation_context(context, result, sender,
+                                       function_name, (gpointer)addr);
+               } else
+                       g_array_append_vals(*out_param1, &address,
+                                       sizeof(bluetooth_device_address_t));
+               break;
+       }
+       case BT_CANCEL_SEARCH_SERVICE: {
+              result = _bt_cancel_search_device();
+                      break;
+       }
        case BT_PASSKEY_REPLY: {
                const char *passkey = NULL;
                gboolean authentication_reply = FALSE;
index 703e3ca..27bf117 100755 (executable)
@@ -428,6 +428,15 @@ void _bt_convert_addr_type_to_string(char *address,
                        addr[3], addr[4], addr[5]);
 }
 
+gboolean _bt_compare_adddress(const bluetooth_device_address_t *addr1,
+               const bluetooth_device_address_t *addr2)
+{
+       if (memcmp(&addr1->addr, &addr2->addr, 6) == 0)
+               return TRUE;
+       else
+               return FALSE;
+}
+
 void _bt_print_device_address_t(const bluetooth_device_address_t *addr)
 {
        BT_INFO("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
@@ -863,7 +872,7 @@ void _bt_copy_remote_dev(bt_remote_dev_info_t * dev_info, remote_device_t * oal_
        for (i=0; i < dev_info->uuid_count; i++) {
                dev_info->uuids[i] = g_malloc0(BLUETOOTH_UUID_STRING_MAX);
                _bt_uuid_to_string((service_uuid_t *)&oal_device->uuid[i].uuid, dev_info->uuids[i]);
-               BT_DBG("UUID size=%d value=%s", sizeof(dev_info->uuids[i]), dev_info->uuids[i]);
+               BT_DBG("[%s]", dev_info->uuids[i]);
        }
 
        BT_INFO("-");
@@ -889,7 +898,6 @@ static void __bt_get_service_list(bt_remote_dev_info_t *info, bluetooth_device_i
        dev->service_index = 0;
        BT_DBG("Total UUID count [%d]", info->uuid_count);
        for (i = 0; i < info->uuid_count; i++) {
-               BT_DBG("UUID count [%d]", i);
                g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX);
 
                parts = g_strsplit(uuids[i], "-", -1);
index 5f107ab..7d68db9 100644 (file)
@@ -113,6 +113,7 @@ void _bt_service_oal_event_receiver(int event_type, gpointer event_data, gsize l
        case OAL_EVENT_DEVICE_PASSKEY_CONFIRMATION_REQUEST:
        case OAL_EVENT_DEVICE_PASSKEY_DISPLAY:
        case OAL_EVENT_DEVICE_SSP_CONSENT_REQUEST:
+       case OAL_EVENT_DEVICE_SERVICES:
                if (device_cb)
                        device_cb(event_type, event_data);
                break;
index f8d8df8..2be2dff 100644 (file)
@@ -62,6 +62,15 @@ typedef struct {
         bt_remote_dev_info_t *dev_info;
 } bt_bond_data_t;
 
+/* Searching Info structure */
+typedef struct {
+        int result;
+        char *addr;
+        gboolean is_cancelled_by_user;
+        bluetooth_device_address_t *dev_addr;
+        bt_remote_dev_info_t *dev_info;
+} bt_service_search_info_data_t;
+
 /* Pairing Info structure */
 typedef struct {
         char *addr;
@@ -73,7 +82,7 @@ typedef struct {
 bt_bond_data_t *trigger_bond_info;
 bt_bond_data_t *trigger_unbond_info;
 bt_pairing_data_t *trigger_pairing_info;
-
+bt_service_search_info_data_t *service_search_info;
 
 typedef enum {
   BT_DEVICE_BOND_STATE_NONE,
@@ -102,6 +111,7 @@ static void __bt_device_remote_device_found_callback(gpointer event_data, gboole
 
 static int __bt_device_handle_bond_state(void);
 static void __bt_free_bond_info(uint8_t type);
+static void __bt_free_service_search_info(bt_service_search_info_data_t **p_info);
 static void __bt_device_handle_bond_completion_event(bt_address_t *bd_addr);
 static void __bt_device_handle_bond_removal_event(bt_address_t *bd_addr);
 static void __bt_device_handle_bond_failed_event(event_dev_bond_failed_t* bond_fail_event);
@@ -116,6 +126,9 @@ static void __bt_device_ssp_passkey_display_callback(event_dev_passkey_t *dev_in
 static void __bt_device_ssp_passkey_confirmation_callback(event_dev_passkey_t *dev_info);
 static void __bt_device_ssp_passkey_entry_callback(remote_device_t* dev_info);
 
+static void __bt_device_services_callback(event_dev_services_t* uuid_list);
+static void __bt_handle_ongoing_device_service_search(bt_remote_dev_info_t *remote_dev_info);
+
 void _bt_device_state_handle_callback_set_request(void)
 {
        _bt_service_register_event_handler_callback(
@@ -139,6 +152,7 @@ void __bt_device_handle_pending_requests(int result, int service_function,
 
                switch (service_function) {
                case BT_BOND_DEVICE:
+               case BT_SEARCH_SERVICE:
                case BT_UNBOND_DEVICE: {
                        char *address = (char *)user_data;
                        if (strncmp((char*)req_info->user_data, address, BT_ADDRESS_STRING_SIZE)) {
@@ -298,7 +312,9 @@ static void __bt_device_remote_properties_callback(event_dev_properties_t *oal_d
        }
 
        _bt_copy_remote_device(rem_info, &dev_info);
+#ifdef __TEST_
        _bt_service_print_dev_info(&dev_info);
+#endif
 
        /* Check if app has requested for device info for already bonded devices */
        __bt_device_handle_pending_requests(result, BT_GET_BONDED_DEVICES,
@@ -311,6 +327,121 @@ static void __bt_device_remote_properties_callback(event_dev_properties_t *oal_d
                __bt_handle_ongoing_bond(trigger_bond_info->dev_info);
        }
 
+       /* Handle SDP Device properties update */
+       if (service_search_info && service_search_info->dev_info) {
+               if (!strcmp(service_search_info->addr, rem_info->address)) {
+                       BT_DBG("Properties received and SDP request pending, fill device properties and send event");
+                       service_search_info->dev_info->class = rem_info->class;
+                       service_search_info->dev_info->paired = rem_info->paired;
+                       service_search_info->dev_info->connected = rem_info->connected;
+                       service_search_info->dev_info->rssi = rem_info->rssi;
+                       service_search_info->dev_info->addr_type = rem_info->addr_type;
+                       service_search_info->dev_info->trust = rem_info->trust;
+
+                       /* TODO*/
+                       service_search_info->dev_info->manufacturer_data = NULL;
+                       service_search_info->dev_info->manufacturer_data_len = 0;
+
+                       __bt_handle_ongoing_device_service_search(service_search_info->dev_info);
+               }
+       }
+
+       BT_DBG("-");
+}
+
+static void __bt_handle_ongoing_device_service_search(bt_remote_dev_info_t *remote_dev_info)
+{
+       GVariant *param = NULL;
+       GVariant *uuids = NULL;
+       GVariantBuilder *builder = NULL;
+       GVariant *manufacturer_data;
+       int i = 0;
+       BT_INFO("Send Service Search request event");
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i=0; i < remote_dev_info->uuid_count; i++) {
+               g_variant_builder_add(builder, "s",
+                               remote_dev_info->uuids[i]);
+       }
+       uuids = g_variant_new("as", builder);
+       g_variant_builder_unref(builder);
+       manufacturer_data = g_variant_new_from_data((const GVariantType *)"ay",
+                       remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len,
+                       TRUE, NULL, NULL);
+
+       param = g_variant_new("(isunsbub@asn@ay)",
+                       BLUETOOTH_ERROR_NONE,
+                       remote_dev_info->address,
+                       remote_dev_info->class,
+                       remote_dev_info->rssi,
+                       remote_dev_info->name,
+                       remote_dev_info->paired,
+                       remote_dev_info->connected,
+                       remote_dev_info->trust,
+                       uuids,
+                       remote_dev_info->manufacturer_data_len,
+                       manufacturer_data);
+       /* Send the event to application */
+       _bt_send_event(BT_ADAPTER_EVENT,
+                       BLUETOOTH_EVENT_SERVICE_SEARCHED,
+                       param);
+
+       __bt_free_service_search_info(&service_search_info);
+       BT_DBG("-");
+}
+
+static void __bt_device_services_callback(event_dev_services_t* uuid_list)
+{
+       bt_remote_dev_info_t *rem_info = NULL;
+       int i;
+       BT_DBG("+");
+
+       if (service_search_info == NULL) {
+               /* Send reply */
+               BT_DBG("searching_info == NULL");
+               return;
+       }
+
+       if (_bt_compare_adddress(service_search_info->dev_addr,
+                               (bluetooth_device_address_t *)&uuid_list->address) == FALSE) {
+               BT_DBG("This device is not queried");
+               return;
+       }
+
+       rem_info = g_malloc0(sizeof(bt_remote_dev_info_t));
+       memset(rem_info, 0x00, sizeof(bt_remote_dev_info_t));
+
+       rem_info->address = g_new0(char, BT_ADDRESS_STRING_SIZE);
+       _bt_convert_addr_type_to_string(rem_info->address, uuid_list->address.addr);
+
+       rem_info->uuid_count = uuid_list->num;
+
+       BT_INFO("Address [%s]", rem_info->address);
+       BT_INFO("Number of UUID's [%d]", rem_info->uuid_count);
+       if (rem_info->uuid_count > 0)
+               rem_info->uuids = g_new0(char *, rem_info->uuid_count);
+
+       /* Fill Remote Device Service List list */
+       for (i=0; i < rem_info->uuid_count; i++) {
+               rem_info->uuids[i] = g_malloc0(BLUETOOTH_UUID_STRING_MAX);
+               _bt_uuid_to_string((service_uuid_t *)&uuid_list->service_list[i].uuid, rem_info->uuids[i]);
+               BT_DBG("UUID value=%s", rem_info->uuids[i]);
+       }
+
+       BT_DBG("DBUS return");
+       __bt_device_handle_pending_requests(BLUETOOTH_ERROR_NONE, BT_SEARCH_SERVICE,
+                       service_search_info->addr, BT_ADDRESS_STRING_SIZE);
+
+       /* Save UUID List of remote devices */
+       service_search_info->dev_info = rem_info;
+
+       /* Query Other device properties */
+       if (_bt_device_get_bonded_device_info(service_search_info->dev_addr) == BLUETOOTH_ERROR_NONE) {
+               BT_DBG("Bonded device info query posted to stack successfully");
+       } else {
+               BT_DBG("Possibly internal stack error in bonded device info query, perform cleanup");
+               __bt_free_service_search_info(&service_search_info);
+       }
        BT_DBG("-");
 }
 
@@ -592,6 +723,11 @@ static void __bt_device_event_handler(int event_type, gpointer event_data)
                 __bt_device_ssp_consent_callback((remote_device_t*)event_data);
                break;
        }
+       case OAL_EVENT_DEVICE_SERVICES: {
+               BT_INFO("Remote Device Services Received");
+               __bt_device_services_callback((event_dev_services_t*)event_data);
+               break;
+       }
        default:
                BT_INFO("Unhandled event..");
        }
@@ -972,6 +1108,30 @@ static void __bt_free_bond_info(uint8_t type)
        }
 }
 
+static void __bt_free_service_search_info(bt_service_search_info_data_t **p_info)
+{
+       bt_service_search_info_data_t * info = *p_info;
+       if (info) {
+               if (info->addr) {
+                       g_free(info->addr);
+                       info->addr = NULL;
+               }
+
+               if (info->dev_addr) {
+                       g_free(info->dev_addr);
+                       info->dev_addr = NULL;
+               }
+
+               if (info->dev_info) {
+                       _bt_free_device_info(info->dev_info);
+                       info->dev_info = NULL;
+               }
+
+               g_free(info);
+       }
+       *p_info = NULL;
+}
+
 static int __bt_device_handle_bond_state(void)
 {
        BT_INFO("Current Bond state: %d", bt_device_bond_state);
@@ -1267,3 +1427,59 @@ void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair)
         ret_if (trigger_bond_info == NULL);
         trigger_bond_info->is_autopair = is_autopair;
 }
+
+int _bt_search_device(bluetooth_device_address_t *device_address)
+{
+       int result = OAL_STATUS_SUCCESS;
+       BT_DBG("+");
+
+       BT_CHECK_PARAMETER(device_address, return);
+
+       if (trigger_bond_info) {
+               BT_ERR("Bonding in progress");
+               return BLUETOOTH_ERROR_DEVICE_BUSY;
+       }
+
+       if (service_search_info) {
+               BT_ERR("Service searching in progress");
+               return BLUETOOTH_ERROR_DEVICE_BUSY;
+       }
+
+       /* allocate user data so that it can be retrieved in callback */
+       service_search_info = g_malloc0(sizeof(bt_service_search_info_data_t));
+       service_search_info->addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
+       service_search_info->dev_addr = g_memdup(device_address, sizeof(bluetooth_device_address_t));
+
+       _bt_convert_addr_type_to_string(service_search_info->addr,
+                       device_address->addr);
+
+       result = device_query_services((bt_address_t *)device_address);
+
+       if (result != OAL_STATUS_SUCCESS) {
+               BT_ERR("Device Service Search Failed..: %d", result);
+               __bt_free_service_search_info(&service_search_info);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_cancel_search_device(void)
+{
+       int ret = OAL_STATUS_SUCCESS;
+       retv_if(service_search_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
+
+       ret = device_stop_query_sevices((bt_address_t *)service_search_info->dev_addr);
+
+       if (ret != OAL_STATUS_SUCCESS) {
+               BT_ERR("SDP Cancel request failed [%d]", ret);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       __bt_device_handle_pending_requests(BLUETOOTH_ERROR_CANCEL_BY_USER, BT_SEARCH_SERVICE,
+                       service_search_info->addr, BT_ADDRESS_STRING_SIZE);
+
+       __bt_free_service_search_info(&service_search_info);
+
+       return BLUETOOTH_ERROR_NONE;
+       BT_DBG("-");
+}
index a0cd308..d059f3c 100755 (executable)
@@ -360,6 +360,9 @@ int _bt_byte_arr_cmp(const char *data1, const char *data2, int data_len);
 int _bt_byte_arr_cmp_with_mask(const char *data1, const char *data2,
                                const char *mask, int data_len);
 
+gboolean _bt_compare_adddress(const bluetooth_device_address_t *addr1,
+                const bluetooth_device_address_t *addr2);
+
 void _bt_print_device_address_t(const bluetooth_device_address_t *addr);
 
 void _bt_divide_device_class(bluetooth_device_class_t *device_class,
index 219f39b..d42b845 100755 (executable)
@@ -46,6 +46,10 @@ gboolean _bt_device_is_bonding(void);
 
 gboolean _bt_device_is_pairing(void);
 
+int _bt_cancel_search_device(void);
+
+int _bt_search_device(bluetooth_device_address_t *device_address);
+
 gboolean _bt_is_bonding_device_address(const char *address);
 
 void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair);