From: Abhishek Chandra Date: Thu, 2 Aug 2018 12:38:45 +0000 (+0530) Subject: BLE Heart Rate Profile - Sensor Implementation X-Git-Tag: submit/tizen/20180829.084300~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=36735bd5d5bb28ddcdff74b3d4c50a39aeaef7be;p=platform%2Fcore%2Fapi%2Fbluetooth.git BLE Heart Rate Profile - Sensor Implementation BLE heartrate profile sensor implementation in bluetooth is added ,following CAPI are added : - bt_hrp_set_heartrate_value - bt_hrp_set_location_value - bt_hrp_set_energy_value - bt_hrp_set_rr_interval - bt_hrp_set_contact_value - bt_hrp_set_device_manufacturer_name - bt_hrp_set_interval - bt_hrp_set_sensor_notification_state_change_cb - bt_hrp_set_sensor_send_notification_state_changed_cb - bt_hrp_set_sensor_read_value_cb - bt_hrp_set_sensor_write_value_cb - bt_hrp_sensor_create - bt_hrp_sensor_start - bt_hrp_sensor_stop - bt_hrp_sensor_update_heartrate_value - bt_hrp_sensor_destroy Change-Id: Ia1cc6de29f147ba3b2827c5b6cd0bf3334392e60 Signed-off-by: Abhishek Chandra --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c6d3219..7605bab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ src/bluetooth-dpm.c src/bluetooth-proximity.c src/bluetooth-tds.c src/bluetooth-otp.c +src/bluetooth-hrp.c ) LIST(APPEND SOURCES src/bluetooth-proximity.c) diff --git a/include/bluetooth_internal.h b/include/bluetooth_internal.h index 5b1383c..67c05ba 100644 --- a/include/bluetooth_internal.h +++ b/include/bluetooth_internal.h @@ -4250,6 +4250,90 @@ int bt_otp_client_execute_object(bt_otp_client_h otp_client, int bt_otp_client_delete_object(bt_otp_client_h otp_client, bt_otp_client_object_delete_cb callback, void *user_data); + +//====================================================================================== + +/** + * @internal + * @brief HRP Sensor API to set initial heart rate value , before creating sensor. + */ +int bt_hrp_sensor_set_heartrate_value(int heartrate); + +/** + * @internal + * @brief HRP Sensor API to set initial Location value , before creating sensor. + */ +int bt_hrp_sensor_set_location_value(bt_body_sensor_location_e location); + +/** + * @internal + * @brief HRP Sensor API to set initial energy value (Value Range : 0-9) , before creating sensor. + */ +int bt_hrp_sensor_set_energy_value(int energy_value); + +/** + * @internal + * @brief HRP Sensor API to set initial rr interval value (Value range : 0-8 If EE is supported, + * 0-9 if EE not supported) before creating sensor. + */ +int bt_hrp_sensor_set_rr_interval(int interval); + +/** + * @internal + * @brief HRP Sensor API to set initial contact value , wearable in contact with + * user or user has removed it, before creating sensor. + */ +int bt_hrp_sensor_set_contact_value(bool enable); + +/** + * @internal + * @brief HRP Sensor API to set manufacturer name , before creating sensor. + */ +int bt_hrp_sensor_set_device_manufacturer_name(char *manuf_name); + +/** + * @internal + * @brief HRP Sensor API to set Notification callback, before creating sensor. + */ +int bt_hrp_sensor_set_sensor_notification_state_change_cb( + bt_gatt_server_characteristic_notification_state_changed_cb callback, void *user_data); + +/** + * @internal + * @brief HRP Sensor API for creating sensor and services. + */ + +int bt_hrp_sensor_create(void); + +/** + * @internal + * @brief HRP Sensor API to start advertising . + */ + +int bt_hrp_sensor_start(bt_hrp_sensor_advertising_state_changed_cb cb); + +/** + * @internal + * @brief HRP Sensor API to stop advertising . + */ + +int bt_hrp_sensor_stop(void); + +/** + * @internal + * @brief HRP Sensor API to Notify Heartrate value. + */ + +int bt_hrp_sensor_update_heartrate_value(int heartrate); + +/** + * @internal + * @brief HRP Sensor API to destory heart rate sensor . + */ + +int bt_hrp_sensor_destroy(); + + /** * @} */ diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index 9fa661b..4fadc08 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -586,6 +586,8 @@ typedef void (*bt_adapter_passkey_notification_cb)(const char *remote_address, c #define BT_FEATURE_OOB "tizen.org/feature/network.bluetooth.oob" #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_CHECK_SUPPORTED_FEATURE(feature_name) \ do { \ @@ -927,6 +929,13 @@ int _bt_proximity_connection_set_state_changed(int result, const char *remote_ad */ void _bt_tds_update_seeker_connection_state_changed(int result, const char *remote_address, bool connected); +/** + * @internal + * @brief Send GATT connection state changed status with remote HRP collector. + */ +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 537472b..8f037d5 100644 --- a/include/bluetooth_type.h +++ b/include/bluetooth_type.h @@ -1708,6 +1708,21 @@ 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. + * + * @details This callback is called when the connection state is changed. + * When you called bt_gatt_connect() or bt_gatt_disconnect(), this callback is also called with error result even though these functions fail. + * + * @since_tizen 4.0 + * @param[in] result The result of changing the connection state. + * @param[in] connected The state to be changed, true means connected state, Otherwise, false. + * @param[in] remote_address The remote_address + * @param[in] user_data The user data passed from the callback registration function. + * + */ +typedef void (*bt_hrp_connection_state_changed_cb)(int result, bool connected, const char *remote_address); /** * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_CLIENT_MODULE @@ -1822,6 +1837,26 @@ typedef void (*bt_gatt_server_read_value_requested_cb) (const char *remote_addre typedef void (*bt_gatt_server_characteristic_notification_state_changed_cb) (bool notify, bt_gatt_server_h server, bt_gatt_h gatt_handle, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE + * @brief Called when the remote device enables or disables the Notification/Indication for particular characteristics for HRP. + * + * @details By using this callback function, server can know notification state. + * + * @since_tizen 3.0 + * @remarks The @a server must not be freed by application. + * @remarks The @a gatt_handle must not be freed by application. + * + * @param[in] notify Indicates whether the Notification/Indication is enabled or not + * @param[in] server The GATT server handle + * @param[in] gatt_handle The characteristic's GATT handle to be read + * @param[in] user_data The user data passed from the registration function + * + */ +typedef void (*bt_hrp_sensor_characteristic_notification_state_changed_cb) (bool notify, + bt_gatt_server_h server, bt_gatt_h gatt_handle, void *user_data); + /** * @ingroup CAPI_NETWORK_BLUETOOTH_GATT_SERVER_MODULE * @brief Called when the sending notification / indication is done. diff --git a/include/bluetooth_type_internal.h b/include/bluetooth_type_internal.h index babfb95..6f3c27e 100644 --- a/include/bluetooth_type_internal.h +++ b/include/bluetooth_type_internal.h @@ -1093,6 +1093,38 @@ typedef void (*bt_otp_client_object_delete_cb) * @} */ +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE + * @brief Enumerations of the Bluetooth advertising state for HRP. + * @since_tizen @if WEARABLE 2.3.1 @else 2.3 @endif + */ +typedef enum { + BT_HRP_SENSOR_ADVERTISING_STOPPED = 0x00, /**< Bluetooth advertising is stopped */ + BT_HRP_SENSOR_ADVERTISING_STARTED, /**< Bluetooth advertising is started */ +} bt_hrp_sensor_advertising_state_e; + +/** + * @internal tizen 4.0 + * @brief HRP Sensor Advertisement state change callback + */ + +typedef void (*bt_hrp_sensor_advertising_state_changed_cb)(int result, + bt_hrp_sensor_advertising_state_e adv_state, void *user_data); + + +/* Body Sensor Enumeration +*/ +typedef enum { + BT_BSL_NOTSUPPORTED = -1, + BT_BSL_OTHER = 0, + BT_BSL_CHEST, + BT_BSL_WRIST, + BT_BSL_FINGER, + BT_BSL_HAND, + BT_BSL_EARLOBE, + BT_BSL_FOOT, +} bt_body_sensor_location_e; + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 9b5110b..5679d2f 100644 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -2062,6 +2062,10 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us if (cb) cb(_bt_get_error_code(param->result), TRUE, device_addr, bt_event_slot_container[event_index].user_data); + + /*HRP Server*/ + __bt_hrp_le_connection_state_changed_cb(param->result, device_addr, TRUE); + g_free(device_addr); device_addr = NULL; break; @@ -2076,6 +2080,10 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us if (cb) cb(_bt_get_error_code(param->result), FALSE, device_addr, bt_event_slot_container[event_index].user_data); + + /*HRP Server*/ + __bt_hrp_le_connection_state_changed_cb(param->result, device_addr, FALSE); + g_free(device_addr); device_addr = NULL; break; @@ -2166,6 +2174,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us /* OTP Client */ _bt_otp_client_connection_state_changed(param->result, device_addr, TRUE); + /*HRP Client*/ + __bt_hrp_le_connection_state_changed_cb(param->result, device_addr, TRUE); + if (device_addr != NULL) free(device_addr); device_addr = NULL; @@ -2197,6 +2208,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us /* OTP Client */ _bt_otp_client_connection_state_changed(param->result, device_addr, FALSE); + /*HRP Client*/ + __bt_hrp_le_connection_state_changed_cb(param->result, device_addr, FALSE); + if (device_addr != NULL) free(device_addr); device_addr = NULL; diff --git a/src/bluetooth-hrp.c b/src/bluetooth-hrp.c new file mode 100644 index 0000000..45eb899 --- /dev/null +++ b/src/bluetooth-hrp.c @@ -0,0 +1,850 @@ +/* + * Bluetooth-frwk + * + * Contact: Abhishek Chandra (abhishek.ch@samsung.com) + * + * Copyright (c) 2018-2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "bluetooth.h" +#include "bluetooth_private.h" +#include "bluetooth_internal.h" + + +#define BT_CHECK_HRS_SUPPORT() \ +{ \ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); \ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE); \ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_HRS); \ +} + +/*====================================================================================================== + Heart Rate Server - Structures +========================================================================================================*/ +#define HEART_RATE_UUID "180d" +#define HEART_RATE_MEASUREMENT_UUID "2a37" +#define BODY_SENSOR_LOCATION_UUID "2a38" +#define HEART_RATE_CONTROL_POINT_UUID "2a39" +#define DEVICE_INFORMATION_UUID "180a" + +#define HEART_RATE_CHARAC_CFG_UUID "2902" +#define DEVICE_INFO_CHARAC_MANUFACTURER_NAME_STRING "2A29" +#define TODO 0 +//Connected Collector List +typedef struct { + char *remote_address; + bool isconnected; +} bt_hrp_collector_notify_info_s; + +//Server Info Local Structure +typedef struct bt_hrp_server_info_s { + //fill with Setter API's + bool is_notify_cb_set; + bool is_hr_value_init; + int hr_value; + bool is_energy_supported; + int energy_value; + bool is_in_contact; + bool is_rr_interval_set; + int rr_interval; + bool is_manuf_name_set; + char *manufname; + bool is_bsl_set; + bt_gatt_server_h hrp_sensor; //Server Created only once + bt_gatt_h hrp_service; //heart rate service + bt_gatt_h dis_service; //device information service + bt_gatt_h hrs_characteristic; // heart rate char + bt_gatt_h dis_characteristic; // device info char + bt_gatt_h hrs_descriptor; // hrs cccd + bt_gatt_h bsl_characteristic; // body sensor location + bt_advertiser_h advertiser; + bt_hrp_sensor_advertising_state_changed_cb adv_app_cb; //application callback for updating state changes + bt_gatt_server_characteristic_notification_state_changed_cb notif_app_cb; //application callback for updating notification + bt_body_sensor_location_e body_sensor_location; //body sensor location + bool cccd_enabled; + GSList *hrs_collector_connected_list; //connected collector list , to be updated when read or write cccd request comes from client +} bt_hrp_server_info_s; + +static guint adv_timer_id; +GSList *sensor_list; +static bt_hrp_server_info_s hrp_server_info_s; + +/*====================================================================================================== + Heart Rate Server - Utility +========================================================================================================*/ + +/*Internal Functions*/ +static void __bt_hrp_sensor_read_value_requested_cb( + const char *remote_address, int request_id, + bt_gatt_server_h server, bt_gatt_h gatt_handle, + int offset, void *user_data) +{ + + BT_INFO("[HR] __bt_gatt_server_read_value_requested_cb"); + BT_INFO("[HR] remote_address %s", remote_address); + BT_INFO("[HR] req_id %d", request_id); + BT_INFO("[HR] server %s", (char *)server); + BT_INFO("[HR] gatt_handle %s", (char *)gatt_handle); + BT_INFO("[HR] Offset %d", offset); + +#if TODO + else { + /* Send Cached response*/ + bt_gatt_server_send_response(request_id, + BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ, offset, + resp_status, char_value_1, 3 - offset); + } +#endif + + +} + + +static void __bt_hrp_sensor_write_value_requested_cb(const char *remote_address, + int request_id, bt_gatt_server_h server, + bt_gatt_h gatt_handle, bool response_needed, int offset, + const char *value, int len, void *user_data) +{ + + BT_INFO("[HR] __bt_gatt_server_read_value_requested_cb"); + BT_INFO("[HR] remote_address %s", remote_address); + BT_INFO("[HR] req_id %d", request_id); + BT_INFO("[HR] server %s", (char *)server); + BT_INFO("[HR] gatt_handle %s", (char *)gatt_handle); + BT_INFO("[HR] Offset %d", offset); + +#if TODO + else { + /* Send Cached response*/ + bt_gatt_server_send_response(request_id, + BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE, offset, + resp_status, char_value_1, 3 - offset); + } +#endif +} + +static void __bt_hrp_notification_send_cb(int result, + const char *remote_address, bt_gatt_server_h server, + bt_gatt_h characteristic, bool completed, void *user_data) +{ + BT_INFO("result [%s]", _bt_convert_error_to_string(result)); + BT_INFO("remote_address : %s", remote_address); + BT_INFO("completed : %d", completed); + BT_INFO("characteristic : %p", characteristic); + +} + +static void __bt_hrp_reduced_interval_adv_state_changed_cb(int result, + bt_advertiser_h advertiser, bt_adapter_le_advertising_state_e adv_state, + void *user_data) +{ + BT_INFO("[HR]Result : %d", result); + BT_INFO("[HR]Advertiser : %p", advertiser); + BT_INFO("[HR]Advertising %s [%d]", + adv_state == BT_ADAPTER_LE_ADVERTISING_STARTED ? + "started" : "stopped", adv_state); + + if (hrp_server_info_s.adv_app_cb && adv_state == BT_ADAPTER_LE_ADVERTISING_STOPPED) + hrp_server_info_s.adv_app_cb(result, adv_state, user_data); +} + +static gboolean __hrp_timeout(gpointer user_data) +{ + int error_code = BT_ERROR_NONE; + + BT_INFO("__hrp_timeout Timeout !!!\n"); + adv_timer_id = -1; + error_code = bt_adapter_le_stop_advertising(hrp_server_info_s.advertiser); + if (error_code != BT_ERROR_NONE) + BT_ERR("[HR]add scan response data [0x%04x]", error_code); + + return FALSE; +} + +static void __bt_hrp_gatt_server_set_char_notification_state_change_cb(bool notify, + bt_gatt_server_h server, bt_gatt_h gatt_handle, + void *user_data) +{ + BT_INFO("[HR]__bt_gatt_server_notification_state_change_cb"); + BT_INFO("[HR]notify %d", notify); + BT_INFO("[HR]server %s", (char *)server); + BT_INFO("[HR]gatt_handle %s", (char *)gatt_handle); + + if (hrp_server_info_s.notif_app_cb) + hrp_server_info_s.notif_app_cb(notify, server, gatt_handle, user_data); + +} + +static void __bt_hrp_fast_interval_adv_state_changed_cb(int result, + bt_advertiser_h advertiser, bt_adapter_le_advertising_state_e adv_state, + void *user_data) +{ + BT_INFO("[HR]Result : %d", result); + BT_INFO("[HR]Advertiser : %p", advertiser); + BT_INFO("[HR]Advertising %s [%d]", + adv_state == BT_ADAPTER_LE_ADVERTISING_STARTED ? + "started" : "stopped", adv_state); + + if (adv_state == BT_ADAPTER_LE_ADVERTISING_STARTED) { + adv_timer_id = + g_timeout_add_seconds(29/*Todo :30 Secs , 29 + time to set mode and restart adv*/, + __hrp_timeout, hrp_server_info_s.hrp_sensor); + } else { /*Advertisement Stopped*/ + //cancel timer as User requested to STOP + if (adv_timer_id != -1) { + BT_DBG("g_source is removed"); + g_source_remove(adv_timer_id); + adv_timer_id = -1; + } else { //Changing mode to Low energy as 30seconds are passed + int error_code = bt_adapter_le_set_advertising_mode(hrp_server_info_s.advertiser, + BT_ADAPTER_LE_ADVERTISING_MODE_LOW_ENERGY); + if (error_code != BT_ERROR_NONE) + BT_ERR("[HR]add scan response data [0x%04x]", error_code); + + error_code = bt_adapter_le_start_advertising_new(hrp_server_info_s.advertiser, + __bt_hrp_reduced_interval_adv_state_changed_cb, NULL); + if (error_code < BT_ERROR_NONE) + BT_ERR("[HR]failed with [0x%04x]", error_code); + + return; + } + } + /*todo : Send Start and stop enums*/ + if (hrp_server_info_s.adv_app_cb) + hrp_server_info_s.adv_app_cb(result, adv_state, user_data); + +} + +static int __bt_hrp_create_primary_service(void) +{ + int error_code = BT_ERROR_NOT_INITIALIZED; + char hrs_char_value[3] ; + char desc_value[2] = {1, 0}; /* Notification enabled ,Indication disabled default*/ + + if (hrp_server_info_s.hrp_sensor == NULL) + return error_code; + + error_code = bt_gatt_service_create(HEART_RATE_UUID, BT_GATT_SERVICE_TYPE_PRIMARY, + &hrp_server_info_s.hrp_service); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]__createPrimaryService : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + hrs_char_value[0] = (hrp_server_info_s.hr_value > 255) ? 1 : 0;//Uint-16 and Uint-8 + hrs_char_value[1] = hrp_server_info_s.hr_value; /*Measurement Value*/ + hrs_char_value[2] = 0; //?? + + BT_INFO("[HR] PRIMARY SERVICE CHAR CREATE\n"); + error_code = bt_gatt_characteristic_create(HEART_RATE_MEASUREMENT_UUID, BT_GATT_PERMISSION_READ, + BT_GATT_PROPERTY_NOTIFY, hrs_char_value, sizeof(hrs_char_value), + &hrp_server_info_s.hrs_characteristic); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_characteristic_create HEART_RATE_MEASUREMENT_UUID : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + BT_INFO("[HR] PRIMARY SERVICE SET READ CB\n"); + + error_code = bt_gatt_service_add_characteristic(hrp_server_info_s.hrp_service, hrp_server_info_s.hrs_characteristic); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_service_add_characteristic : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + BT_INFO("[HR] PRIMARY SERVICE DESCRIPTOR CREATE\n"); + error_code = bt_gatt_descriptor_create(HEART_RATE_CHARAC_CFG_UUID, BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE, + desc_value, sizeof(desc_value), &hrp_server_info_s.hrs_descriptor); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_descriptor_create HEART_RATE_CHARAC_CFG_UUID : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + BT_INFO("[HR] PRIMARY SERVICE ADD DESCRIPTOR\n"); + + error_code = bt_gatt_characteristic_add_descriptor(hrp_server_info_s.hrs_characteristic, hrp_server_info_s.hrs_descriptor); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_characteristic_add_descriptor : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + error_code = bt_gatt_server_set_read_value_requested_cb(hrp_server_info_s.hrs_descriptor, + __bt_hrp_sensor_read_value_requested_cb, NULL); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_set_read_value_requested_cb : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + error_code = bt_gatt_server_set_write_value_requested_cb(hrp_server_info_s.hrs_descriptor, + __bt_hrp_sensor_write_value_requested_cb, NULL); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_set_read_value_requested_cb : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + + BT_INFO("[HR] PRIMARY SERVICE BSL\n"); + + if (hrp_server_info_s.body_sensor_location != BT_BSL_NOTSUPPORTED) { + + char bs_location = hrp_server_info_s.body_sensor_location; + + error_code = bt_gatt_characteristic_create(BODY_SENSOR_LOCATION_UUID, BT_GATT_PERMISSION_READ, BT_GATT_PROPERTY_READ, + &bs_location, sizeof(bs_location), + &hrp_server_info_s.bsl_characteristic); + BT_INFO("[HR] PRIMARY SERVICE BSL SET REQUEST CB\n"); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_characteristic_create BODY_SENSOR_LOCATION_UUID : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + bt_gatt_server_set_read_value_requested_cb(hrp_server_info_s.bsl_characteristic, + __bt_hrp_sensor_read_value_requested_cb, NULL); + + + if ((NULL != hrp_server_info_s.hrp_service) && (hrp_server_info_s.bsl_characteristic != NULL)) { + BT_INFO("[HR] PRIMARY SERVICE BSL ADD CHAR CB\n"); + + error_code = bt_gatt_service_add_characteristic(hrp_server_info_s.hrp_service, hrp_server_info_s.bsl_characteristic); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_service_add_characteristic : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + } + + BT_INFO("[HR] PRIMARY SERVICE REGISTER SERVICE\n"); + + error_code = bt_gatt_server_register_service(hrp_server_info_s.hrp_sensor, hrp_server_info_s.hrp_service); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_register_service : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + } + BT_INFO("[HR] PRIMARY SERVICE EXIT!!!\n"); + + return error_code; +} + +static int __bt_hrp_create_secondary_service(void) +{ + int error_code = BT_ERROR_NOT_INITIALIZED; + + if (hrp_server_info_s.hrp_sensor == NULL) + return error_code; + + error_code = bt_gatt_service_create(DEVICE_INFORMATION_UUID, + BT_GATT_SERVICE_TYPE_SECONDARY, &hrp_server_info_s.dis_service); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_service_create : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + error_code = bt_gatt_characteristic_create(DEVICE_INFO_CHARAC_MANUFACTURER_NAME_STRING, BT_GATT_PERMISSION_READ, + BT_GATT_PROPERTY_READ, hrp_server_info_s.manufname, + strlen(hrp_server_info_s.manufname), &hrp_server_info_s.dis_characteristic); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_characteristic_create : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + bt_gatt_server_set_read_value_requested_cb(hrp_server_info_s.dis_characteristic, + __bt_hrp_sensor_read_value_requested_cb, NULL); + + error_code = bt_gatt_service_add_characteristic(hrp_server_info_s.dis_service, hrp_server_info_s.dis_characteristic); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_service_add_characteristic : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + error_code = bt_gatt_server_set_characteristic_notification_state_change_cb + (hrp_server_info_s.hrs_characteristic, + __bt_hrp_gatt_server_set_char_notification_state_change_cb, NULL); + + if (error_code != BT_ERROR_NONE) + BT_ERR("[HR]bt_gatt_server_set_characteristic_notification_state_change_cb : %s\n", _bt_convert_error_to_string(error_code)); + + error_code = bt_gatt_server_register_service(hrp_server_info_s.hrp_sensor, hrp_server_info_s.dis_service); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_register_service : %s\n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + return error_code; +} + +static int __bt_hrp_sensor_create_service(void) +{ + + int error_code = BT_ERROR_NOT_INITIALIZED; + + if (NULL == hrp_server_info_s.hrp_sensor) { + BT_ERR("[bt_hrp_sensor_create_service] Call Create First !!\n"); + return error_code; + } + + BT_INFO("[HR] CREATE SERVICE PRIMARY \n"); + error_code = __bt_hrp_create_primary_service(); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]__bt_hrp_create_primary_service : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + BT_INFO("[HR] CREATE SERVICE SECONDARY \n"); + error_code = __bt_hrp_create_secondary_service(); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]__bt_hrp_create_secondary_service : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + return error_code; +} + +static void _bt_hrp_sensor_client_info_free(gpointer object) +{ + bt_hrp_collector_notify_info_s *client_s = (bt_hrp_collector_notify_info_s *)object; + g_free(client_s->remote_address); + client_s->isconnected = false; +} + +static void _bt_hrp_sensor_initilize(void) +{ + hrp_server_info_s.is_notify_cb_set = false; + hrp_server_info_s.hrp_sensor = NULL; + hrp_server_info_s.hrp_service = NULL; + hrp_server_info_s.dis_service = NULL; + hrp_server_info_s.hrs_characteristic = NULL; + hrp_server_info_s.dis_characteristic = NULL; + hrp_server_info_s.hrs_descriptor = NULL; + hrp_server_info_s.advertiser = NULL; + hrp_server_info_s.adv_app_cb = NULL; + hrp_server_info_s.hrs_collector_connected_list = NULL; + hrp_server_info_s.is_in_contact = true; + + hrp_server_info_s.cccd_enabled = true; //by default + + if (hrp_server_info_s.is_hr_value_init == false) + hrp_server_info_s.hr_value = 0; + + if (hrp_server_info_s.is_bsl_set == false) + hrp_server_info_s.body_sensor_location = BT_BSL_OTHER; + + if (hrp_server_info_s.is_energy_supported == false) + hrp_server_info_s.energy_value = 0; + + if (hrp_server_info_s.is_rr_interval_set == false) + hrp_server_info_s.rr_interval = 2; //Fill with some default value + + if (hrp_server_info_s.is_manuf_name_set == false) + hrp_server_info_s.manufname = g_strdup("SAMSUNG"); +} + +void __bt_hrp_le_connection_state_changed_cb(int result, + const char *remote_address, bool connected) +{ + + BT_INFO("[HR] bt_hrp_le_connection_state_changed_cb Result : %d", result); + BT_INFO("[HR]IsConnected : %d", connected); + BT_INFO("[HR]Remote Address : %s", remote_address); + bool isappend = true; + int error_code = BT_ERROR_NOT_INITIALIZED; + + 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; + } + } + } + + 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); + } + + 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; + } + +} + +/*Application Interfaces*/ + +int bt_hrp_sensor_set_heartrate_value(int heartrate) +{ + + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + if (heartrate < 0) + return BT_ERROR_INVALID_PARAMETER; + + hrp_server_info_s.hr_value = heartrate; + hrp_server_info_s.is_hr_value_init = true; + + return BT_ERROR_NONE; +} + +int bt_hrp_sensor_set_location_value(bt_body_sensor_location_e location) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + if (location == BT_BSL_NOTSUPPORTED) + return BT_ERROR_INVALID_PARAMETER; + + + hrp_server_info_s.body_sensor_location = location; + hrp_server_info_s.is_bsl_set = true; + + return BT_ERROR_NONE; +} + +int bt_hrp_sensor_set_energy_value(int energy_value) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + if ((energy_value < 0) || (energy_value > 9)) + return BT_ERROR_INVALID_PARAMETER; + + hrp_server_info_s.energy_value = energy_value; + hrp_server_info_s.is_energy_supported = true; + + return BT_ERROR_NOT_SUPPORTED; + +} + +int bt_hrp_sensor_set_contact_value(bool enable) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + hrp_server_info_s.is_in_contact = enable; + + return BT_ERROR_NONE; +} + +int bt_hrp_sensor_set_rr_interval(int interval) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + if ((interval < 0) || (interval > 9)) //Todo : Check for EE support + return BT_ERROR_INVALID_PARAMETER; + + hrp_server_info_s.rr_interval = interval; + hrp_server_info_s.is_rr_interval_set = true; + + return BT_ERROR_NOT_SUPPORTED; +} + +int bt_hrp_sensor_set_device_manufacturer_name(char *manuf_name) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(manuf_name); + + if (hrp_server_info_s.manufname) + g_free(hrp_server_info_s.manufname); + + //Todo : Parsing Logic for manufacturer name . + + hrp_server_info_s.manufname = g_strdup(manuf_name); + hrp_server_info_s.is_manuf_name_set = true; + + return BT_ERROR_NONE; +} + +int bt_hrp_sensor_set_sensor_notification_state_change_cb( + bt_gatt_server_characteristic_notification_state_changed_cb callback, void *user_data) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + + hrp_server_info_s.notif_app_cb = callback; + + return BT_ERROR_NONE; +} + +int bt_hrp_sensor_create(void) +{ + int error_code = BT_ERROR_NONE; + bool is_in_use = false; + + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + error_code = bt_adapter_is_service_used(HEART_RATE_UUID, &is_in_use); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HRP- Sensor Create] bt_adapter_is_service_used : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + if (true == is_in_use) { + BT_ERR("[HRP- Sensor Create] bt_adapter_is_service_used Server Already Created !!"); + return BT_ERROR_ALREADY_DONE; + } + + _bt_hrp_sensor_initilize(); + + error_code = bt_gatt_server_initialize(); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HRP- Sensor Create] Gatt Server Initialize error code : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + error_code = bt_gatt_server_create(&hrp_server_info_s.hrp_sensor); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HRP- Sensor Create] bt_gatt_server_create : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + error_code = __bt_hrp_sensor_create_service(); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HRP- Sensor Create] __bt_hrp_sensor_create_service : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + return error_code; +} + +int bt_hrp_sensor_start(bt_hrp_sensor_advertising_state_changed_cb cb) +{ + int error_code = BT_ERROR_NOT_INITIALIZED; + + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(cb); + + if (NULL == hrp_server_info_s.hrp_sensor) { + BT_ERR("[HR Sensor START] Call Create First !!\n"); + return error_code; + } + + BT_INFO("[HR] START GATT SERVER \n"); + error_code = bt_gatt_server_start(); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_start : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + + if (hrp_server_info_s.advertiser == NULL) { + + error_code = bt_adapter_le_create_advertiser(&hrp_server_info_s.advertiser); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR Sensor START] bt_adapter_le_create_advertiser : %s \n", _bt_convert_error_to_string(error_code)); + return error_code; + } + } else { + + error_code = bt_adapter_le_clear_advertising_data(hrp_server_info_s.advertiser, + BT_ADAPTER_LE_PACKET_ADVERTISING); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR Sensor START] clear advertising data [0x%04x]", error_code); + return error_code; + } + error_code = bt_adapter_le_clear_advertising_data(hrp_server_info_s.advertiser, + BT_ADAPTER_LE_PACKET_SCAN_RESPONSE); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR Sensor START] clear scan response data [0x%04x]", error_code); + return error_code; + } + } + + error_code = bt_adapter_le_add_advertising_service_solicitation_uuid(hrp_server_info_s.advertiser, + BT_ADAPTER_LE_PACKET_ADVERTISING, HEART_RATE_UUID); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR Sensor START] add service_solicitation_uuid [0x%04x]", error_code); + return error_code; + } + + error_code = bt_adapter_le_set_advertising_device_name(hrp_server_info_s.advertiser, + BT_ADAPTER_LE_PACKET_ADVERTISING, true); + + if (error_code != BT_ERROR_NONE) + BT_ERR("[HR Sensor START] set device name [0x%04x]", error_code); + + + /*interval = 150*/ + error_code = bt_adapter_le_set_advertising_mode(hrp_server_info_s.advertiser, BT_ADAPTER_LE_ADVERTISING_MODE_LOW_LATENCY); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR Sensor START] add scan response data [0x%04x]", error_code); + return error_code; + } + + hrp_server_info_s.adv_app_cb = cb; + + error_code = bt_adapter_le_set_advertising_device_name(hrp_server_info_s.advertiser, + BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true); + + if (error_code != BT_ERROR_NONE) + BT_ERR("[HR Sensor START] set device name [0x%04x]", error_code); + + error_code = bt_adapter_le_start_advertising_new(hrp_server_info_s.advertiser, + __bt_hrp_fast_interval_adv_state_changed_cb, NULL); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR Sensor START] failed with [0x%04x]", error_code); + return error_code; + } + + BT_INFO("[HR Sensor START] bt_hrp_sensor_start exit\n"); + return error_code; + +} + +int bt_hrp_sensor_stop() +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + int error_code = BT_ERROR_NOT_INITIALIZED; + + error_code = bt_adapter_le_stop_advertising(hrp_server_info_s.advertiser); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_hrp_sensor_stop failed with [0x%04x]", error_code); + return error_code; + } + + return error_code; + +} + +int bt_hrp_sensor_update_heartrate_value(int heartrate) +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + int error_code = BT_ERROR_NOT_INITIALIZED; + + if (NULL == hrp_server_info_s.hrp_sensor) { + BT_ERR("[HR Sensor START] Call Create First !!\n"); + return error_code; + } + + if (hrp_server_info_s.cccd_enabled) { + error_code = bt_gatt_set_int_value(hrp_server_info_s.hrs_characteristic, + BT_DATA_TYPE_UINT16, heartrate, 1); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_set_int_value failed with [0x%04x]", error_code); + return error_code; + } + } + + return error_code; + +} + +int bt_hrp_sensor_destroy() +{ + BT_CHECK_HRS_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + BT_INFO("[HR]bt_gatt_server_destroy GATT Destroy\n"); + + int error_code = BT_ERROR_NOT_INITIALIZED; + bt_gatt_destroy(hrp_server_info_s.hrs_descriptor); + bt_gatt_destroy(hrp_server_info_s.hrs_characteristic); + bt_gatt_destroy(hrp_server_info_s.dis_characteristic); + bt_gatt_destroy(hrp_server_info_s.bsl_characteristic); + bt_gatt_destroy(hrp_server_info_s.dis_service); + bt_gatt_destroy(hrp_server_info_s.hrp_service); + + BT_INFO("[HR]bt_gatt_server_destroy Advertiser Destroy\n"); + + error_code = bt_adapter_le_destroy_advertiser(hrp_server_info_s.advertiser); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_hrp_sensor_stop failed with [0x%04x]", error_code); + return error_code; + } + + BT_INFO("[HR]bt_gatt_server_destroy Server Destroy\n"); + + error_code = bt_gatt_server_destroy(hrp_server_info_s.hrp_sensor); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_destroy failed with [0x%04x]", error_code); + return error_code; + } + + BT_INFO("[HR]bt_gatt_server_destroy Server Deinit\n"); + + error_code = bt_gatt_server_deinitialize(); + if (error_code != BT_ERROR_NONE) { + BT_ERR("[HR]bt_gatt_server_destroy failed with [0x%04x]", error_code); + return error_code; + } + + hrp_server_info_s.is_notify_cb_set = false; + hrp_server_info_s.is_hr_value_init = false; + hrp_server_info_s.hr_value = 0; + hrp_server_info_s.is_energy_supported = false; + hrp_server_info_s.energy_value = 0; + hrp_server_info_s.is_in_contact = false; + hrp_server_info_s.is_rr_interval_set = false; + hrp_server_info_s.rr_interval = 0; + hrp_server_info_s.is_manuf_name_set = false; + hrp_server_info_s.is_bsl_set = false; + hrp_server_info_s.hrp_service = NULL; + hrp_server_info_s.dis_service = NULL; + hrp_server_info_s.bsl_characteristic = NULL; + hrp_server_info_s.dis_characteristic = NULL; + hrp_server_info_s.hrs_characteristic = NULL; + hrp_server_info_s.hrs_descriptor = NULL; + hrp_server_info_s.advertiser = NULL; + + if (hrp_server_info_s.manufname) + g_free(hrp_server_info_s.manufname); + + hrp_server_info_s.adv_app_cb = NULL; + hrp_server_info_s.notif_app_cb = NULL; + hrp_server_info_s.body_sensor_location = BT_BSL_NOTSUPPORTED; + hrp_server_info_s.cccd_enabled = false; + + g_slist_free_full(hrp_server_info_s.hrs_collector_connected_list, _bt_hrp_sensor_client_info_free); + + hrp_server_info_s.hrs_collector_connected_list = NULL; + + BT_INFO("[HR]bt_gatt_server_destroy Exit\n"); + + + return error_code; + +} + diff --git a/test/bt_unit_test.c b/test/bt_unit_test.c index 7547b95..51c4a69 100644 --- a/test/bt_unit_test.c +++ b/test/bt_unit_test.c @@ -182,6 +182,8 @@ tc_table_t tc_main[] = { , BT_UNIT_TEST_TABLE_TDS_SEEKER}, {"OTP" , BT_UNIT_TEST_TABLE_OTP}, + {"HRS" + , BT_UNIT_TEST_TABLE_HR_SENSOR}, {"Initialize All" , BT_UNIT_TEST_FUNCTION_INITIALIZE_ALL}, {"FINISH" @@ -1158,6 +1160,40 @@ tc_table_t tc_otp[] = { {NULL , 0x0000}, }; +tc_table_t tc_hr_sensor[] = { + /* HR Sensor functions */ + {"BACK" + , BT_UNIT_TEST_FUNCTION_BACK}, + {"[sensor]Set HeartRate Value" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_HR_VALUE}, + {"[sensor]Set Location Value" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_LOC_VALUE}, + {"[sensor]Set Contact Value" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_CONTACT_VALUE}, + {"[sensor]Set Device Name" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_DEVICE_NAME}, + {"[sensor]Set Notification Callback" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_NOTIF_CB}, + {"[sensor]Set Read Callback" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_READ_CB}, + {"[sensor]Set Send Notification Callback" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_SEND_NOTIF_CB}, + {"HR Sensor Create Instance" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_CREATE}, + {"HR Sensor Start Advertising" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_START}, + {"HR Sensor Stop Advertising" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_STOP}, + {"HR Sensor SET Notify" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_NOTIFY}, + {"HR Sensor Notify" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_NOTIFY}, + {"HR Sensor Destroy" + , BT_UNIT_TEST_FUNCTION_HR_SENSOR_DESTORY}, + {NULL , 0x0000}, +}; + + tc_table_t tc_automated_test[] = { /* Automated test Functions*/ {"BACK" , BT_UNIT_TEST_FUNCTION_BACK}, @@ -1267,6 +1303,9 @@ void tc_usage_print(void) case BT_UNIT_TEST_TABLE_OTP: tc_table = tc_otp; break; + case BT_UNIT_TEST_TABLE_HR_SENSOR: + tc_table = tc_hr_sensor; + break; case BT_UNIT_TEST_TABLE_MAIN: __default__: default: @@ -3167,6 +3206,16 @@ static void __bt_otp_client_object_delete_cb(int result, const char *remote_addr BT_ERR("Object[%llu] delete failed!", obj_id); } +static void __bt_adapter_hrp_sensor_adv_state_cb(int result, + bt_hrp_sensor_advertising_state_e adv_state, void *user_data) +{ + TC_PRT("[HR]Result : %d", result); + TC_PRT("[HR]Advertiser : %p", advertiser); + TC_PRT("[HR]Advertising %s [%d]", + adv_state == BT_HRP_SENSOR_ADVERTISING_STARTED ? + "started" : "stopped", adv_state); +} + static void __bt_initialize_all(void) { int ret; @@ -9435,6 +9484,73 @@ int test_input_callback(void *data) break; } break; + } + case BT_UNIT_TEST_TABLE_HR_SENSOR: { + switch (test_id) { + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_HR_VALUE: { + TC_PRT("HR SENSOR SET HR VALUE\n"); + int heartrate = 0x38; + bt_hrp_sensor_set_heartrate_value(heartrate); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_LOC_VALUE: { + TC_PRT("HR SENSOR SET LOC VALUE\n"); + bt_body_sensor_location_e location = BT_BSL_WRIST; + bt_hrp_sensor_set_location_value(location); + + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_CONTACT_VALUE: { + TC_PRT("HR SENSOR SET CONTACT VALUE\n"); + bool iscontact = true; + bt_hrp_sensor_set_contact_value(iscontact); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_DEVICE_NAME: { + TC_PRT("HR SENSOR SET DEVICE NAME\n"); + char *name = g_strdup("SAMSUNG HR"); + bt_hrp_sensor_set_device_manufacturer_name(name); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_NOTIF_CB: { + TC_PRT("HR SENSOR SET NOTIFICATION CALLBACK\n"); + bt_hrp_sensor_set_sensor_notification_state_change_cb( + __bt_gatt_server_notification_state_change_cb, NULL); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_CREATE: { + TC_PRT("HR SENSOR CREATE\n"); + ret = bt_hrp_sensor_create(); + TC_PRT("returns %s\n", __bt_get_error_message(ret)); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_START: { + TC_PRT("HR SENSOR START\n"); + ret = bt_hrp_sensor_start(__bt_adapter_hrp_sensor_adv_state_cb); + TC_PRT("returns %s\n", __bt_get_error_message(ret)); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_STOP: { + TC_PRT("HR SENSOR STOP\n"); + ret = bt_hrp_sensor_stop(); + TC_PRT("returns %s\n", __bt_get_error_message(ret)); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_NOTIFY: { + TC_PRT("HR SENSOR UPDATE HR value\n"); + bt_hrp_sensor_update_heartrate_value(7); + break; + } + case BT_UNIT_TEST_FUNCTION_HR_SENSOR_DESTORY: { + TC_PRT("HR SENSOR DESTROY\n"); + ret = bt_hrp_sensor_destroy(); + TC_PRT("returns %s\n", __bt_get_error_message(ret)); + break; + } + default: + break; + } + break; } case BT_UNIT_TEST_TABLE_ETC: { static unsigned int delay = 0; diff --git a/test/bt_unit_test.h b/test/bt_unit_test.h index f2ec69e..bfdb286 100644 --- a/test/bt_unit_test.h +++ b/test/bt_unit_test.h @@ -54,6 +54,7 @@ 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_FINISH = 0xFF, } bt_unit_test_table_e; @@ -514,6 +515,22 @@ typedef enum { BT_UNIT_TEST_FUNCTION_OTP_CLIENT_EXECUTE_OBJ, BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DELETE_OBJ, + /*HR-Sensor*/ + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_HR_VALUE = 1, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_LOC_VALUE, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_CONTACT_VALUE, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_DEVICE_NAME, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_NOTIF_CB, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_READ_CB, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_SEND_NOTIF_CB, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_CREATE, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_START, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_STOP, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_SET_NOTIFY, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_NOTIFY, + BT_UNIT_TEST_FUNCTION_HR_SENSOR_DESTORY, + + BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS = 0XFF, } bt_unit_test_function_e;