From: Abhishek Chandra Date: Tue, 14 Aug 2018 11:57:13 +0000 (+0530) Subject: BLE Heart Rate Profile - Collector Implementation X-Git-Tag: accepted/tizen/unified/20180830.061026^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F85%2F186285%2F15;p=platform%2Fcore%2Fapi%2Fbluetooth.git BLE Heart Rate Profile - Collector Implementation 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 --- diff --git a/include/bluetooth_internal.h b/include/bluetooth_internal.h index 67c05ba..e1e369b 100644 --- a/include/bluetooth_internal.h +++ b/include/bluetooth_internal.h @@ -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); /** * @} diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index 4fadc08..4e1181e 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -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. diff --git a/include/bluetooth_type.h b/include/bluetooth_type.h index 8f037d5..107a6ba 100644 --- a/include/bluetooth_type.h +++ b/include/bluetooth_type.h @@ -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. diff --git a/include/bluetooth_type_internal.h b/include/bluetooth_type_internal.h index 6f3c27e..790034f 100644 --- a/include/bluetooth_type_internal.h +++ b/include/bluetooth_type_internal.h @@ -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 */ diff --git a/src/bluetooth-hrp.c b/src/bluetooth-hrp.c index 45eb899..749c43c 100644 --- a/src/bluetooth-hrp.c +++ b/src/bluetooth-hrp.c @@ -39,6 +39,13 @@ 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; +} + diff --git a/test/bt_unit_test.c b/test/bt_unit_test.c index 51c4a69..88043bd 100644 --- a/test/bt_unit_test.c +++ b/test/bt_unit_test.c @@ -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; diff --git a/test/bt_unit_test.h b/test/bt_unit_test.h index bfdb286..d37b39c 100644 --- a/test/bt_unit_test.h +++ b/test/bt_unit_test.h @@ -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;