BLE Heart Rate Profile - Collector Implementation 85/186285/15 accepted/tizen/unified/20180830.061026 submit/tizen/20180829.084300
authorAbhishek Chandra <abhishek.ch@samsung.com>
Tue, 14 Aug 2018 11:57:13 +0000 (17:27 +0530)
committerPyun DoHyun <dh79.pyun@samsung.com>
Wed, 29 Aug 2018 07:21:02 +0000 (07:21 +0000)
BLE heartrate profile collector implementation in
bluetooth is added ,following CAPI are added :
    - bt_hrp_collector_create
    - bt_hrp_collector_destory
    - bt_hrp_collector_start_scan
    - bt_hrp_collector_stop_scan
    - bt_hrp_collector_connect
    - bt_hrp_collector_disconnect
    - bt_hrp_collector_set_notification
    - bt_hrp_get_body_sensor_location
    - bt_hrp_collector_set_connection_state_changed_cb
    - bt_hrp_collector_unset_connection_state_changed_cb

Change-Id: I128900292674eb3ad8db9e65865c32c088ba622b
Signed-off-by: Abhishek Chandra <abhishek.ch@samsung.com>
include/bluetooth_internal.h
include/bluetooth_private.h
include/bluetooth_type.h
include/bluetooth_type_internal.h
src/bluetooth-hrp.c
test/bt_unit_test.c
test/bt_unit_test.h

index 67c05ba..e1e369b 100644 (file)
@@ -4333,6 +4333,76 @@ int bt_hrp_sensor_update_heartrate_value(int heartrate);
 
 int bt_hrp_sensor_destroy();
 
+/**
+ * @internal
+ * @brief HRP collector API to create collector .
+ */
+
+int bt_hrp_collector_create(const char *remote_address,
+                               bt_hrp_collector_h *collector);
+
+/**
+ * @internal
+ * @brief HRP collector API to destory collector.
+ */
+void bt_hrp_collector_destory(bt_hrp_collector_h collector);
+
+/**
+ * @internal
+ * @brief HRP collector API to start scan .
+ */
+int bt_hrp_collector_start_scan();
+
+/**
+ * @internal
+ * @brief HRP collector API to stop scan.
+ */
+int bt_hrp_collector_stop_scan();
+
+/**
+ * @internal
+ * @brief HRP collector API to connect to remote sensor .
+ */
+int bt_hrp_collector_connect(const char *address, bool auto_connect);
+
+/**
+ * @internal
+ * @brief HRP collector API to disconnect to remote sensor .
+ */
+int bt_hrp_collector_disconnect(const char *address);
+
+/**
+ * @internal
+ * @brief HRP collector API to set notification on / off.
+ */
+int bt_hrp_collector_set_notification(bt_hrp_collector_h collector,
+                       bt_hrp_collector_heart_rate_value_changed_cb callback,
+                       bool isNotify);
+
+/**
+ * @internal
+ * @brief HRP collector API to read Body Sensor location , fills body sensor location in bsl_location
+ */
+
+bt_body_sensor_location_e bt_hrp_get_body_sensor_location(bt_hrp_collector_h collector,
+                       bt_hrp_collector_bsl_read_completed_cb bsl_read_cb);
+
+
+/**
+ * @internal
+ * @brief HRP collector API to set connection state callback
+ */
+
+int bt_hrp_collector_set_connection_state_changed_cb(bt_hrp_collector_h collector,
+                       bt_hrp_collector_connection_state_changed_cb callback,
+                       void *user_data);
+
+/**
+ * @internal
+ * @brief HRP collector API to unset connection state callback
+ */
+
+int bt_hrp_collector_unset_connection_state_changed_cb(bt_hrp_collector_h collector);
 
 /**
  * @}
index 4fadc08..4e1181e 100644 (file)
@@ -587,6 +587,7 @@ typedef void (*bt_adapter_passkey_notification_cb)(const char *remote_address, c
 #define BT_FEATURE_GATT_SERVER "tizen.org/feature/network.bluetooth.le.gatt.server"
 #define BT_FEATURE_GATT_CLIENT "tizen.org/feature/network.bluetooth.le.gatt.client"
 #define BT_FEATURE_HRS "tizen.org/feature/network.bluetooth.le.hrp.sensor"
+#define BT_FEATURE_HRC "tizen.org/feature/network.bluetooth.le.hrp.collector"
 
 
 #define BT_CHECK_SUPPORTED_FEATURE(feature_name) \
@@ -935,7 +936,6 @@ void _bt_tds_update_seeker_connection_state_changed(int result, const char *remo
  */
 void __bt_hrp_le_connection_state_changed_cb(int result, const char *remote_address, bool connected);
 
-
 /**
  * @internal
  * @brief  Parses TDS AD Type data recived in scan, to extract meaningful transport specific data.
index 8f037d5..107a6ba 100644 (file)
@@ -1708,6 +1708,7 @@ typedef void (*bt_gatt_client_request_completed_cb) (int result,
  */
 typedef void (*bt_gatt_client_characteristic_value_changed_cb) (bt_gatt_h characteristic,
                char *value, int len, void *user_data);
+
 /**
  * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_MODULE
  * @brief Called when the connection state is changed.
index 6f3c27e..790034f 100644 (file)
@@ -1125,6 +1125,70 @@ typedef enum {
        BT_BSL_FOOT,
 } bt_body_sensor_location_e;
 
+/**
+ * @internal
+ * @brief The handle of a HRP Collector client which is associated with a remote HRP sensor
+ * @since_tizen 4.0
+ */
+typedef void *bt_hrp_collector_h;
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE
+ * @brief  Called when a value of a watched characteristic's GATT handle has been changed in HRP.
+ * @since_tizen 2.3.1
+ *
+ * @remarks After this function is returned, a changed value is automatically \n
+ * applied to @a characteristic. Before that, @a characteristic has an old value.
+ *
+ * @param[in] characteristic The characteristic's GATT handle of which value change is informed. It has an old value.
+ * @param[in] value The new value
+ * @param[in] len The length of @a value
+ * @param[in] user_data The user data passed from the registering function
+ *
+ * @see bt_gatt_client_set_characteristic_value_changed_cb()
+ */
+typedef void (*bt_hrp_collector_heart_rate_value_changed_cb) (bt_gatt_client_h characteristic,
+               unsigned short hr_value, void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE
+ * @brief type information structure ,define what type of reequest is made.
+ * @since_tizen 4.0
+ *
+ * @see bt_gatt_client_att_mtu_changed_cb()
+ */
+
+typedef enum {
+       HEART_RATE = 1,
+       BODY_SENSOR_LOCATION,
+       HEART_CONTROL_POINT,
+} bt_serv_char_type_t;
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE
+ * @brief  Called when the client request read operation on body sensor location has been completed.
+ * @since_tizen 4
+ *
+ * @param[in] result The result of a request
+ * @param[in] request_handle The requesting GATT handle
+ * @param[in] type : Heart Rate Value , Body Sensor Location or Heart Control Point
+ * @param[in] value : Int value corresponding to the type recieved .
+ * @param[in] user_data The user data passed from the requesting function
+ *
+ */
+typedef void (*bt_hrp_collector_bsl_read_completed_cb) (int result,
+               bt_hrp_collector_h request_handle, bt_body_sensor_location_e location, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 4.0
+ * @brief HRP Collector profile Connection State changed callback which is associated with
+ *     a remote HRP sensor.
+ */
+typedef void (*bt_hrp_collector_connection_state_changed_cb)
+               (int result, const char *remote_address, bt_hrp_collector_h collector,
+                 bool connected, void *user_data);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 45eb899..749c43c 100644 (file)
        BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_HRS); \
 }
 
+#define BT_CHECK_HRC_SUPPORT() \
+{ \
+       BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); \
+       BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE); \
+       BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_HRC); \
+}
+
 /*======================================================================================================
        Heart Rate Server - Structures
 ========================================================================================================*/
@@ -90,6 +97,27 @@ static guint adv_timer_id;
 GSList *sensor_list;
 static bt_hrp_server_info_s hrp_server_info_s;
 
+//Collector Structures
+
+typedef struct {
+       char *remote_address;   //remote sensor
+       bool connected;         //is connected to sensor or not
+       int heart_rate_measurement;
+       bt_gatt_h bsl_char_handle;
+       bt_hrp_collector_connection_state_changed_cb connection_callback;       //GATT connection state changes callback
+       void *conn_cb_user_data;        //
+       char *hrs_service_handle;            /* HRS Primary Service Handle */
+       char *dis_service_handle;            /* DIS Primary Service Handle */
+       bool cccd_enabled;                   /* TDS Control Point CCCD is enabled or not */
+       bt_hrp_collector_heart_rate_value_changed_cb char_update_cb;
+       bt_hrp_collector_bsl_read_completed_cb bsl_read_cb;
+} bt_hrp_collector_s;
+
+GSList *hrp_collector_list;
+static bt_adapter_le_scan_result_cb scan_cb;   //le scan application callback
+static bt_hrp_collector_s *_bt_hrp_collector_find(const char *remote_address);
+
+
 /*======================================================================================================
        Heart Rate Server - Utility
 ========================================================================================================*/
@@ -471,37 +499,51 @@ void __bt_hrp_le_connection_state_changed_cb(int result,
        BT_INFO("[HR]Remote Address : %s", remote_address);
        bool isappend = true;
        int error_code = BT_ERROR_NOT_INITIALIZED;
+       /*To do Check for if it for sensor or collector */
+
+       /*If Sensor */
+       if (hrp_server_info_s.hrp_sensor == NULL) {
+
+               GSList *iter = hrp_server_info_s.hrs_collector_connected_list;
+
+               for (; iter; iter = g_slist_next(iter)) {
+                       if ((iter) && (iter->data != NULL) &&
+                               (((bt_hrp_collector_notify_info_s *)iter->data)->remote_address != NULL)) {
+                               if (!g_ascii_strcasecmp(((bt_hrp_collector_notify_info_s *)iter->data)->remote_address,
+                                                                                       remote_address)) {
+                                       ((bt_hrp_collector_notify_info_s *)iter->data)->isconnected = connected;
+                                       isappend = false;
+                                       break;
+                               }
+                       }
+               }
 
-       GSList *iter = hrp_server_info_s.hrs_collector_connected_list;
+               if (isappend) {
+                       bt_hrp_collector_notify_info_s *client_s = g_malloc(sizeof(bt_hrp_collector_notify_info_s));
+                       client_s->isconnected = connected;
+                       client_s->remote_address = g_strdup(remote_address);
+                       hrp_server_info_s.hrs_collector_connected_list =
+                                       g_slist_append(hrp_server_info_s.hrs_collector_connected_list, (gpointer)client_s);
+               }
 
-       for (; iter; iter = g_slist_next(iter)) {
-               if ((iter) && (iter->data != NULL) &&
-                       (((bt_hrp_collector_notify_info_s *)iter->data)->remote_address != NULL)) {
-                       if (!g_ascii_strcasecmp(((bt_hrp_collector_notify_info_s *)iter->data)->remote_address,
-                                                                               remote_address)) {
-                               ((bt_hrp_collector_notify_info_s *)iter->data)->isconnected = connected;
-                               isappend = false;
-                               break;
-                       }
+               if (connected == true && hrp_server_info_s.is_notify_cb_set == false) {
+                       error_code = bt_gatt_server_notify_characteristic_changed_value(hrp_server_info_s.hrs_characteristic,
+                                                               __bt_hrp_notification_send_cb,  NULL,  NULL);
+                       if (error_code != BT_ERROR_NONE)
+                               BT_ERR("bt_gatt_server_notify_characteristic_changed_value : %s\n", _bt_convert_error_to_string(error_code));
+                       hrp_server_info_s.is_notify_cb_set = true;
                }
-       }
 
-       if (isappend) {
-               bt_hrp_collector_notify_info_s *client_s = g_malloc(sizeof(bt_hrp_collector_notify_info_s));
-               client_s->isconnected = connected;
-               client_s->remote_address = g_strdup(remote_address);
-               hrp_server_info_s.hrs_collector_connected_list =
-                               g_slist_append(hrp_server_info_s.hrs_collector_connected_list, (gpointer)client_s);
-       }
+       } else {
+                       /*If Collector*/
+                       bt_hrp_collector_s *collector_s = _bt_hrp_collector_find(remote_address);
 
-       if (connected == true && hrp_server_info_s.is_notify_cb_set == false) {
-               error_code = bt_gatt_server_notify_characteristic_changed_value(hrp_server_info_s.hrs_characteristic,
-                                                       __bt_hrp_notification_send_cb,  NULL,  NULL);
-               if (error_code != BT_ERROR_NONE)
-                       BT_ERR("bt_gatt_server_notify_characteristic_changed_value : %s\n", _bt_convert_error_to_string(error_code));
-               hrp_server_info_s.is_notify_cb_set = true;
+                       if (collector_s && collector_s->connection_callback)
+                               collector_s->connection_callback(result, remote_address,
+                                               (bt_hrp_collector_h)collector_s, connected, NULL);
        }
 
+
 }
 
 /*Application Interfaces*/
@@ -848,3 +890,352 @@ int bt_hrp_sensor_destroy()
 
 }
 
+/*======================================================================================================
+  Hear Rate Collector
+  =======================================================================================================*/
+static void _bt_hrp_collector_characteristic_value_changed_cb(bt_hrp_collector_h characteristic,
+               char *value, int len, void *user_data)
+{
+
+       BT_INFO("_bt_hrp_collector_characteristic_value_changed_cb Called with value %s", value);
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)characteristic;
+
+       /*To do :Extract value in to uint and send*/
+       unsigned short hr_value = 1;
+
+       if (collector_s->char_update_cb)
+               collector_s->char_update_cb(characteristic, hr_value, user_data);
+
+}
+static void _bt_hrp_collector_bsl_read_completed_cb (int result,       bt_hrp_collector_h collector, void *user_data)
+{
+       BT_INFO();
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)collector;
+       char *value = NULL;
+       int len = 0;
+
+       int error_code = bt_gatt_get_value(collector_s->bsl_char_handle, &value, &len);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("bt_gatt_get_value is failed : %d", error_code);
+               return;
+       }
+
+       if (collector_s->bsl_read_cb)
+               collector_s->bsl_read_cb(result, collector, (bt_body_sensor_location_e) *value, user_data);
+
+}
+
+static bt_hrp_collector_s *_bt_hrp_collector_find(const char *remote_address)
+{
+       GSList *l;
+
+       for (l = hrp_collector_list; l; l = g_slist_next(l)) {
+
+               if ((l == NULL) || (l->data == NULL) ||
+                               (((bt_hrp_collector_s *)l->data)->remote_address == NULL)) {
+                       BT_ERR("_bt_hrp_collector_find Error Parameter are NULL..\n");
+                       continue;
+               } else if (!g_ascii_strcasecmp(
+                                       ((bt_hrp_collector_s *)l->data)->remote_address, remote_address)) {
+                       return ((bt_hrp_collector_s *)l->data);
+               }
+       }
+       return NULL;
+}
+
+static void __bt_hrp_reset_collector_data(bt_hrp_collector_s *collector)
+{
+
+       g_free((collector)->remote_address);
+       (collector)->remote_address = NULL;
+
+       (collector)->connected = false;
+
+       (collector)->connection_callback = NULL;
+
+       (collector)->conn_cb_user_data = NULL;
+
+       g_free(collector->hrs_service_handle);
+       collector->hrs_service_handle = NULL;
+
+       collector->cccd_enabled = false;
+}
+
+int bt_hrp_collector_create(const char *remote_address, bt_hrp_collector_h *collector)
+{
+       int error_code = BT_ERROR_NONE;
+       bt_hrp_collector_s *collector_s = NULL;
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(remote_address); /* LCOV_EXCL_START */
+
+       if (_bt_hrp_collector_find(remote_address) != NULL)
+               return BT_ERROR_ALREADY_DONE;
+
+       error_code = bt_gatt_client_create(remote_address, collector);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               return error_code;
+       }
+
+       collector_s = g_malloc0(sizeof(*collector_s));
+       if (collector_s == NULL) {
+               error_code = BT_ERROR_OUT_OF_MEMORY;
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               return error_code;
+       }
+
+       __bt_hrp_reset_collector_data(collector_s);
+
+       collector_s->remote_address = g_strdup(remote_address);
+       if (collector_s->remote_address == NULL) {
+               g_free(collector_s);
+               error_code = BT_ERROR_OUT_OF_MEMORY;
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               return error_code;
+       }
+
+       hrp_collector_list = g_slist_append(hrp_collector_list, collector_s);
+       BT_INFO("bt_hrp_collector_create Exit");
+
+       return error_code;
+}
+
+void bt_hrp_collector_destory(bt_hrp_collector_h collector)
+{
+
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)collector;
+
+       if (collector_s) {
+               BT_DBG("bt_hrp_collector_destory destroy Remote Provider [%s]", collector_s->remote_address);
+               __bt_hrp_reset_collector_data(collector_s);
+
+               hrp_collector_list = g_slist_remove(hrp_collector_list, collector_s);
+               g_free(collector_s);
+       }
+
+}
+
+static void __bt_hrp_le_scan_result_cb(int result,
+               bt_adapter_le_device_scan_result_info_s *info,
+               void *user_data)
+{
+
+       BT_INFO("__bt_hrp_le_scan_result_cb \n");
+       BT_INFO("%s Adv %d Scan resp %d RSSI %d Addr_type %d",
+                       info->remote_address, info->adv_data_len,
+                       info->scan_data_len, info->rssi,
+                       info->address_type);
+
+       if (scan_cb)
+               scan_cb(result, info, user_data);
+
+}
+
+int bt_hrp_collector_set_connection_state_changed_cb(bt_hrp_collector_h collector,
+               bt_hrp_collector_connection_state_changed_cb callback,
+               void *user_data)
+{
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)collector;
+
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(collector_s);
+       BT_CHECK_INPUT_PARAMETER(callback);
+
+       if (_bt_hrp_collector_find(collector_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("Set HRP collectorr Connection State changed callback");
+       /* register the callback */
+       collector_s->connection_callback = callback;
+       collector_s->conn_cb_user_data = user_data;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_hrp_collector_unset_connection_state_changed_cb(bt_hrp_collector_h collector)
+{
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)collector;
+
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(collector_s);
+
+       if (_bt_hrp_collector_find(collector_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("Set HRP collectorr Connection State changed callback");
+       /* register the callback */
+       collector_s->connection_callback = NULL;
+       collector_s->conn_cb_user_data = NULL;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_hrp_collector_start_scan(bt_adapter_le_scan_result_cb cb)
+{
+
+       bt_scan_filter_h scan_filter = NULL;
+       int error_code = BT_ERROR_NONE;
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+
+       scan_cb = cb;   //le scan application callback
+       /*ToDo error code handling*/
+       error_code = bt_adapter_le_scan_filter_create(&scan_filter);
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("failed with [0x%04x]", error_code);
+
+       error_code = bt_adapter_le_scan_filter_set_service_uuid(scan_filter, HEART_RATE_UUID);
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("failed with [0x%04x]", error_code);
+
+       error_code = bt_adapter_le_scan_filter_register(scan_filter);
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("failed with [0x%04x]", error_code);
+
+       error_code = bt_adapter_le_start_scan(
+                       __bt_hrp_le_scan_result_cb, NULL);
+       BT_ERR("returns %s\n", _bt_convert_error_to_string(error_code));
+
+       error_code = bt_adapter_le_scan_filter_destroy(scan_filter);
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("failed with [0x%04x]", error_code);
+
+       return error_code;
+
+}
+
+int bt_hrp_collector_stop_scan()
+{
+       int error_code = BT_ERROR_NONE;
+
+       error_code = bt_adapter_le_stop_scan();
+       BT_ERR("returns %s\n", _bt_convert_error_to_string(error_code));
+
+       scan_cb = NULL;
+
+       return error_code;
+
+}
+
+int bt_hrp_collector_connect(const char *address, bool auto_connect)
+{
+
+       int error_code = BT_ERROR_NONE;
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+
+       error_code = bt_gatt_connect(address, auto_connect);
+
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+       return error_code;
+}
+
+int bt_hrp_collector_disconnect(const char *address)
+{
+       int error_code = BT_ERROR_NONE;
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       error_code = bt_gatt_disconnect(address);
+
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+       return error_code;
+}
+
+int bt_hrp_collector_set_notification(bt_hrp_collector_h collector,
+               bt_hrp_collector_heart_rate_value_changed_cb callback,
+               bool isNotify)
+{
+       int error_code = BT_ERROR_NONE;
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)collector;
+       bt_gatt_h svc = NULL;
+       bt_gatt_h chr = NULL;
+
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(collector_s);
+
+       if (_bt_hrp_collector_find(collector_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+
+       error_code = bt_gatt_client_get_service(collector, HEART_RATE_MEASUREMENT_UUID, &svc);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("bt_gatt_client_get_service is failed : %d", error_code);
+               return error_code;
+       }
+
+       error_code = bt_gatt_service_get_characteristic(svc, HEART_RATE_CHARAC_CFG_UUID, &chr);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("bt_gatt_service_get_characteristic is failed : %d", error_code);
+               return error_code;
+       }
+
+       collector_s->char_update_cb = callback;
+
+       if (isNotify == true) {
+               error_code = bt_gatt_client_set_characteristic_value_changed_cb(chr, _bt_hrp_collector_characteristic_value_changed_cb, NULL);
+               if (error_code != BT_ERROR_NONE)
+                       BT_ERR("bt_gatt_client_set_characteristic_value_changed_cb is failed : %d", error_code);
+       } else {
+               error_code = bt_gatt_client_unset_characteristic_value_changed_cb(chr);
+               if (error_code != BT_ERROR_NONE)
+                       BT_ERR("bt_gatt_client_set_characteristic_value_changed_cb is failed : %d", error_code);
+       }
+
+       return error_code;
+}
+
+bt_body_sensor_location_e bt_hrp_get_body_sensor_location(bt_hrp_collector_h collector,
+                       bt_hrp_collector_bsl_read_completed_cb bsl_read_cb)
+{
+       int error_code = BT_ERROR_NONE;
+       bt_gatt_h svc = NULL;
+       bt_gatt_h chr = NULL;
+
+       bt_hrp_collector_s *collector_s = (bt_hrp_collector_s *)collector;
+
+       BT_CHECK_HRC_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(collector_s);
+
+       if (_bt_hrp_collector_find(collector_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       error_code = bt_gatt_client_get_service(collector, HEART_RATE_UUID, &svc);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("bt_gatt_client_get_service is failed : %d", error_code);
+               return error_code;
+       }
+
+       error_code = bt_gatt_service_get_characteristic(svc, BODY_SENSOR_LOCATION_UUID, &chr);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("bt_gatt_service_get_characteristic is failed : %d", error_code);
+               return error_code;
+       }
+
+       collector_s->bsl_read_cb = bsl_read_cb;
+       collector_s->bsl_char_handle = chr;
+
+       //read bsl char
+       error_code = bt_gatt_client_read_value(chr, _bt_hrp_collector_bsl_read_completed_cb, NULL);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("bt_gatt_client_read_value is failed : %d", error_code);
+               return error_code;
+       }
+
+       return error_code;
+}
+
index 51c4a69..88043bd 100644 (file)
@@ -123,6 +123,9 @@ char *tds_act_address;
 bt_tds_seeker_h seeker;
 
 bt_otp_client_h otp_client;
+bt_hrp_collector_h collector;
+bool set_notif = true;
+
 
 static unsigned char *hash = NULL;
 static unsigned char *randomizer = NULL;
@@ -183,7 +186,9 @@ tc_table_t tc_main[] = {
        {"OTP"
                , BT_UNIT_TEST_TABLE_OTP},
        {"HRS"
-               , BT_UNIT_TEST_TABLE_HR_SENSOR},
+               , BT_UNIT_TEST_TABLE_HRP_SENSOR},
+       {"HRC"
+               , BT_UNIT_TEST_TABLE_HRP_COLLECTOR},
        {"Initialize All"
                , BT_UNIT_TEST_FUNCTION_INITIALIZE_ALL},
        {"FINISH"
@@ -1193,6 +1198,30 @@ tc_table_t tc_hr_sensor[] = {
        {NULL                                   , 0x0000},
 };
 
+tc_table_t tc_hr_collector[] = {
+       {"BACK"
+               , BT_UNIT_TEST_FUNCTION_BACK},
+       {"[collector]HR collector set notification"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_SET_NOTIFICATION},
+       {"[collector]HR collector start scan"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_START_SCAN},
+       {"[collector]HR collector stop scan"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_STOP_SCAN},
+       {"[collector]HR collector connect"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CONNECT},
+       {"[collector]HR collector disconnect"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_DISCONNECT},
+       {"[collector]HR collector create"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CREATE},
+       {"[collector]HR collector destroy"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_DESTROY},
+       {"[collector]HR collector connection state callback"
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CONNECTION_STATE_CALLBACK},
+       {"[collector]HR collector read bsl value "
+               , BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_GET_BSL_LOC},
+       {NULL                                   , 0x0000},
+};
+
 
 tc_table_t tc_automated_test[] = {
        /* Automated test Functions*/
@@ -1303,9 +1332,12 @@ void tc_usage_print(void)
        case BT_UNIT_TEST_TABLE_OTP:
                tc_table = tc_otp;
                break;
-       case BT_UNIT_TEST_TABLE_HR_SENSOR:
+       case BT_UNIT_TEST_TABLE_HRP_SENSOR:
                tc_table = tc_hr_sensor;
                break;
+       case BT_UNIT_TEST_TABLE_HRP_COLLECTOR:
+               tc_table = tc_hr_collector;
+               break;
        case BT_UNIT_TEST_TABLE_MAIN:
 __default__:
        default:
@@ -2555,6 +2587,20 @@ void __bt_gatt_client_value_changed_cb(bt_gatt_h chr,
 
        return;
 }
+void __bt_hrp_heart_rate_value_changed_cb(bt_gatt_h chr,
+       unsigned short hr_value, void *user_data)
+{
+       char *uuid = NULL;
+
+       bt_gatt_get_uuid(chr, &uuid);
+
+       TC_PRT("Value changed for [%s]", uuid);
+       TC_PRT("Value [%d]", hr_value);
+
+       g_free(uuid);
+
+       return;
+}
 
 void __bt_HP_client_cp_req_status_changed_cb(bt_gatt_h chr,
        char *value, int len, void *user_data)
@@ -3062,6 +3108,20 @@ static void __bt_tds_seeker_connection_state_changed_cb(int result, const char *
                BT_ERR("TDS Connection failed!");
 }
 
+static void __bt_hrp_collector_connection_state_changed_cb(int result, const char *remote_address,
+                       bt_hrp_collector_h seeker, bool connected, void *user_data)
+{
+       TC_PRT("Result: %s", __bt_get_error_message(result));
+       if (result == BT_ERROR_NONE) {
+               if (connected)
+                       TC_PRT("HRP Collector connected(address = %s)", remote_address);
+               else
+                       TC_PRT("HRP Collector Disconnected (address = %s)", remote_address);
+       } else
+               BT_ERR("HRP Collection Connection failed!");
+}
+
+
 static void __bt_tds_seeker_complete_transport_data_cb(int result, const char *remote_address,
                        bt_tds_transport_block_list_s *info, void *user_data)
 {
@@ -3216,6 +3276,26 @@ static void __bt_adapter_hrp_sensor_adv_state_cb(int result,
                "started" : "stopped", adv_state);
 }
 
+void __bt_gatt_client_read_request_completed_cb(int result,
+               bt_gatt_h request_handle, void *user_data)
+{
+       TC_PRT("[HR]Result : %d", result);
+}
+
+void __bt_gatt_client_write_request_completed_cb(int result,
+               bt_gatt_h request_handle, void *user_data)
+{
+       TC_PRT("[HR]Result : %d", result);
+}
+void _bt_hrp_collector_bsl_read_completed_cb(int result,
+               bt_hrp_collector_h request_handle, bt_body_sensor_location_e location, void *user_data)
+{
+       TC_PRT("[HR]Result : %d", result);
+       TC_PRT("[HR]request_handle : %p", request_handle);
+       TC_PRT("[HR]location [%d]", location);
+
+}
+
 static void __bt_initialize_all(void)
 {
        int ret;
@@ -9485,7 +9565,7 @@ int test_input_callback(void *data)
                }
                break;
        }
-               case BT_UNIT_TEST_TABLE_HR_SENSOR: {
+               case BT_UNIT_TEST_TABLE_HRP_SENSOR: {
                switch (test_id) {
                case BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_HR_VALUE: {
                        TC_PRT("HR SENSOR SET HR VALUE\n");
@@ -9552,6 +9632,81 @@ int test_input_callback(void *data)
                }
                break;
        }
+               case BT_UNIT_TEST_TABLE_HRP_COLLECTOR: {
+               switch (test_id) {
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CONNECTION_STATE_CALLBACK: {
+                               TC_PRT("HR COLLECTOR CONNECTION STATE CALLBACK\n");
+                       if (collector) {
+                               ret = bt_hrp_collector_set_connection_state_changed_cb(collector,
+                                               __bt_hrp_collector_connection_state_changed_cb, NULL);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_SET_NOTIFICATION: {
+                               TC_PRT("HR COLLECTOR SET NOTIFICATION\n");
+                               if (set_notif == true) {
+                                       set_notif = false;
+                                       ret = bt_hrp_collector_set_notification(collector,
+                                                                       __bt_hrp_heart_rate_value_changed_cb, true);
+                                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               } else {
+                                       set_notif = true;
+                                       ret = bt_hrp_collector_set_notification(collector,
+                                                                       __bt_hrp_heart_rate_value_changed_cb, false);
+                                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               }
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CREATE: {
+                               TC_PRT("HR COLLECTOR CREATE\n");
+                               ret = bt_hrp_collector_create(remote_addr, &collector);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_START_SCAN: {
+                               TC_PRT("HR COLLECTOR START SCAN\n");
+                               ret = bt_hrp_collector_start_scan(__bt_adapter_le_scan_result_cb);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_STOP_SCAN: {
+                               TC_PRT("HR COLLECTOR STOP SCAN\n");
+                               ret = bt_hrp_collector_stop_scan();
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CONNECT: {
+                               TC_PRT("HR COLLECTOR CONNECT\n");
+                               ret = bt_hrp_collector_connect(remote_addr, true);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_DISCONNECT: {
+                               TC_PRT("HR COLLECTOR DISCONNECT\n");
+                               ret = bt_hrp_collector_disconnect(remote_addr);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_GET_BSL_LOC: {
+                               TC_PRT("HR COLLECTOR GET BSL LOCATION\n");
+                               if (collector) {
+                                       ret = bt_hrp_get_body_sensor_location(collector, _bt_hrp_collector_bsl_read_completed_cb);
+                                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                               }
+                               break;
+               }
+               case BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_DESTROY: {
+                               TC_PRT("HR COLLECTOR DESTROY\n");
+                               bt_hrp_collector_destory(collector);
+                               break;
+               }
+               default:
+                       break;
+               }
+               break;
+       }
+
        case BT_UNIT_TEST_TABLE_ETC: {
                static unsigned int delay = 0;
                bt_onoff_cnt = 0;
index bfdb286..d37b39c 100644 (file)
@@ -54,7 +54,8 @@ typedef enum {
        BT_UNIT_TEST_TABLE_TDS_PROVIDER,
        BT_UNIT_TEST_TABLE_TDS_SEEKER,
        BT_UNIT_TEST_TABLE_OTP,
-       BT_UNIT_TEST_TABLE_HR_SENSOR,
+       BT_UNIT_TEST_TABLE_HRP_SENSOR,
+       BT_UNIT_TEST_TABLE_HRP_COLLECTOR,
        BT_UNIT_TEST_TABLE_FINISH = 0xFF,
 } bt_unit_test_table_e;
 
@@ -529,7 +530,16 @@ typedef enum {
        BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_NOTIFY,
        BT_UNIT_TEST_FUNCTION_HR_SENSOR_NOTIFY,
        BT_UNIT_TEST_FUNCTION_HR_SENSOR_DESTORY,
-
+       /*HR-Collector*/
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_SET_NOTIFICATION = 1,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_START_SCAN,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_STOP_SCAN,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CONNECT,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_DISCONNECT,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CREATE,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_DESTROY,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_CONNECTION_STATE_CALLBACK,
+       BT_UNIT_TEST_FUNCTION_HR_COLLECTOR_GET_BSL_LOC,
 
        BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS = 0XFF,
 } bt_unit_test_function_e;