ble plugin: Implement basic operation 20/260520/2
authorCheoleun Moon <chleun.moon@samsung.com>
Mon, 28 Jun 2021 07:21:11 +0000 (16:21 +0900)
committercheoleun moon <chleun.moon@samsung.com>
Fri, 2 Jul 2021 02:45:54 +0000 (02:45 +0000)
Change-Id: I8dd59934cdd897172b0ef36100b670e2ed4f02f1
Signed-off-by: Cheoleun Moon <chleun.moon@samsung.com>
packaging/capi-network-vine.spec
plugins/ble/ble-plugin.cpp
src/include/vine-constants.h

index 462fbc3ca56274ca99fbdadf8716c8ac3977d20d..34cf7510f17028a5f4629f7b3d33e932fa1c9d91 100755 (executable)
@@ -3,7 +3,7 @@
 %bcond_without use_glib_event_loop
 Name:    capi-network-vine
 Summary: An service discovery framework
-Version: 1.0.10
+Version: 1.1.1
 Release: 0
 Group:   Network & Connectivity/API
 License: Apache-2.0
index 53db819c481eebab1c354ab5aa98cb56d1310862..97adf931fb4637ec77fc117360f4051106319836 100755 (executable)
@@ -15,7 +15,9 @@
  *
 */
 
+#include <glib.h>
 #include <string>
+#include <map>
 
 #include <bluetooth.h>
 #include <netinet/in.h>
 #include "ble-plugin.h"
 
 #define VINE_UUID "29AD"
+#define VINE_MANUFACTURER_ID 0x1111
+#define VINE_MAX_MANUFACTURER_DATA_LEN 31
 
 typedef struct {
        void *disc_handle;
+       char service_type[VINE_MAX_BLE_SERVICE_TYPE_LEN + 1];
        bt_advertiser_h adv;
+       bt_scan_filter_h filter;
 } vine_ble_s;
 
 static vine_disc_plugin_callbacks event_callbacks;
@@ -75,6 +81,7 @@ vine_disc_error ble_init(void **plugin_handle, void *disc_handle)
 
        handle->disc_handle = disc_handle;
        handle->adv = NULL;
+       handle->filter = NULL;
        *plugin_handle = handle;
 
        return VINE_DISC_ERROR_NONE;
@@ -97,6 +104,58 @@ static void __ble_advertising_state_changed_cb(int result, bt_advertiser_h adver
        VINE_LOGD("BLE advertising state is changed. result: %d, state: %d", result, adv_state);
 }
 
+static int __configure_advertiser(bt_advertiser_h adv,
+       const char *service_type, const char *service_name)
+{
+       int ret = bt_adapter_le_add_advertising_service_uuid(adv,
+                               BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, VINE_UUID);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_add_advertising_service_uuid() fails %d", ret);
+
+       // TODO: Determine which data should be set for service_data
+       // It should be set mandatorily?
+       // Or we don't have to set service_data if manufacturer data is set
+       char service_data[3] = {0x01, 0x02, 0x03};
+       // TODO: ALso set for BT_ADAPTER_LE_PACKET_ADVERTISING?
+       ret = bt_adapter_le_add_advertising_service_data(adv,
+                               BT_ADAPTER_LE_PACKET_SCAN_RESPONSE,
+                               VINE_UUID, service_data, sizeof(service_data));
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_add_advertising_service_data() fails %d", ret);
+
+       // TODO: Also set for BT_ADAPTER_LE_PACKET_ADVERTISING?
+       ret = bt_adapter_le_set_advertising_device_name(adv,
+                               BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_set_advertising_device_name() fails %d", ret);
+
+       ret = bt_adapter_le_set_advertising_connectable(adv, true);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_set_advertising_connectable() fails %d", ret);
+
+       ret = bt_adapter_le_set_advertising_mode(adv,
+                               BT_ADAPTER_LE_ADVERTISING_MODE_BALANCED);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_set_advertising_mode() fails %d", ret);
+
+       char manufacturer_data[VINE_MAX_MANUFACTURER_DATA_LEN + 1];
+       int manufacturer_len = strlen(service_type) + strlen(service_name) + 1;
+       RET_VAL_IF(manufacturer_len > 31, BT_ERROR_INVALID_PARAMETER,
+               "Too long service_type and service_name");
+
+       snprintf(manufacturer_data, VINE_MAX_MANUFACTURER_DATA_LEN + 1,
+               "%s.%s", service_type, service_name);
+
+       ret = bt_adapter_le_add_advertising_manufacturer_data(adv,
+               BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, VINE_MANUFACTURER_ID,
+               manufacturer_data, manufacturer_len);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_add_advertising_manufacturer_data() fails %d", ret);
+
+
+       return BT_ERROR_NONE;
+}
+
 vine_disc_error ble_publish(void *plugin_handle, const char *service_type,
                const char *service_name, int port, const map<string, string> &attributes,
                const char *iface_name)
@@ -104,62 +163,34 @@ vine_disc_error ble_publish(void *plugin_handle, const char *service_type,
        RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
        RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL");
        RET_VAL_IF(!service_name, VINE_DISC_ERROR_INVALID_PARAMETER, "service_name is NULL");
+       RET_VAL_IF(strlen(service_type) > VINE_MAX_BLE_SERVICE_TYPE_LEN, VINE_DISC_ERROR_INVALID_PARAMETER,
+               "too long service type");
+       RET_VAL_IF(strlen(service_name) > VINE_MAX_BLE_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER,
+               "too long service namr");
 
        vine_ble_s *ble_handle = (vine_ble_s *)plugin_handle;
        RET_VAL_IF(ble_handle->adv != NULL, VINE_DISC_ERROR_INVALID_PARAMETER, "Already published");
 
-       // TODO: Determine which data should be set for service_data
-       char service_data[3] = {0x01, 0x02, 0x03};
-
        int ret = bt_adapter_le_create_advertiser(&ble_handle->adv);
        RET_VAL_IF(ret != BT_ERROR_NONE, __convert_ble_error_to_vine_disc_error(ret),
                "bt_adapter_le_create_advertiser() fails");
 
-       ret = bt_adapter_le_add_advertising_service_uuid(ble_handle->adv,
-                               BT_ADAPTER_LE_PACKET_ADVERTISING, VINE_UUID);
-       if (ret != BT_ERROR_NONE) {
-               VINE_LOGE("bt_adapter_le_add_advertising_service_uuid() fails %d", ret);
-               goto error;
-       }
-
-       // TODO: ALso set for BT_ADAPTER_LE_PACKET_ADVERTISING?
-       ret = bt_adapter_le_add_advertising_service_data(ble_handle->adv,
-                               BT_ADAPTER_LE_PACKET_SCAN_RESPONSE,
-                               VINE_UUID, service_data, sizeof(service_data));
-       if (ret != BT_ERROR_NONE) {
-               VINE_LOGE("bt_adapter_le_add_advertising_service_data() fails %d", ret);
-               goto error;
-       }
-
-       // TODO: Also set for BT_ADAPTER_LE_PACKET_SCAN_RESPONSE?
-       ret = bt_adapter_le_set_advertising_device_name(ble_handle->adv,
-                               BT_ADAPTER_LE_PACKET_ADVERTISING, true);
-       if (ret != BT_ERROR_NONE) {
-               VINE_LOGE("bt_adapter_le_set_advertising_device_name() fails %d", ret);
-               goto error;
-       }
-
-       ret = bt_adapter_le_set_advertising_connectable(ble_handle->adv, true);
-       if (ret != BT_ERROR_NONE) {
-               VINE_LOGE("bt_adapter_le_set_advertising_connectable() fails %d", ret);
-               goto error;
-       }
-
-       ret = bt_adapter_le_set_advertising_mode(ble_handle->adv,
-                               BT_ADAPTER_LE_ADVERTISING_MODE_BALANCED);
+       ret = __configure_advertiser(ble_handle->adv, service_type, service_name);
        if (ret != BT_ERROR_NONE) {
-               VINE_LOGE("bt_adapter_le_set_advertising_mode() fails %d", ret);
-               goto error;
+               VINE_LOGE("__configure_advertiser() fails %d", ret);
+               goto ERR;
        }
 
        ret = bt_adapter_le_start_advertising_new(ble_handle->adv,
                                __ble_advertising_state_changed_cb, ble_handle);
        if (ret != BT_ERROR_NONE) {
                VINE_LOGE("bt_adapter_le_start_advertising_new() fails %d", ret);
-               goto error;
+               goto ERR;
        }
 
-error:
+       return VINE_DISC_ERROR_NONE;
+
+ERR:
        if (ble_handle->adv) {
                bt_adapter_le_destroy_advertiser(ble_handle->adv);
                ble_handle->adv = NULL;
@@ -172,7 +203,63 @@ vine_disc_error ble_stop_publish(void *plugin_handle)
 {
        RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
 
-       return VINE_DISC_ERROR_NONE;
+       vine_ble_s *ble_handle = (vine_ble_s *)plugin_handle;
+       RET_VAL_IF(ble_handle->adv == NULL, VINE_DISC_ERROR_INVALID_PARAMETER, "No advertiser");
+
+       int ret = bt_adapter_le_stop_advertising(ble_handle->adv);
+       ble_handle->adv = NULL;
+
+       return __convert_ble_error_to_vine_disc_error(ret);
+}
+
+static int __configure_scan_filter(bt_scan_filter_h filter, const char *service_type)
+{
+       int ret = bt_adapter_le_scan_filter_set_service_uuid(filter, VINE_UUID);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_scan_filter_set_service_uuid() fails %d", ret);
+
+       ret = bt_adapter_le_scan_filter_register(filter);
+       RET_VAL_IF(ret != BT_ERROR_NONE, ret,
+               "bt_adapter_le_scan_filter_register() fails %d", ret);
+
+       return BT_ERROR_NONE;
+}
+
+static void __le_scan_result_cb(int result, bt_adapter_le_device_scan_result_info_s *info,
+       void *user_data)
+{
+       if (info == NULL)
+               return;
+
+       if (info->adv_data_len > 31 || info->scan_data_len > 31) {
+               VINE_LOGE("Invalid length");
+               return;
+       }
+
+       int manufacturer_id;
+       char *manufacturer_data;
+       int manufacturer_len;
+       // TODO: For now, check only scan_data
+       int ret = bt_adapter_le_get_scan_result_manufacturer_data(info, BT_ADAPTER_LE_PACKET_SCAN_RESPONSE,
+               &manufacturer_id, &manufacturer_data, &manufacturer_len);
+       RET_IF(ret != BT_ERROR_NONE, "Invalid Data");
+
+       vine_ble_s *ble_handle = (vine_ble_s *)user_data;
+       int service_type_len = strlen(ble_handle->service_type);
+       if (manufacturer_len > service_type_len &&
+               strncmp(manufacturer_data, ble_handle->service_type, service_type_len) == 0) {
+               char service_name[VINE_MAX_BLE_SERVICE_NAME_LEN + 1];
+               int service_name_len = manufacturer_len - 1 - service_type_len;
+               strncpy(service_name, manufacturer_data + service_type_len + 1, service_name_len);
+               if (event_callbacks.discovered_cb) {
+                       std::map<string, string> empty_map;
+                               event_callbacks.discovered_cb(ble_handle, true,
+                                       ble_handle->service_type, service_name, NULL, 0, empty_map,
+                                       NULL, 0, ble_handle->disc_handle);
+               }
+       }
+
+       g_free(manufacturer_data);
 }
 
 vine_disc_error ble_subscribe(void *plugin_handle,
@@ -180,16 +267,51 @@ vine_disc_error ble_subscribe(void *plugin_handle,
 {
        RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
        RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL");
+       RET_VAL_IF(strlen(service_type) > VINE_MAX_BLE_SERVICE_TYPE_LEN, VINE_DISC_ERROR_INVALID_PARAMETER,
+               "too long service type");
 
        vine_ble_s *ble_handle = (vine_ble_s *)plugin_handle;
+       RET_VAL_IF(ble_handle->filter != NULL, VINE_DISC_ERROR_INVALID_PARAMETER, "Already subscribed");
+
+       int ret = bt_adapter_le_scan_filter_create(&ble_handle->filter);
+       RET_VAL_IF(ret != BT_ERROR_NONE, __convert_ble_error_to_vine_disc_error(ret),
+               "bt_adapter_le_scan_filter_create() fails");
+
+       ret = __configure_scan_filter(ble_handle->filter, service_type);
+       if (ret != BT_ERROR_NONE) {
+               VINE_LOGE("__configure_scan_filter() fails %d", ret);
+               goto ERR;
+       }
+
+       ret = bt_adapter_le_start_scan(__le_scan_result_cb, NULL);
+       if (ret != BT_ERROR_NONE) {
+               VINE_LOGE("bt_adapter_le_start_scan() fails");
+               goto ERR;
+       }
 
+       strncpy(ble_handle->service_type, service_type, VINE_MAX_BLE_SERVICE_TYPE_LEN);
        return VINE_DISC_ERROR_NONE;
+
+ERR:
+       bt_adapter_le_scan_filter_destroy(ble_handle->filter);
+       ble_handle->filter = NULL;
+
+       return __convert_ble_error_to_vine_disc_error(ret);
 }
 
 vine_disc_error ble_stop_subscribe(void *plugin_handle)
 {
        RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
 
+       vine_ble_s *ble_handle = (vine_ble_s *)plugin_handle;
+       RET_VAL_IF(ble_handle->filter == NULL, VINE_DISC_ERROR_INVALID_PARAMETER, "Not subscribed");
+
+       bt_adapter_le_stop_scan();
+
+       bt_adapter_le_scan_filter_unregister(ble_handle->filter);
+       bt_adapter_le_scan_filter_destroy(ble_handle->filter);
+       ble_handle->filter = NULL;
+
        return VINE_DISC_ERROR_NONE;
 }
 
index 26de5b37fac67d9ef7c418cfadd6cfebb46e4f67..0082fabc42db9c117d75c93e275c1d1cedd4015a 100644 (file)
@@ -29,4 +29,9 @@
 
 #define VINE_MAX_TOPIC_LEN 63
 
+// Actually, max length of service_type and service_name for ble cannot be restricted strictly.
+// Even though the constraits is met, the operation can be failed.
+#define VINE_MAX_BLE_SERVICE_TYPE_LEN 15
+#define VINE_MAX_BLE_SERVICE_NAME_LEN 15
+
 #endif /* __VINE_SERV__VINE_CONSTANTS_H__ICE_H__ */