diff options
author | DoHyun Pyun <dh79.pyun@samsung.com> | 2016-08-23 17:07:52 +0900 |
---|---|---|
committer | DoHyun Pyun <dh79.pyun@samsung.com> | 2016-08-23 17:07:52 +0900 |
commit | e46c73af5755926004e4a6dc5a3eb5399fffdb1c (patch) | |
tree | 2c05b868b1dfca8b2b6ee90fe5fbc3374b651948 | |
parent | a10642793e3a3d30fe2c8cc97739dcd0834be154 (diff) | |
download | bluetooth-e46c73af5755926004e4a6dc5a3eb5399fffdb1c.tar.gz bluetooth-e46c73af5755926004e4a6dc5a3eb5399fffdb1c.tar.bz2 bluetooth-e46c73af5755926004e4a6dc5a3eb5399fffdb1c.zip |
Merge the code from private
branch:devel/bluetooth/master
=================================================
commit 590b9e2b91ffb859bab635544f2656f5d9286dee
Author: Deokhyun Kim <dukan.kim@samsung.com>
Date: Wed Jul 27 16:23:38 2016 +0900
[bt_unit_test] Apply g_timeout_add instead of sleep
==================================================
Change-Id: Ib3e675c73ad7820d4aadcedd6b1f7f75d1349a47
Signed-off-by: DoHyun Pyun <dh79.pyun@samsung.com>
-rw-r--r-- | include/bluetooth_private.h | 313 | ||||
-rw-r--r-- | include/mobile/bluetooth_type_internal.h | 46 | ||||
-rw-r--r-- | include/wearable/bluetooth_type_internal.h | 45 | ||||
-rw-r--r-- | src/bluetooth-adapter.c | 478 | ||||
-rw-r--r-- | src/bluetooth-audio.c | 104 | ||||
-rw-r--r-- | src/bluetooth-avrcp.c | 38 | ||||
-rw-r--r-- | src/bluetooth-common.c | 634 | ||||
-rw-r--r-- | src/bluetooth-device.c | 294 | ||||
-rw-r--r-- | src/bluetooth-gatt.c | 645 | ||||
-rw-r--r-- | src/bluetooth-hid.c | 27 | ||||
-rw-r--r-- | src/bluetooth-socket.c | 13 | ||||
-rw-r--r-- | test/bt_unit_test.c | 28 |
12 files changed, 2304 insertions, 361 deletions
diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index b0686b1..473291e 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -99,7 +99,9 @@ typedef enum { BT_EVENT_HID_DEVICE_DATA_RECEIVED, /**< HID Device Data received callback */ BT_EVENT_DEVICE_CONNECTION_STATUS, /**< Device connection status callback */ BT_EVENT_GATT_CONNECTION_STATUS, /** < GATT connection status callback */ + BT_EVENT_GATT_ATT_MTU_CHANGE_STATUS, /** < GATT Attribute MTU change status callback */ BT_EVENT_GATT_CLIENT_SERVICE_DISCOVERED, /** GATT services discovered callback */ + BT_EVENT_GATT_CLIENT_SERVICE_CHANGED, /** GATT services changed callback */ BT_EVENT_GATT_CLIENT_VALUE_CHANGED, /**< GATT characteristic value changed callback */ BT_EVENT_GATT_CLIENT_READ_CHARACTERISTIC, /**< GATT characteristic value read callback */ BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC, /**< GATT characteristic value write callback */ @@ -118,10 +120,13 @@ typedef enum { BT_EVENT_LE_DATA_LENGTH_CHANGED, /** LE data length changed callback */ BT_EVENT_ADVERTISING_STATE_CHANGED, /**< Advertising state changed callback */ BT_EVENT_MANUFACTURER_DATA_CHANGED, /**< Manufacturer data changed callback */ + BT_EVENT_PASSKEY_NOTIFICATION_EVENT, /**< Display passkey callback */ BT_EVENT_CONNECTABLE_CHANGED_EVENT, /**< Adapter connectable changed callback */ BT_EVENT_RSSI_ENABLED_EVENT, /**< RSSI Enabled callback */ BT_EVENT_RSSI_ALERT_EVENT, /**< RSSI Alert callback */ BT_EVENT_GET_RSSI_EVENT, /**< Get RSSI Strength callback */ + BT_EVENT_LE_READ_MAXIMUM_DATA_LENGTH, /**< Read maximun LE data length callback */ + BT_EVENT_SUPPORTED_TRUSTED_PROFILE_EVENT, /**< Trusted Profile callback */ #ifdef TIZEN_WEARABLE BT_EVENT_PBAP_CONNECTION_STATUS, /**< PBAP connection status callback */ BT_EVENT_PBAP_PHONEBOOK_SIZE, /**< PBAP Phonebook Size status callback */ @@ -135,6 +140,8 @@ typedef enum { BT_EVENT_HF_VENDOR_DEP_CMD_EVENT, /**< Audio - HF Vendor Command callback */ BT_EVENT_HF_MULTI_CALL_HANDLING_EVENT, /**< Audio - HF 3-way call event callback */ BT_EVENT_HF_CALL_STATUS_UPDATED_EVENT, /**< Audio - HF call status updated callback */ + BT_EVENT_HF_REMOTE_CALL_EVENT, /**< Audio - HF : call state event callback */ + BT_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED, /**< Audio - HF : device state changed callback */ #endif BT_EVENT_MAX } bt_event_e; @@ -194,6 +201,90 @@ typedef enum { /** * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Called when trying to be displayed the passkey. + * @since_tizen 3.0 + * + * @param[in] remote_address The address of remote device + * @param[in] passkey The passkey to be paired with remote device + * @param[in] user_data The user data passed from the callback registration function + * @pre This function will be invoked when trying to be displayed the passkey + * if callback is registered using bt_adapter_set_passkey_notification(). + * @see bt_adapter_set_passkey_notification() + * @see bt_adapter_unset_passkey_notification() + */ +typedef void (*bt_adapter_passkey_notification_cb)(const char *remote_address, const char *passkey, void *user_data); + +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Registers a callback function to be invoked + * when trying to be displayed the passkey. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/bluetooth.admin + * + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_PERMISSION_DENIED Permission denied + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @pre The Bluetooth service must be initialized with bt_initialize(). + * @post bt_adapter_passkey_notification_cb() will be invoked. + * + * @see bt_initialize() + */ +int bt_adapter_set_passkey_notification(bt_adapter_passkey_notification_cb callback, void *user_data); + +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @privlevel platform + * @privilege %http://tizen.org/privilege/bluetooth.admin + * + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_NOT_INITIALIZED Not initialized + * @retval #BT_ERROR_PERMISSION_DENIED Permission denied + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @pre The Bluetooth service must be initialized with bt_initialize(). + * + * @see bt_initialize() + * @see bt_adapter_set_passkey_notification() + */ +int bt_adapter_unset_passkey_notification(void); + +typedef enum { + BT_GATT_CLIENT_SERVICE_ADDED, + BT_GATT_CLIENT_SERVICE_REMOVED, +} bt_gatt_client_service_change_type_e; + +typedef void (*bt_gatt_client_service_changed_cb) (bt_gatt_client_h client, + bt_gatt_client_service_change_type_e change_type, + const char* service_uuid, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Enumerations of the Bluetooth device's LE connection mode. + * @since_tizen 3.0 + */ +typedef enum +{ + BT_DEVICE_LE_CONNECTION_MODE_BALANCED, /**< Balanced mode of power consumption and connection latency */ + BT_DEVICE_LE_CONNECTION_MODE_LOW_LATENCY, /**< Low connection latency but high power consumption */ + BT_DEVICE_LE_CONNECTION_MODE_LOW_ENERGY, /**< Low power consumption but high connection latency */ +} bt_device_le_connection_mode_e; + +/** + * @internal */ typedef struct { bt_adapter_le_advertising_mode_e mode; @@ -252,6 +343,10 @@ typedef struct { GSList *services; char *remote_address; bool services_discovered; + bool connected; + + bt_gatt_client_service_changed_cb service_changed_cb; + void *service_changed_user_data; } bt_gatt_client_s; typedef struct { @@ -275,6 +370,9 @@ typedef struct { GSList *included_services; GSList *characteristics; + + char **include_handles; + char **char_handles; } bt_gatt_service_s; typedef struct { @@ -290,6 +388,8 @@ typedef struct { GSList *descriptors; + char **desc_handles; + bt_gatt_client_characteristic_value_changed_cb value_changed_cb; void *value_changed_user_data; @@ -340,9 +440,156 @@ typedef struct { bt_gatt_client_request_completed_cb cb; } bt_gatt_client_cb_data_s; +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Attribute protocol MTU change information structure. + * @since_tizen 3.0 + * + * @see bt_device_att_mtu_changed_cb() + */ +typedef struct { + char *remote_address; /**< The address of remote device */ + unsigned int mtu; /** < MTU value */ + unsigned int status; /** < request status*/ +} bt_device_att_mtu_info_s; + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Called when the connection state is changed. + * @since_tizen 2.3.1 + * + * @param[in] connected The connection status: (@c true = connected, @c false = disconnected) + * @param[in] conn_info The connection information + * @param[in] user_data The user data passed from the callback registration function + * @see bt_device_set_connection_state_changed_cb() + * @see bt_device_unset_connection_state_changed_cb() + */ +typedef void (*bt_device_att_mtu_changed_cb)(int result, bt_device_att_mtu_info_s *mtu_info, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Called when RSSI monitoring is enabled. + * @since_tizen 3.0 + * + * @param[in] remote_address Remote Device address + * @param[in] link_type Link type for the connection (@c 0 = BR/EDR link, @c 1 = LE link). + * @param[in] rssi_enabled RSSI monitoring status (@c 1 = enabled, @c 0 = disabled) + * @param[in] user_data The user data passed from the callback registration function + * @see bt_device_enable_rssi_monitor() + * @see bt_device_disable_rssi_monitor() + */ +typedef void (*bt_rssi_monitor_enabled_cb)(const char *remote_address, + bt_device_connection_link_type_e link_type, + int rssi_enabled, void *user_data); + + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Called when RSSI Alert is received. + * @since_tizen 3.0 + * + * @param[in] remote_address Remote Device address + * @param[in] link_type Link type for the connection (@c 0 = BR/EDR link, @c 1 = LE link). + * @param[in] rssi_alert_type RSSI Alert type (@c 1 = High Alert (In-Range Alert), @c 2 = Low Alert) + * @param[in] rssi_alert_dbm RSSI Alert signal strength value + * @param[in] user_data The user data passed from the callback registration function + * @see bt_device_enable_rssi_monitor() + * @see bt_device_disable_rssi_monitor() + */ +typedef void (*bt_rssi_alert_cb)(char *bt_address, + bt_device_connection_link_type_e link_type, + int rssi_alert_type, int rssi_alert_dbm, void *user_data); + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Called when Raw RSSI signal strength is received. + * @since_tizen 3.0 + * + * @param[in] remote_address Remote Device address + * @param[in] link_type Link type for the connection (@c 0 = BR/EDR link, @c 1 = LE link). + * @param[in] rssi_dbm Raw RSSI signal strength value + * @param[in] user_data The user data passed from the callback registration function + * @see bt_device_get_rssi_strength() + */ +typedef void (*bt_rssi_strength_cb)(char *bt_address, + bt_device_connection_link_type_e link_type, + int rssi_dbm, void *user_data); + + typedef void (*_bt_gatt_client_value_changed_cb)(char *char_path, unsigned char *value, int value_length, void *user_data); +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Enumaration for the address type field in manufactrer specific data + * @since_tizen 3.0 + */ +typedef enum { + ADDRESS_NONE_TYPE = 0x00, + WI_FI_P2P_ADDRESS = 0x01, + BLUETOOTH_ADDRESS = 0x02, + INDICATION_ADDRESS = 0x04, + IPV4_ADDRESS = 0x08, + IPV6_ADDRESS = 0x10, + UNKNOWN_ADDRESS = 0xff +} connectivity_address_t; + +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Enumaration for the proximity locality type field in manufactrer specific data + * @since_tizen 3.0 + */ +typedef enum { + NONE_TYPE = 0x00, + PROXIMITY = 0x01, + CO_PRESENCE = 0x02, + UNKNOWN_TYPE= 0xff +} bt_proximity_locality_t; + +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Structure of samsung specific manufacturer data + * @since_tizen 3.0 + */ +typedef struct { + unsigned char version; + unsigned char service_id; + unsigned char discovery_version; + unsigned char associated_service_id; + bt_proximity_locality_t proximity_locality_type; + unsigned char proximity_locality_info; + unsigned char device_type; + unsigned char device_icon; + unsigned char auth_info[5]; + connectivity_address_t addr_type; + unsigned char addr1[6]; + unsigned char addr2[6]; + unsigned char channel_info; + unsigned char associated_service_data_len; + unsigned char *associated_service_data_val; + char *name; +} bt_manufacturer_data; + +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Called when trying to be displayed the passkey. + * @since_tizen 3.0 + * + * @param[in] remote_address The address of remote device + * @param[in] passkey The passkey to be paired with remote device + * @param[in] user_data The user data passed from the callback registration function + * @pre This function will be invoked when trying to be displayed the passkey + * if callback is registered using bt_adapter_set_passkey_notification(). + * @see bt_adapter_set_passkey_notification() + * @see bt_adapter_unset_passkey_notification() + */ +typedef void (*bt_adapter_passkey_notification_cb)(const char *remote_address, const char *passkey, void *user_data); + + #define BT_CHECK_INPUT_PARAMETER(arg) \ if (arg == NULL) { \ LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, BT_ERROR_INVALID_PARAMETER); \ @@ -486,6 +733,12 @@ char *_bt_convert_error_to_string(int error); /** * @internal + * @brief Convert uuid to uuid128 + */ +char* _bt_convert_uuid_to_uuid128(const char *uuid); + +/** + * @internal * @brief Convert the visibility mode */ bt_adapter_visibility_mode_e _bt_get_bt_visibility_mode_e(bluetooth_discoverable_mode_t mode); @@ -498,6 +751,32 @@ void _bt_audio_event_proxy(int event, bt_audio_event_param_t *param, void *user_ #ifdef TIZEN_WEARABLE /** + * @ingroup CAPI_NETWORK_BLUETOOTH_AUDIO_HF_MODULE + * @brief Enumerations for the device state event from Audio-Gateway device + * @since_tizen 3.0 + */ +typedef enum { + BT_HF_REMOTE_DEVICE_STATE_BATTERY_LEVEL = 0x00, /**< Battery charge level of AG (ranges from 0 to 5) */ + BT_HF_REMOTE_DEVICE_STATE_SIGNAL_STRENGTH, /**< Signal strength level of AG (ranges from 0 to 5) */ + BT_HF_REMOTE_DEVICE_STATE_NETWORK_SERVICE, /**< Network service availability (0:no service , 1:available) */ + BT_HF_REMOTE_DEVICE_STATE_VOICE_RECOGNITON, /**< Voice Recognition State (0:disabled , 1:enabled) */ +} bt_hf_remote_device_state_e; + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_AUDIO_HF_MODULE + * @brief Called when a device status changed event happend from Audio-Gateway device + * @since_tizen 3.0 + * + * @param[in] event The device state chagned event from remote Audio-Gateway device + * @param[in] value The new values to be changed. + * @param[in] user_data The user data passed from the callback registration function + * + * @see bt_hf_set_remote_device_state_changed_cb() + * @see bt_hf_unset_remote_device_state_changed_cb() + */ +typedef void (*bt_hf_remote_device_state_changed_cb) (bt_hf_remote_device_state_e state, int value, void *user_data); + +/** * @internal * @brief Since the HF call back and event proxy call backs have different prototype it is wrapper function. */ @@ -528,11 +807,39 @@ void _bt_adapter_le_invoke_advertising_state_cb(int handle, int result, bt_adapt bool _bt_gatt_is_legacy_client_mode(void); #endif -const GSList *_bt_gatt_get_client_list(void); -const GSList *_bt_gatt_get_server_list(void); +/** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_MODULE + * @brief Gets the specification name from the UUID + * @since_tizen 3.0 + * + * @remarks @a name must be released with free() by you. + * + * @param[in] uuid The UUID + * @param[out] name The specification name which defined from www.bluetooth.org + * @return 0 on success, otherwise a negative error value. + * @retval #BT_ERROR_NONE Successful + * @retval #BT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #BT_ERROR_NOT_SUPPORTED Not supported + * + * @see bt_gatt_get_uuid() + */ +int bt_get_uuid_name(const char *uuid, char **name); + +bt_gatt_client_h _bt_gatt_get_client(const char *remote_addr); + +const GSList* _bt_gatt_get_server_list(void); + +bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, const char *path); + +int _bt_gatt_client_update_services(bt_gatt_client_h client); + +int _bt_gatt_client_update_include_services(bt_gatt_h service); + +int _bt_gatt_client_update_characteristics(bt_gatt_h service); -int _bt_gatt_client_update_all(bt_gatt_client_h client); +int _bt_gatt_client_update_descriptors(bt_gatt_h characteristic); /** * @ingroup CAPI_NETWORK_BLUETOOTH_LE_MODULE diff --git a/include/mobile/bluetooth_type_internal.h b/include/mobile/bluetooth_type_internal.h index 1a09f63..55b7555 100644 --- a/include/mobile/bluetooth_type_internal.h +++ b/include/mobile/bluetooth_type_internal.h @@ -155,6 +155,21 @@ typedef void (*bt_adapter_manufacturer_data_changed_cb) (char *data, int len, void *user_data); /** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Called repeatedly when you get the devices connected with specific profile. + * @since_tizen 3.0 + * + * @param[in] remote_address The address of remote device + * @param[in] user_data The user data passed from the callback registration function + * @return @c true to continue with the next iteration of the loop, + * \n @c false to break out of the loop. + * @pre bt_adapter_foreach_profile_connected_devices() will invoke this function. + * @see bt_adapter_foreach_profile_connected_devices() + */ +typedef bool (*bt_adapter_profile_connected_devices_cb)(const char *remote_address, void *user_data); + +/** * @ingroup CAPI_NETWORK_BLUETOOTH_DPM_MODULE * @brief DPM BT allowance state * @since_tizen 3.0 @@ -363,6 +378,37 @@ typedef void (*bt_hid_device_connection_state_changed_cb) (int result, typedef void (*bt_hid_device_data_received_cb)(const bt_hid_device_received_data_s *data, void *user_data); /** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Trusted Profile enumeration. + * @since_tizen 3.0 + * + * @see bt_device_set_profile_trusted() + * @see bt_device_get_profile_trusted() + */ +typedef enum { + BT_TRUSTED_PROFILE_PBAP = 1, + BT_TRUSTED_PROFILE_MAP, + BT_TRUSTED_PROFILE_SAP, + BT_TRUSTED_PROFILE_ALL = 0xFFFFFFFF, +} bt_trusted_profile_t; + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Called when Trusted Profiles is changed. + * @since_tizen 3.0 + * + * @param[in] result The result of supported profile callback + * @param[in] remote_address Address of remote device + * @param[in] trusted_profiles Trusted profile FLAG + * @param[in] user_data The user data passed from the callback registration function + * @see bt_device_set_trusted_profile_cb() + * @see bt_device_unset_trusted_profile_cb() + */ +typedef void (*bt_device_trusted_profiles_cb) + (int result, char *remote_address, int trusted_profile, bool supported, bool trusted,void *user_data); + + +/** * @internal * @ingroup * @brief IPSP Init state changed callback diff --git a/include/wearable/bluetooth_type_internal.h b/include/wearable/bluetooth_type_internal.h index ac4fe1a..a8a68f6 100644 --- a/include/wearable/bluetooth_type_internal.h +++ b/include/wearable/bluetooth_type_internal.h @@ -226,6 +226,21 @@ typedef void (*bt_adapter_manufacturer_data_changed_cb) (char *data, int len, void *user_data); /** + * @internal + * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE + * @brief Called repeatedly when you get the devices connected with specific profile. + * @since_tizen 3.0 + * + * @param[in] remote_address The address of remote device + * @param[in] user_data The user data passed from the callback registration function + * @return @c true to continue with the next iteration of the loop, + * \n @c false to break out of the loop. + * @pre bt_adapter_foreach_profile_connected_devices() will invoke this function. + * @see bt_adapter_foreach_profile_connected_devices() + */ +typedef bool (*bt_adapter_profile_connected_devices_cb)(const char *remote_address, void *user_data); + +/** * @ingroup CAPI_NETWORK_BLUETOOTH_AUDIO_HF_MODULE * @brief Called when the SCO(Synchronous Connection Oriented link) state is changed. * @since_tizen 2.3 @@ -380,6 +395,36 @@ typedef struct { } bt_dpm_uuids_list_s; /** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Trusted Profile enumeration. + * @since_tizen 3.0 + * + * @see bt_device_set_profile_trusted() + * @see bt_device_get_profile_trusted() + */ +typedef enum { + BT_TRUSTED_PROFILE_PBAP = 1, + BT_TRUSTED_PROFILE_MAP, + BT_TRUSTED_PROFILE_SAP, + BT_TRUSTED_PROFILE_ALL = 0xFFFFFFFF, +} bt_trusted_profile_t; + +/** + * @ingroup CAPI_NETWORK_BLUETOOTH_DEVICE_MODULE + * @brief Called when Trusted Profiles is changed. + * @since_tizen 3.0 + * + * @param[in] result The result of supported profile callback + * @param[in] remote_address Address of remote device + * @param[in] trusted_profiles Trusted profile FLAG + * @param[in] user_data The user data passed from the callback registration function + * @see bt_device_set_trusted_profile_cb() + * @see bt_device_unset_trusted_profile_cb() + */ +typedef void (*bt_device_trusted_profiles_cb) + (int result, char *remote_address, int trusted_profile, bool supported, bool trusted,void *user_data); + +/** * @internal * @brief IPSP Init state changed callback */ diff --git a/src/bluetooth-adapter.c b/src/bluetooth-adapter.c index 4f09730..9ea349b 100644 --- a/src/bluetooth-adapter.c +++ b/src/bluetooth-adapter.c @@ -285,6 +285,11 @@ int bt_adapter_get_local_info(char **chipset, char **firmware, goto ERROR; } info_size = info_end - info_start - 1; + if (info_size < 0) { + BT_ERR("info_size is invalid(%d)", info_size); + ret = BT_ERROR_OPERATION_FAILED; + goto ERROR; + } local_firmware = (char *)malloc(sizeof(char) *(info_size + 1)); if (local_firmware == NULL) { @@ -733,6 +738,69 @@ int bt_adapter_is_service_used(const char *service_uuid, bool *used) return ret; } +int bt_adapter_foreach_profile_connected_devices(const char *profile_uuid, + bt_adapter_profile_connected_devices_cb callback, void *user_data) +{ + char *uuid128; + GPtrArray *addr_list = NULL; + bluetooth_device_address_t *remote_addr = NULL; + char *remote_address = NULL; + int ret = BT_ERROR_NONE; + int i = 0; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(profile_uuid); + BT_CHECK_INPUT_PARAMETER(callback); + + uuid128 = _bt_convert_uuid_to_uuid128(profile_uuid); + if (uuid128 == NULL) { + BT_ERR("Wrong type of uuid : %s", profile_uuid); + return BT_ERROR_INVALID_PARAMETER; + } + + addr_list = g_ptr_array_new(); + if (addr_list == NULL) { + BT_ERR("OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY); + return BT_ERROR_OUT_OF_MEMORY; + } + + ret = _bt_get_error_code( + bluetooth_get_profile_connected_device_list(uuid128, &addr_list)); + g_free(uuid128); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x) : Failed to get profile connected device list", + _bt_convert_error_to_string(ret), ret); + return ret; + } + + for (i = 0; i < addr_list->len; i++) { + remote_addr = g_ptr_array_index(addr_list, i); + if (remote_addr != NULL) { + ret = _bt_convert_address_to_string(&remote_address, remote_addr); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + if (!callback(remote_address, user_data)) { + g_free(remote_address); + break; + } + g_free(remote_address); + } else { + BT_ERR("OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); + ret = BT_ERROR_OPERATION_FAILED; + break; + } + } + + g_ptr_array_foreach(addr_list, (GFunc)g_free, NULL); + g_ptr_array_free(addr_list, TRUE); + + return ret; +} + int bt_adapter_set_state_changed_cb(bt_adapter_state_changed_cb callback, void *user_data) { @@ -1027,11 +1095,11 @@ int bt_adapter_get_local_oob_data(unsigned char **hash, ret = _bt_get_error_code(bluetooth_oob_read_local_data(&oob_data)); if (BT_ERROR_NONE == ret) { - *hash = g_memdup(oob_data.hash, BLUETOOTH_OOB_DATA_LENGTH); + *hash = g_memdup(oob_data.hash, oob_data.hash_len); *randomizer = g_memdup(oob_data.randomizer, - BLUETOOTH_OOB_DATA_LENGTH); - *hash_len = BLUETOOTH_OOB_DATA_LENGTH; - *randomizer_len = BLUETOOTH_OOB_DATA_LENGTH; + oob_data.randomizer_len); + *hash_len = oob_data.hash_len; + *randomizer_len = oob_data.randomizer_len; } else { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); /* LCOV_EXCL_LINE */ @@ -1046,6 +1114,7 @@ int bt_adapter_set_remote_oob_data(const char *remote_address, int ret = BT_ERROR_NONE; bluetooth_device_address_t addr_hex = { {0,} }; bt_oob_data_t oob_data = { {0},}; + int len; BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); BT_CHECK_INIT_STATUS(); @@ -1053,11 +1122,18 @@ int bt_adapter_set_remote_oob_data(const char *remote_address, _bt_convert_address_to_hex(&addr_hex, remote_address); - if (hash != NULL && randomizer != NULL) { - memcpy(oob_data.hash, hash, hash_len); - memcpy(oob_data.randomizer, randomizer, randomizer_len); - oob_data.hash_len = hash_len; - oob_data.randomizer_len = randomizer_len; + if (hash && randomizer) { + len = hash_len < BLUETOOTH_OOB_DATA_LENGTH ? + hash_len : BLUETOOTH_OOB_DATA_LENGTH; + memcpy(oob_data.hash, hash, len); + oob_data.hash_len = len; + + len = randomizer_len < BLUETOOTH_OOB_DATA_LENGTH ? + randomizer_len : BLUETOOTH_OOB_DATA_LENGTH; + memcpy(oob_data.randomizer, randomizer, len); + oob_data.randomizer_len = len; + } else { + return BT_ERROR_INVALID_PARAMETER; } ret = _bt_get_error_code(bluetooth_oob_add_remote_data(&addr_hex, @@ -1069,6 +1145,110 @@ int bt_adapter_set_remote_oob_data(const char *remote_address, return ret; } +int bt_adapter_get_local_oob_ext_data(unsigned char **hash192, unsigned char **randomizer192, + int *hash192_len, int *randomizer192_len, + unsigned char **hash256, unsigned char **randomizer256, + int *hash256_len, int *randomizer256_len) +{ + int ret = BT_ERROR_NONE; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(hash192); + BT_CHECK_INPUT_PARAMETER(randomizer192); + BT_CHECK_INPUT_PARAMETER(hash192_len); + BT_CHECK_INPUT_PARAMETER(randomizer192_len); + BT_CHECK_INPUT_PARAMETER(hash256); + BT_CHECK_INPUT_PARAMETER(randomizer256); + BT_CHECK_INPUT_PARAMETER(hash256_len); + BT_CHECK_INPUT_PARAMETER(randomizer256_len); + + bt_oob_data_t oob_data; + + ret = _bt_get_error_code(bluetooth_oob_read_local_data(&oob_data)); + if (BT_ERROR_NONE == ret) { + *hash192 = *randomizer192 = NULL; + *hash192_len = *randomizer192_len = 0; + + *hash256 = *randomizer256 = NULL; + *hash256_len = *randomizer256_len = 0; + + if (oob_data.hash_len && oob_data.randomizer_len) { + *hash192 = g_memdup(oob_data.hash, oob_data.hash_len); + *randomizer192 = g_memdup(oob_data.randomizer, + oob_data.randomizer_len); + + *hash192_len = oob_data.hash_len; + *randomizer192_len = oob_data.randomizer_len; + } + + if (oob_data.hash256_len && oob_data.randomizer256_len) { + *hash256 = g_memdup(oob_data.hash256, oob_data.hash256_len); + *randomizer256 = g_memdup(oob_data.randomizer256, + oob_data.randomizer256_len); + + *hash256_len = oob_data.hash256_len; + *randomizer256_len = oob_data.randomizer256_len; + } + } else { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + + return ret; +} + +int bt_adapter_set_remote_oob_ext_data(const char *remote_address, + const unsigned char *hash192, const unsigned char *randomizer192, + int hash192_len, int randomizer192_len, + const unsigned char *hash256, const unsigned char *randomizer256, + int hash256_len, int randomizer256_len) +{ + int ret = BT_ERROR_NONE; + bluetooth_device_address_t addr_hex = { {0,} }; + bt_oob_data_t oob_data = { {0},}; + int len; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + if ((!hash192 || !randomizer192) && (!hash256 || !randomizer256)) + return BT_ERROR_INVALID_PARAMETER; + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + if (hash192 && randomizer192) { + len = hash192_len < BLUETOOTH_OOB_DATA_LENGTH ? + hash192_len : BLUETOOTH_OOB_DATA_LENGTH; + memcpy(oob_data.hash, hash192, len); + oob_data.hash_len = len; + + len = randomizer192_len < BLUETOOTH_OOB_DATA_LENGTH ? + randomizer192_len : BLUETOOTH_OOB_DATA_LENGTH; + memcpy(oob_data.randomizer, randomizer192, len); + oob_data.randomizer_len = len; + } + + if (hash256 && randomizer256) { + len = hash256_len < BLUETOOTH_OOB_DATA_LENGTH ? + hash256_len : BLUETOOTH_OOB_DATA_LENGTH; + memcpy(oob_data.hash256, hash256, len); + oob_data.hash256_len = len; + + len = randomizer256_len < BLUETOOTH_OOB_DATA_LENGTH ? + randomizer256_len : BLUETOOTH_OOB_DATA_LENGTH; + memcpy(oob_data.randomizer256, randomizer256, len); + oob_data.randomizer256_len = len; + } + + ret = _bt_get_error_code(bluetooth_oob_add_remote_data(&addr_hex, &oob_data)); + if (BT_ERROR_NONE != ret) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + + return ret; +} + int bt_adapter_remove_remote_oob_data(const char *remote_address) { int ret = BT_ERROR_NONE; @@ -1119,6 +1299,101 @@ int bt_adapter_set_manufacturer_data(char *data, int len) return ret; } +int bt_adapter_parse_manufacturer_data(bt_manufacturer_data *data, char *manufacturer_data, int manufacturer_data_len) +{ + + int cursor, name_len; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(data); + BT_CHECK_INPUT_PARAMETER(manufacturer_data); + + if (manufacturer_data_len < 30) { + BT_DBG("minimum Size of the smasung specific manufacturer data is greater than 30 "); + return BT_ERROR_INVALID_PARAMETER; + } + if (manufacturer_data[0] != 0x00 || manufacturer_data[1] != 0x75) { + BT_DBG("This is not a samsung specific manufaturer data"); + return BT_ERROR_INVALID_PARAMETER; + } + + cursor = 2; + +/* control and version */ + data->version = manufacturer_data[cursor++]; + +/* service ID */ + data->service_id = manufacturer_data[cursor++]; + +/* Samsung discovery version */ + data->discovery_version = manufacturer_data[cursor++]; + +/* associated service ID */ + data->associated_service_id = manufacturer_data[cursor++]; + +/* Proxamity and locality */ + /* type */ + data->proximity_locality_type = manufacturer_data[cursor++]; + + /* info */ + data->proximity_locality_info = manufacturer_data[cursor++]; + +/* Device */ + /* type */ + data->device_type = manufacturer_data[cursor++]; + + /* icon */ + data->device_icon = manufacturer_data[cursor++]; + + /* Authentication info */ + memcpy(data->auth_info, &(manufacturer_data[cursor]), 5); + cursor = cursor + 5; + +/* Connectivity */ + /* address type */ + data->addr_type = manufacturer_data[cursor++]; + + /* addr1 */ + memcpy(data->addr1, &(manufacturer_data[cursor]), 6); + cursor = cursor + 6; + + /* addr2 */ + memcpy(data->addr2, &(manufacturer_data[cursor]), 6); + cursor = cursor + 6; + + /* channel info */ + data->channel_info = manufacturer_data[cursor++]; + + +/* Associated service data */ + data->associated_service_data_len = manufacturer_data[cursor++]; + if (data->associated_service_data_len) { + data->associated_service_data_val = g_malloc0(data->associated_service_data_len); + memcpy(data->associated_service_data_val, &(manufacturer_data[cursor]), + data->associated_service_data_len); + + cursor = cursor + data->associated_service_data_len; + } + +/* name : include the null termination */ + name_len = manufacturer_data_len - cursor; + if (name_len > 0) { + data->name= g_malloc0(name_len + 1); + memcpy(data->name, &(manufacturer_data[cursor]), name_len); + data->name[name_len] = '\0'; + } + return BT_ERROR_NONE; +} + +int bt_adapter_free_manufacturer_data(bt_manufacturer_data *data) +{ + BT_CHECK_INPUT_PARAMETER(data); + g_free(data->associated_service_data_val); + g_free(data->name); + return BT_ERROR_NONE; +} + int bt_adapter_set_manufacturer_data_changed_cb( bt_adapter_manufacturer_data_changed_cb callback, void *user_data) @@ -1146,6 +1421,43 @@ int bt_adapter_unset_manufacturer_data_changed_cb(void) return BT_ERROR_NONE; } +int bt_adapter_set_passkey_notification( + bt_adapter_passkey_notification_cb callback, void *user_data) +{ + int ret = BT_ERROR_NONE; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + + ret = _bt_get_error_code(bluetooth_set_passkey_notification(TRUE)); + if (ret == BT_ERROR_NONE) { + _bt_set_cb(BT_EVENT_PASSKEY_NOTIFICATION_EVENT, + callback, user_data); + } else { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + + return ret; +} + +int bt_adapter_unset_passkey_notification(void) +{ + int ret = BT_ERROR_NONE; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + + ret = _bt_get_error_code(bluetooth_set_passkey_notification(FALSE)); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + + _bt_unset_cb(BT_EVENT_PASSKEY_NOTIFICATION_EVENT); + + return BT_ERROR_NONE; +} + int bt_adapter_le_add_white_list(const char *address, bt_device_address_type_e address_type) { @@ -1234,6 +1546,24 @@ int bt_adapter_le_set_scan_mode(bt_adapter_le_scan_mode_e scan_mode) } /* LCOV_EXCL_STOP */ +int bt_adapter_le_set_customized_scan_mode(float scan_interval, float scan_window) +{ + int ret = BT_ERROR_NONE; + bluetooth_le_scan_params_t scan_params; + + BT_CHECK_INIT_STATUS(); + + scan_params.type = BT_ADAPTER_LE_ACTIVE_SCAN; + scan_params.interval = scan_interval; + scan_params.window = scan_window; + + ret = _bt_get_error_code(bluetooth_set_scan_parameters(&scan_params)); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + return ret; +} + int bt_adapter_le_create_advertiser(bt_advertiser_h *advertiser) { bt_advertiser_s *__adv = NULL; @@ -1317,12 +1647,9 @@ static int __bt_remove_ad_data_by_type(char *in_data, unsigned int in_len, if (i + len > in_len) { BT_ERR("Invalid advertising data"); /* LCOV_EXCL_LINE */ return BT_ERROR_OPERATION_FAILED; /* LCOV_EXCL_LINE */ - } else if (len == 0 && - in_type != BT_ADAPTER_LE_ADVERTISING_DATA_LOCAL_NAME && - in_type != BT_ADAPTER_LE_ADVERTISING_DATA_TX_POWER_LEVEL) { - BT_INFO("AD Type 0x%02x data is not set", - in_type); /* LCOV_EXCL_LINE */ - return BT_ERROR_OPERATION_FAILED; /* LCOV_EXCL_LINE */ + } else if (len == 0) { + BT_INFO("AD Type 0x%02x data is not set", in_type); + return BT_ERROR_OPERATION_FAILED; } p = (char *)malloc(sizeof(char) *(in_len - len)); @@ -1777,7 +2104,7 @@ int bt_adapter_le_add_advertising_service_data(bt_advertiser_h advertiser, char *adv_data = NULL; int uuid_bit; char *uuid_ptr; - int byte_len; + int byte_len = 0; char *converted_uuid = NULL; BT_CHECK_LE_SUPPORT(); @@ -2279,12 +2606,28 @@ int bt_adapter_le_enable_privacy(bool enable_privacy) return error_code; } +int bt_adapter_le_set_static_random_address(bool enable) +{ + int error_code = BT_ERROR_NONE; + + BT_CHECK_LE_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + error_code = _bt_get_error_code(bluetooth_set_le_static_random_address(enable)); + + if (error_code != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); + } + return error_code; +} + static void __bt_adapter_le_convert_scan_filter( bluetooth_le_scan_filter_t *dest, bt_le_scan_filter_s *src) { int bit; char *data; + char *converted_uuid = NULL; memset(dest, 0x00, sizeof(bluetooth_le_scan_filter_t)); @@ -2309,17 +2652,30 @@ static void __bt_adapter_le_convert_scan_filter( dest->service_uuid.data_len = 2; else dest->service_uuid.data_len = 16; - memcpy(dest->service_uuid.data.data, data, + + if (__bt_convert_byte_ordering(data, dest->service_uuid.data_len, + &converted_uuid) == BT_ERROR_NONE) { + memcpy(dest->service_uuid.data.data, converted_uuid, dest->service_uuid.data_len); + g_free(converted_uuid); + converted_uuid = NULL; + } g_free(data); + data = NULL; dest->service_uuid_mask.data_len = dest->service_uuid.data_len; if (src->service_uuid_mask) { - __bt_convert_string_to_uuid( - src->service_uuid_mask, &data, &bit); - memcpy(dest->service_uuid_mask.data.data, data, - dest->service_uuid_mask.data_len); + __bt_convert_string_to_uuid(src->service_uuid_mask, &data, &bit); + + if (__bt_convert_byte_ordering(data, dest->service_uuid_mask.data_len, + &converted_uuid) == BT_ERROR_NONE) { + memcpy(dest->service_uuid_mask.data.data, converted_uuid, + dest->service_uuid_mask.data_len); + g_free(converted_uuid); + converted_uuid = NULL; + } g_free(data); + data = NULL; } else { memset(dest->service_uuid_mask.data.data, 0xFF, dest->service_uuid_mask.data_len); @@ -2336,17 +2692,30 @@ static void __bt_adapter_le_convert_scan_filter( dest->service_solicitation_uuid.data_len = 2; else dest->service_solicitation_uuid.data_len = 16; - memcpy(dest->service_solicitation_uuid.data.data, data, - dest->service_solicitation_uuid.data_len); + + if (__bt_convert_byte_ordering(data, dest->service_solicitation_uuid.data_len, + &converted_uuid) == BT_ERROR_NONE) { + memcpy(dest->service_solicitation_uuid.data.data, + converted_uuid, dest->service_solicitation_uuid.data_len); + g_free(converted_uuid); + converted_uuid = NULL; + } g_free(data); + data = NULL; dest->service_solicitation_uuid_mask.data_len = dest->service_solicitation_uuid.data_len; if (src->service_solicitation_uuid_mask) { - __bt_convert_string_to_uuid( - src->service_solicitation_uuid_mask, - &data, &bit); - memcpy(dest->service_solicitation_uuid_mask.data.data, data, dest->service_solicitation_uuid_mask.data_len); + __bt_convert_string_to_uuid(src->service_solicitation_uuid_mask, &data, &bit); + + if (__bt_convert_byte_ordering(data, dest->service_solicitation_uuid_mask.data_len, + &converted_uuid) == BT_ERROR_NONE) { + memcpy(dest->service_solicitation_uuid_mask.data.data, + converted_uuid, dest->service_solicitation_uuid_mask.data_len); + g_free(converted_uuid); + converted_uuid = NULL; + } g_free(data); + data = NULL; } else { memset(dest->service_solicitation_uuid_mask.data.data, 0xFF, dest->service_solicitation_uuid_mask.data_len); } @@ -2354,27 +2723,28 @@ static void __bt_adapter_le_convert_scan_filter( } if (src->service_data_uuid) { - char *service_uuid; int uuid_len; - if (__bt_convert_string_to_uuid(src->service_data_uuid, - &service_uuid, &bit) == BT_ERROR_NONE) { + if (__bt_convert_string_to_uuid(src->service_data_uuid, &data, &bit) == BT_ERROR_NONE) { dest->added_features |= BLUETOOTH_LE_SCAN_FILTER_FEATURE_SERVICE_DATA; if (bit == 16) uuid_len = 2; else uuid_len = 16; - memcpy(dest->service_data.data.data, service_uuid, uuid_len); - g_free(service_uuid); - memcpy(dest->service_data.data.data + uuid_len, - src->service_data, src->service_data_len); - dest->service_data.data_len = uuid_len - + src->service_data_len; - - dest->service_data_mask.data_len = uuid_len - + src->service_data_len; - memset(dest->service_data_mask.data.data, - 0xFF, uuid_len); + if (__bt_convert_byte_ordering(data, uuid_len, &converted_uuid) + == BT_ERROR_NONE) { + memcpy(dest->service_data.data.data, converted_uuid, uuid_len); + g_free(converted_uuid); + converted_uuid = NULL; + } + g_free(data); + data = NULL; + + memcpy(dest->service_data.data.data + uuid_len, src->service_data, src->service_data_len); + dest->service_data.data_len = uuid_len + src->service_data_len; + + dest->service_data_mask.data_len = dest->service_data.data_len; + memset(dest->service_data_mask.data.data, 0xFF, uuid_len); if (src->service_data_mask) memcpy(dest->service_data_mask.data.data + uuid_len, src->service_data_mask, src->service_data_len); else @@ -2919,6 +3289,11 @@ int bt_adapter_le_create_scan_filter(bt_scan_filter_h *scan_filter) bt_le_scan_filter_s *__filter = NULL; BT_CHECK_LE_SUPPORT(); + if (bluetooth_is_scan_filter_supported() == FALSE) { + BT_ERR("BT_ERROR_NOT_SUPPORTED(0x%08x)", BT_ERROR_NOT_SUPPORTED); + return BT_ERROR_NOT_SUPPORTED; + } + BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(scan_filter); @@ -3278,6 +3653,11 @@ int bt_adapter_le_unregister_all_scan_filters(void) int error_code = BT_ERROR_NONE; BT_CHECK_LE_SUPPORT(); + if (bluetooth_is_scan_filter_supported() == FALSE) { + BT_ERR("BT_ERROR_NOT_SUPPORTED(0x%08x)", BT_ERROR_NOT_SUPPORTED); + return BT_ERROR_NOT_SUPPORTED; + } + BT_CHECK_INIT_STATUS(); if (bluetooth_is_le_scanning() == TRUE) { BT_ERR("NOW_IN_PROGRESS(0x%08x)", @@ -3294,6 +3674,7 @@ int bt_adapter_le_unregister_all_scan_filters(void) return BT_ERROR_NONE; } + int bt_adapter_le_read_maximum_data_length( int *max_tx_octets, int *max_tx_time, int *max_rx_octets, int *max_rx_time) @@ -3376,6 +3757,21 @@ int bt_adapter_le_read_suggested_default_data_length( return ret; } +int bt_adapter_force_hcidump(int timeout) +{ + int error_code = BT_ERROR_NONE; + + BT_CHECK_LE_SUPPORT(); + BT_CHECK_INIT_STATUS(); + + error_code = _bt_get_error_code(bluetooth_force_hcidump(timeout)); + + 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_adapter_set_authentication_req_cb(bt_adapter_authentication_req_cb callback, void *user_data) { diff --git a/src/bluetooth-audio.c b/src/bluetooth-audio.c index 852d06c..7feebe6 100644 --- a/src/bluetooth-audio.c +++ b/src/bluetooth-audio.c @@ -565,11 +565,17 @@ int bt_ag_notify_call_event(bt_ag_call_event_e event, unsigned int call_id, cons case BT_AG_CALL_EVENT_ALERTING: error = bluetooth_telephony_call_remote_ringing(call_id); break; - case BT_AG_CALL_EVENT_INCOMING: - BT_CHECK_INPUT_PARAMETER(phone_number); - error = bluetooth_telephony_indicate_incoming_call(phone_number, + case BT_AG_CALL_EVENT_INCOMING: { + const char *ph_number; + if (phone_number) { + ph_number = phone_number; + } else { + ph_number = ""; + } + error = bluetooth_telephony_indicate_incoming_call(ph_number, call_id); break; + } default: error = BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; } @@ -601,6 +607,23 @@ int bt_ag_notify_call_list(bt_call_list_h list) } /* LCOV_EXCL_STOP */ +int bt_ag_notify_vendor_cmd(const char *command) +{ + int error; + + BT_CHECK_HFP_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_AG_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(command); + + error = bluetooth_telephony_send_vendor_cmd(command); + error = _bt_convert_telephony_error_code(error); + if (error != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error); + } + return error; +} + int bt_ag_notify_voice_recognition_state(bool state) { int error; @@ -787,7 +810,11 @@ int bt_call_list_add(bt_call_list_h list, unsigned int call_id, bt_ag_call_state return BT_ERROR_OUT_OF_MEMORY; call_status->call_id = call_id; call_status->call_status = state; - call_status->phone_number = g_strdup(phone_number); + if (phone_number) { + call_status->phone_number = g_strdup(phone_number); + } else { + call_status->phone_number = g_strdup(""); + } handle->list = g_list_append(handle->list, (gpointer)call_status); return BT_ERROR_NONE; @@ -1092,6 +1119,33 @@ int bt_hf_get_call_status_info_list(GSList **call_list) return error; } +int bt_hf_is_inband_ringtone_supported(bool *supported) +{ +#ifdef TIZEN_BT_HFP_HF_ENABLE + int error; + gboolean is_supported = FALSE; + + BT_CHECK_HF_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(supported); + + error = bluetooth_hf_is_ibr_supported(&is_supported); + error = _bt_get_error_code(error); + if (error != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error); + + if (is_supported) + *supported = TRUE; + else + *supported = FALSE; + + return error; +#else + BT_ERR("NOT_SUPPORTED(0x%08x)", BT_ERROR_NOT_SUPPORTED); + return BT_ERROR_NOT_SUPPORTED; +#endif +} + static void __bt_hf_free_call_status_info(void *data) { bt_hf_call_status_info_s *call_info = (bt_hf_call_status_info_s *)data; @@ -1172,4 +1226,44 @@ int bt_hf_unset_multi_call_handling_event_cb(void) _bt_unset_cb(BT_EVENT_HF_MULTI_CALL_HANDLING_EVENT); return BT_ERROR_NONE; } -#endif + +int bt_hf_set_remote_call_event_cb( + bt_hf_remote_call_event_cb callback, + void *user_data) +{ + BT_CHECK_HF_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + _bt_set_cb(BT_EVENT_HF_REMOTE_CALL_EVENT, callback, user_data); + return BT_ERROR_NONE; +} + +int bt_hf_unset_remote_call_event_cb(void) +{ + BT_CHECK_HF_SUPPORT(); + BT_CHECK_INIT_STATUS(); + if (_bt_check_cb(BT_EVENT_HF_REMOTE_CALL_EVENT) == true) + _bt_unset_cb(BT_EVENT_HF_REMOTE_CALL_EVENT); + return BT_ERROR_NONE; +} + +int bt_hf_set_remote_device_state_changed_cb( + bt_hf_remote_device_state_changed_cb callback, + void *user_data) +{ + BT_CHECK_HF_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + _bt_set_cb(BT_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED, callback, user_data); + return BT_ERROR_NONE; +} + +int bt_hf_unset_remote_device_state_changed_cb(void) +{ + BT_CHECK_HF_SUPPORT(); + BT_CHECK_INIT_STATUS(); + if (_bt_check_cb(BT_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED) == true) + _bt_unset_cb(BT_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED); + return BT_ERROR_NONE; +} +#endif
\ No newline at end of file diff --git a/src/bluetooth-avrcp.c b/src/bluetooth-avrcp.c index 8d659f8..25fe672 100644 --- a/src/bluetooth-avrcp.c +++ b/src/bluetooth-avrcp.c @@ -108,6 +108,44 @@ int bt_avrcp_target_initialize(bt_avrcp_target_connection_state_changed_cb callb return BT_ERROR_NONE; } +int bt_avrcp_target_connect(const char *remote_address) +{ + int error; + bluetooth_device_address_t addr_hex = { {0,} }; + + BT_CHECK_AVRCP_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_AVRCP_TARGET_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + _bt_convert_address_to_hex(&addr_hex, remote_address); + + error = bluetooth_media_target_connect(&addr_hex); + error = _bt_get_error_code(error); + if (error != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error); + + return error; +} + +int bt_avrcp_target_disconnect(const char *remote_address) +{ + int error; + bluetooth_device_address_t addr_hex = { {0,} }; + + BT_CHECK_AVRCP_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_AVRCP_TARGET_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + _bt_convert_address_to_hex(&addr_hex, remote_address); + + error = bluetooth_media_target_disconnect(&addr_hex); + error = _bt_get_error_code(error); + if (error != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error); + + return error; +} + int bt_avrcp_target_deinitialize(void) { int error; diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 8e58ead..28deedc 100644 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -42,7 +42,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us static void __bt_le_event_proxy(int event, bluetooth_event_param_t *param, void *user_data); static int __bt_get_cb_index(int event); static void __bt_convert_lower_to_upper(char *origin); -static int __bt_get_bt_device_sdp_info_s(bt_device_sdp_info_s **dest, bt_sdp_info_t *source); +static int __bt_get_bt_device_sdp_info_s(bt_device_sdp_info_s **dest, bt_sdp_info_t *source, int error); static void __bt_free_bt_device_sdp_info_s(bt_device_sdp_info_s *sdp_info); static int __bt_get_bt_device_connection_info_s(bt_device_connection_info_s **dest, bt_connection_info_t *source); static void __bt_free_bt_device_connection_info_s(bt_device_connection_info_s *conn_info); @@ -63,9 +63,12 @@ static int __bt_gatt_client_update_descriptors(bt_gatt_handle_info_t desc_handle int bt_initialize(void) { + int ret; + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); if (is_initialized != true) { - if (bluetooth_register_callback(&__bt_event_proxy, NULL) != BLUETOOTH_ERROR_NONE) { + ret = bluetooth_register_callback(&__bt_event_proxy, NULL); + if (ret != BLUETOOTH_ERROR_NONE && ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { BT_ERR("OPERATION_FAILED(0x%08x)", BT_ERROR_OPERATION_FAILED); /* LCOV_EXCL_LINE */ return BT_ERROR_OPERATION_FAILED; /* LCOV_EXCL_LINE */ } @@ -88,6 +91,177 @@ int bt_deinitialize(void) return BT_ERROR_NONE; } +int bt_get_uuid_name(const char *uuid, char **name) +{ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INPUT_PARAMETER(uuid); + BT_CHECK_INPUT_PARAMETER(name); + + int i; + int offset = 0; + int uuid_len = 4; + static struct { + const char *uuid; + const char *specification_name; + } bt_uuid_name[] = { + /* BT Classic Services */ + {"1101", "Serial Port Service"}, + {"1102", "LAN Access Using PPP Service"}, + {"1103", "Dialup Netwworking Service"}, + {"1104", "IrMCSync Service"}, + {"1105", "OBEX Object Push Service"}, + {"1106", "OBEX File Transfer Service"}, + {"1107", "IrMC Sync Command Service"}, + {"1108", "Headset Service"}, + {"1109", "Cordless Telephony Service"}, + {"110A", "Audio Source Service"}, + {"110B", "Audio Sink Service"}, + {"110C", "AV Remote Control Target Service"}, + {"110D", "Advanced Audio Distribution Profile"}, + {"110E", "AV Remote Control Service"}, + {"110F", "Video Conferencing Service"}, + {"1110", "Intercom Service"}, + {"1111", "Fax Service"}, + {"1112", "Headset Audio Gateway Service"}, + {"1113", "WAP Service"}, + {"1114", "WAP Client Service"}, + {"1115", "PANU Service"}, + {"1116", "NAP Service"}, + {"1117", "GN Service"}, + {"1118", "Direct Printing Service"}, + {"1119", "Reference Printing Service"}, + {"111A", "Basic Imaging Profile"}, + {"111B", "Imaging Responder Service"}, + {"111C", "Imaging Automatic Archive Service"}, + {"111D", "Imaging Reference Objects Service"}, + {"111E", "Handsfree Service"}, + {"111F", "Handsfree Audio Gateway Service"}, + {"1120", "Direct Printing Reference Objects Service"}, + {"1121", "Reflected UI Service"}, + {"1122", "Basic Printing Profile"}, + {"1123", "Printing Status Service"}, + {"1124", "Human Interface Device Service"}, + {"1125", "Hardcopy Cable Replacement Profile"}, + {"1126", "HCR Print Service"}, + {"1127", "HCR Scan Service"}, + {"112D", "SIM Access Service"}, + {"112E", "Phonebook Access PCE Service"}, + {"112F", "Phonebook Access PSE Service"}, + {"1130", "Phonebook Access Profile"}, + {"1132", "Message Access Server Service"}, + {"1133", "Message Notification Server Service"}, + {"1134", "Message Access Profile"}, + {"1200", "PnP Information Service"}, + {"1201", "Generic Networking Service"}, + {"1202", "Generic File Transfer Service"}, + {"1203", "Generic Audio Service"}, + {"1204", "Generic Telephony Service"}, + {"1205", "UPnP Service"}, + {"1206", "UPnP Ip Service"}, + {"1400", "Health Device Profile"}, + + /* GATT Services */ + {"1800", "Generic Access"}, + {"1801", "Generic Attribute"}, + {"1802", "Immediate Alert"}, + {"1803", "Link Loss"}, + {"1804", "Tx Power"}, + {"1805", "Current Time Service"}, + {"1806", "Reference Time Update Service"}, + {"1807", "Next DST Change Service"}, + {"1808", "Glucose"}, + {"1809", "Health Thermometer"}, + {"180A", "Device Information"}, + {"180D", "Heart Rate"}, + {"180F", "Battery Service"}, + {"1810", "Blood Pressure"}, + {"1811", "Alert Notification Service"}, + {"1812", "Human Interface Device"}, + + /* GATT Declarations */ + {"2800", "Primary Service Declaration"}, + {"2801", "Secondary Service Declaration"}, + {"2802", "Include Declaration"}, + {"2803", "Characteristic Declaration"}, + + /* GATT Descriptors */ + {"2900", "Characteristic Extended Properties"}, + {"2901", "Characteristic User Description"}, + {"2902", "Client Characteristic Configuration"}, + {"2903", "Server Characteristic Configuration"}, + {"2904", "Characteristic Format"}, + {"2905", "Characteristic Aggregate Formate"}, + {"2906", "Valid Range"}, + {"2907", "External Report Reference"}, + {"2908", "Report Reference"}, + + /* GATT Characteristics */ + {"2A00", "Device Name"}, + {"2A01", "Appearance"}, + {"2A02", "Peripheral Privacy Flag"}, + {"2A03", "Reconnection Address"}, + {"2A04", "Peripheral Preferred Connection Parameters"}, + {"2A05", "Service Changed"}, + {"2A06", "Alert Level"}, + {"2A07", "Tx Power Level"}, + {"2A08", "Date Time"}, + {"2A09", "Day of Week"}, + {"2A0A", "Day Date Time"}, + {"2A19", "Battery Level"}, + {"2A1E", "Intermediate Temperature"}, + {"2A23", "System ID"}, + {"2A24", "Model Number String"}, + {"2A25", "Serial Number String"}, + {"2A26", "Firmware Revision String"}, + {"2A27", "Hardware Revision String"}, + {"2A28", "Software Revision String"}, + {"2A29", "Manufacturer Name String"}, + {"2A2A", "IEEE 11073-20601 Regulatory Certification Data List"}, + {"2A2B", "Current Time"}, + {"2A37", "Heart Rate Measurement"}, + {"2A38", "Body Sensor Location"}, + {"2A3F", "Alert Status"}, + {"2A46", "New Alert"}, + {"2A4A", "HID Information"}, + {"2A4C", "HID Control Point"}, + {"2A50", "PnP ID"}, + + /* Custom uuids */ + {"7905F431-B5CE-4E99-A40F-4B1E122D00D0", "Apple Notification Center Service"}, + {"9FBF120D-6301-42D9-8C58-25E699A21DBD", "Notifications Source"}, + {"69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9", "Control Point"}, + {"22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB", "Data Source"}, + {"89D3502B-0F36-433A-8EF4-C502AD55F8DC", "Apple Media Service"}, + {"9B3C81D8-57B1-4A8A-B8DF-0E56F7CA51C2", "Remote Command"}, + {"2F7CABCE-808D-411F-9A0C-BB92BA96C102", "Entity Update"}, + {"C6B2F38C-23AB-46D8-A6AB-A3A870BBD5D7", "Entity Attribute"}, + {"9A3F68E0-86CE-11E5-A309-0002A5D5C51B", "Samsung Gear Manager Service"}, + {"c2f2cc0f-c085-4dd4-be5a-aca3074bbc72", "Control Point"}, + {"cece518b-28d7-4171-92d5-76a1e249a3b9", "Notifications Source"}, + {NULL, NULL} + }; + + if (strlen(uuid) == 36) { + if (!g_ascii_strncasecmp(uuid + 9, "0000-1000-8000-00805F9B34FB", 27)) + offset = 4; + else { + offset = 0; + uuid_len = 36; + } + } else if (strlen(uuid) >= 8) + offset = 4; + + for (i = 0; bt_uuid_name[i].uuid; i++) { + if (!g_ascii_strncasecmp(uuid + offset, bt_uuid_name[i].uuid, uuid_len)) { + *name = g_strdup(bt_uuid_name[i].specification_name); + return BT_ERROR_NONE; + } + } + + *name = g_strdup("Unknown"); + return BT_ERROR_NONE; +} + /* * Common Functions */ @@ -160,8 +334,9 @@ int _bt_get_error_code(int origin_error) return BT_ERROR_NONE; case BLUETOOTH_ERROR_INVALID_DATA: case BLUETOOTH_ERROR_INVALID_PARAM: - case BLUETOOTH_ERROR_NOT_CONNECTED: return BT_ERROR_INVALID_PARAMETER; + case BLUETOOTH_ERROR_NOT_CONNECTED: + return BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED; case BLUETOOTH_ERROR_NOT_SUPPORT: return BT_ERROR_NOT_SUPPORTED; case BLUETOOTH_ERROR_MEMORY_ALLOCATION: @@ -175,6 +350,7 @@ int _bt_get_error_code(int origin_error) case BLUETOOTH_ERROR_ALREADY_INITIALIZED: case BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST: case BLUETOOTH_ERROR_ALREADY_DEACTIVATED: + case BLUETOOTH_ERROR_ALREADY_CONNECT: return BT_ERROR_ALREADY_DONE; case BLUETOOTH_ERROR_NOT_PAIRED: return BT_ERROR_REMOTE_DEVICE_NOT_BONDED; @@ -199,12 +375,14 @@ int _bt_get_error_code(int origin_error) return BT_ERROR_SERVICE_NOT_FOUND; case BLUETOOTH_ERROR_NOT_INITIALIZED: return BT_ERROR_NOT_INITIALIZED; + case BLUETOOTH_ERROR_NO_RESOURCES: + return BT_ERROR_QUOTA_EXCEEDED; + case BLUETOOTH_ERROR_AUTHENTICATION_REJECTED: + return BT_ERROR_AUTH_REJECTED; case BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION: return BT_ERROR_DEVICE_POLICY_RESTRICTION; case BLUETOOTH_ERROR_PARING_FAILED: case BLUETOOTH_ERROR_MAX_CONNECTION: - case BLUETOOTH_ERROR_ALREADY_CONNECT: - case BLUETOOTH_ERROR_NO_RESOURCES: case BLUETOOTH_ERROR_REGISTRATION_FAILED: case BLUETOOTH_ERROR_CONNECTION_BUSY: case BLUETOOTH_ERROR_MAX_CLIENT: @@ -235,6 +413,11 @@ int _bt_get_bt_device_info_s(bt_device_info_s **dest_dev, bluetooth_device_info_ else (*dest_dev)->remote_name = NULL; +#if 0 + (*dest_dev)->is_alias_set = source_dev->is_alias_set; + BT_DBG("is_alias_set: [%s]", (*dest_dev)->is_alias_set ? "TRUE" : "FALSE"); +#endif + _bt_convert_address_to_string(&((*dest_dev)->remote_address), &(source_dev->device_address)); (*dest_dev)->bt_class.major_device_class = source_dev->device_class.major_class; @@ -374,6 +557,12 @@ char *_bt_convert_error_to_string(int error) return "SERVICE_NOT_FOUND"; /* LCOV_EXCL_LINE */ case BT_ERROR_NOT_SUPPORTED: return "NOT_SUPPORTD"; /* LCOV_EXCL_LINE */ + case BT_ERROR_NO_DATA: + return "NO_DATA"; + case BT_ERROR_QUOTA_EXCEEDED: + return "QUOTA EXCEEDED"; + case BT_ERROR_AGAIN: + return "AGAIN"; case BT_ERROR_DEVICE_POLICY_RESTRICTION: return "DEVICE_POLICY_RESTRICTION"; default: @@ -381,6 +570,33 @@ char *_bt_convert_error_to_string(int error) } } +char *_bt_convert_uuid_to_uuid128(const char *uuid) +{ + int len; + char *uuid128; + + len = strlen(uuid); + + switch (len) { + case 4: /* UUID 16bits */ + uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805f9b34fb", uuid); + break; + + case 8: /* UUID 32bits */ + uuid128 = g_strdup_printf("%s-0000-1000-8000-00805f9b34fb", uuid); + break; + + case 36: /* UUID 128bits */ + uuid128 = strdup(uuid); + break; + + default: + return NULL; + } + + return uuid128; +} + bt_adapter_visibility_mode_e _bt_get_bt_visibility_mode_e(bluetooth_discoverable_mode_t mode) { switch (mode) { @@ -398,7 +614,7 @@ bt_adapter_visibility_mode_e _bt_get_bt_visibility_mode_e(bluetooth_discoverable */ /* LCOV_EXCL_START */ -static int __bt_get_bt_device_sdp_info_s(bt_device_sdp_info_s **dest, bt_sdp_info_t *source) +static int __bt_get_bt_device_sdp_info_s(bt_device_sdp_info_s **dest, bt_sdp_info_t *source, int error) { int i = 0; @@ -412,6 +628,10 @@ static int __bt_get_bt_device_sdp_info_s(bt_device_sdp_info_s **dest, bt_sdp_inf __bt_free_bt_device_sdp_info_s(*dest); return BT_ERROR_OUT_OF_MEMORY; } + if(error != BT_ERROR_NONE) { + BT_DBG("In error case, ignore other fields of service search"); + return BT_ERROR_NONE; + } if (source->service_index > 0) { (*dest)->service_uuid = (char **)malloc(sizeof(char *) *source->service_index); @@ -458,6 +678,25 @@ static void __bt_free_bt_device_sdp_info_s(bt_device_sdp_info_s *sdp_info) sdp_info = NULL; } +static int __bt_get_bt_device_att_mtu_info_s(bt_device_att_mtu_info_s **dest, bluetooth_le_att_mtu_info_t *source) +{ + *dest = (bt_device_att_mtu_info_s *)g_malloc0(sizeof(bt_device_att_mtu_info_s)); + if (*dest == NULL) + return BT_ERROR_OUT_OF_MEMORY; + + if (_bt_convert_address_to_string(&((*dest)->remote_address), &(source->device_address)) != BT_ERROR_NONE) { + g_free(*dest); + *dest = NULL; + + return BT_ERROR_OUT_OF_MEMORY; + } + + (*dest)->mtu = source->mtu; + (*dest)->status = source->status; + + return BT_ERROR_NONE; +} + static int __bt_get_bt_device_connection_info_s(bt_device_connection_info_s **dest, bt_connection_info_t *source) { *dest = (bt_device_connection_info_s *)g_malloc0(sizeof(bt_device_connection_info_s)); @@ -490,7 +729,7 @@ static int __bt_get_bt_device_connection_info_s(bt_device_connection_info_s **de } static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( - bt_gatt_h service, bt_gatt_h attribute, void **user_data) + bt_gatt_h service, bt_gatt_h attribute, bt_gatt_h *gatt_handle, void **user_data) { gchar *svc_path = (gchar *)service; gchar *att_path = (gchar *)attribute; @@ -516,6 +755,7 @@ static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( if (g_strcmp0(chr->path, att_path) == 0) { if (chr->read_requested_cb) { *user_data = chr->read_requested_user_data; + *gatt_handle = chr; return chr->read_requested_cb; } else return NULL; @@ -526,6 +766,7 @@ static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( if (desc && g_strcmp0(desc->path, att_path) == 0) { if (desc->read_requested_cb) { *user_data = desc->read_requested_user_data; + *gatt_handle = desc; return desc->read_requested_cb; } else return NULL; @@ -541,7 +782,7 @@ static bt_gatt_server_read_value_requested_cb __bt_gatt_attribute_get_read_cb( } static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_change_cb( - bt_gatt_h service, bt_gatt_h attribute, void **user_data) + bt_gatt_h service, bt_gatt_h attribute, bt_gatt_h *gatt_handle, void **user_data) { gchar *svc_path = (gchar *)service; gchar *att_path = (gchar *)attribute; @@ -567,6 +808,7 @@ static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_cha if (g_strcmp0(chr->path, att_path) == 0) { if (chr->write_value_requested_cb) { *user_data = chr->write_value_requested_user_data; + *gatt_handle = chr; return chr->write_value_requested_cb; } else return NULL; @@ -577,6 +819,7 @@ static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_cha if (desc && g_strcmp0(desc->path, att_path) == 0) { if (desc->write_value_requested_cb) { *user_data = desc->write_value_requested_user_data; + *gatt_handle = desc; return desc->write_value_requested_cb; } else return NULL; @@ -591,8 +834,9 @@ static bt_gatt_server_write_value_requested_cb __bt_gatt_attribute_get_value_cha return NULL; } -static bt_gatt_server_characteristic_notification_state_changed_cb __bt_gatt_attribute_get_notification_change_cb( - bt_gatt_h service, bt_gatt_h attribute, void **user_data) +static bt_gatt_server_characteristic_notification_state_changed_cb + __bt_gatt_attribute_get_notification_change_cb( + bt_gatt_h service, bt_gatt_h attribute, bt_gatt_h *gatt_handle, void **user_data) { gchar *svc_path = (gchar *)service; gchar *att_path = (gchar *)attribute; @@ -617,6 +861,7 @@ static bt_gatt_server_characteristic_notification_state_changed_cb __bt_gatt_att if (chr && g_strcmp0(chr->path, att_path) == 0) { if (chr->notification_changed_cb) { *user_data = chr->notification_changed_user_data; + *gatt_handle = chr; return chr->notification_changed_cb; } else return NULL; @@ -730,6 +975,31 @@ void _bt_hid_event_proxy(int event, hid_event_param_t *param, void *user_data) } /* LCOV_EXCL_STOP */ +static bool __bt_need_to_handle(int event) +{ + int event_index = -1; + + switch (event) { + case BLUETOOTH_EVENT_ADVERTISING_STARTED: + case BLUETOOTH_EVENT_ADVERTISING_STOPPED: + case BLUETOOTH_EVENT_GATT_CONNECTED: + case BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED: + case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED: + case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED: + case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED: + case BLUETOOTH_EVENT_GATT_CLIENT_SERVICE_CHANGED: + return true; + default: + break; + } + + event_index = __bt_get_cb_index(event); + if (event_index != -1 && bt_event_slot_container[event_index].callback) + return true; + + return false; +} + static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *user_data) { int call_id; @@ -766,44 +1036,10 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_le_data_length_params_t *data_length_info = NULL; bt_ipsp_connection_info_t *bt_ipsp_iface_info = NULL; - event_index = __bt_get_cb_index(event); - - if (event == BLUETOOTH_EVENT_GATT_CONNECTED) { - const GSList *clients = NULL; /* LCOV_EXCL_START */ - const GSList *l = NULL; - int ret; - - _bt_convert_address_to_string(&device_addr, - (bluetooth_device_address_t *)(param->param_data)); - - clients = _bt_gatt_get_client_list(); - for (l = clients; l; l = g_slist_next(l)) { - bt_gatt_client_s *client_s = l->data; - - if (!g_strcmp0(client_s->remote_address, device_addr)) { - if (client_s->services_discovered == false) { - BT_INFO("Matched GATT Client is found"); - ret = _bt_gatt_client_update_all((bt_gatt_client_h)l->data); - if (ret != BT_ERROR_NONE) - BT_ERR("bluetooth_gatt_get_primary_services is failed"); - else - client_s->services_discovered = true; - } - break; - } - } - g_free(device_addr); - device_addr = NULL; /* LCOV_EXCL_STOP */ - } - - if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED || event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED || - event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED || event == BLUETOOTH_EVENT_ADVERTISING_STARTED || - event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED || event == BLUETOOTH_EVENT_ADVERTISING_STOPPED) - BT_INFO("NOT use bt_event_slot_container"); - else if (event_index == -1 || bt_event_slot_container[event_index].callback == NULL) + if (!__bt_need_to_handle(event)) return; - memset(&rfcomm_connection, 0x00, sizeof(bt_socket_connection_s)); + event_index = __bt_get_cb_index(event); switch (event) { case BLUETOOTH_EVENT_ENABLED: @@ -838,6 +1074,13 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us ((bt_adapter_connectable_changed_cb)bt_event_slot_container[event_index].callback) (_bt_get_error_code(param->result), *(bool *)(param->param_data), bt_event_slot_container[event_index].user_data); break; + case BLUETOOTH_EVENT_SUPPORTED_PROFILE_TRUSTED: { + BT_INFO("bt_device_trusted_profile_cb() will be called"); + bt_supported_profile_trusted_t *parameter = param->param_data; + ((bt_device_trusted_profiles_cb)bt_event_slot_container[event_index].callback) + (_bt_get_error_code(param->result), parameter->address, parameter->profile, parameter->supported, parameter->trusted, bt_event_slot_container[event_index].user_data); + break; + } case BLUETOOTH_EVENT_DISCOVERY_STARTED: BT_INFO("bt_adapter_device_discovery_state_changed_cb() will be called with BT_ADAPTER_DEVICE_DISCOVERY_STARTED"); ((bt_adapter_device_discovery_state_changed_cb) bt_event_slot_container[event_index].callback) @@ -961,11 +1204,13 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us break; case BLUETOOTH_EVENT_SERVICE_SEARCHED: BT_INFO("bt_device_service_searched_cb() will be called"); - __bt_get_bt_device_sdp_info_s(&sdp_info, (bt_sdp_info_t *)(param->param_data)); error_code = _bt_get_error_code(param->result); /* In service search, BT_ERROR_SERVICE_SEARCH_FAILED is returned instead of BT_ERROR_OPERATION_FAILED. */ if (error_code == BT_ERROR_OPERATION_FAILED) error_code = BT_ERROR_SERVICE_SEARCH_FAILED; + + __bt_get_bt_device_sdp_info_s(&sdp_info, (bt_sdp_info_t *)(param->param_data), error_code); + ((bt_device_service_searched_cb)bt_event_slot_container[event_index].callback) (error_code, sdp_info, bt_event_slot_container[event_index].user_data); __bt_free_bt_device_sdp_info_s(sdp_info); @@ -1510,25 +1755,47 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us ((bt_hid_device_received_data_s *)(param->param_data), bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_GATT_CONNECTED: { + bt_gatt_client_s *client_s; + bt_gatt_connection_state_changed_cb cb = NULL; BT_INFO("BLUETOOTH_EVENT_GATT_CONNECTED"); - gboolean connected = TRUE; - bd_addr = (bluetooth_device_address_t *)(param->param_data); - _bt_convert_address_to_string(&device_addr, bd_addr); - if (_bt_get_error_code(param->result) != BT_ERROR_NONE) - connected = FALSE; - ((bt_gatt_connection_state_changed_cb)bt_event_slot_container[event_index].callback) - (_bt_get_error_code(param->result), connected, device_addr, - bt_event_slot_container[event_index].user_data); + _bt_convert_address_to_string(&device_addr, + (bluetooth_device_address_t *)(param->param_data)); + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + if (client_s && !client_s->services_discovered) { + if (_bt_gatt_client_update_services(client_s) != BT_ERROR_NONE) + BT_ERR("_bt_gatt_client_update_services failed"); + else + client_s->services_discovered = true; } + if (client_s) + client_s->connected = true; + if (event_index >= 0) + cb = bt_event_slot_container[event_index].callback; + if (cb) + cb(_bt_get_error_code(param->result), TRUE, device_addr, + bt_event_slot_container[event_index].user_data); + g_free(device_addr); + device_addr = NULL; break; - case BLUETOOTH_EVENT_GATT_DISCONNECTED: + } + case BLUETOOTH_EVENT_GATT_DISCONNECTED: { + bt_gatt_client_s *client_s; + bt_gatt_connection_state_changed_cb cb = NULL; BT_INFO("BLUETOOTH_EVENT_GATT_DISCONNECTED"); - bd_addr = (bluetooth_device_address_t *)(param->param_data); - _bt_convert_address_to_string(&device_addr, bd_addr); - ((bt_gatt_connection_state_changed_cb)bt_event_slot_container[event_index].callback) - (_bt_get_error_code(param->result), FALSE, device_addr, - bt_event_slot_container[event_index].user_data); + _bt_convert_address_to_string(&device_addr, + (bluetooth_device_address_t *)(param->param_data)); + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + if (client_s) + client_s->connected = false; + if (event_index >= 0) + cb = bt_event_slot_container[event_index].callback; + if (cb) + cb(_bt_get_error_code(param->result), FALSE, device_addr, + bt_event_slot_container[event_index].user_data); + g_free(device_addr); + device_addr = NULL; break; + } #ifdef BT_ENABLE_LEGACY_GATT_CLIENT case BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED: { BT_INFO("BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED"); @@ -1619,7 +1886,18 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us } #endif _bt_unset_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC); - ret = _bt_get_error_code(param->result); + + /* Send actual ATT error code to Application + * if param->result is not BLUETOOTH_ERROR_INTERNAL. + */ + if (param->result == BLUETOOTH_ERROR_INTERNAL) + ret = _bt_get_error_code(param->result); + else + ret = param->result; + + if (ret != BT_ERROR_NONE) + BT_ERR("BLUETOOTH_EVENT_GATT_WRITE_CHAR - ret [%d]", ret); + cb(ret, cb_data->gatt_handle, cb_data->user_data); g_free(cb_data); @@ -1663,8 +1941,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_gatt_read_req_t *read_req = param->param_data; bt_gatt_server_read_value_requested_cb cb; void *user_data = NULL; + bt_gatt_h gatt_handle = NULL; cb = __bt_gatt_attribute_get_read_cb(read_req->service_handle, - read_req->att_handle, &user_data); + read_req->att_handle, &gatt_handle, &user_data); BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED"); if (cb == NULL) { @@ -1675,7 +1954,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us } cb(read_req->address, read_req->req_id, read_req->service_handle, - read_req->att_handle, read_req->offset, + gatt_handle, read_req->offset, user_data); break; } @@ -1683,8 +1962,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_gatt_value_change_t *value_change = param->param_data; bt_gatt_server_write_value_requested_cb cb; void *user_data = NULL; + bt_gatt_h gatt_handle = NULL; cb = __bt_gatt_attribute_get_value_change_cb(value_change->service_handle, - value_change->att_handle, &user_data); + value_change->att_handle, &gatt_handle, &user_data); BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGE"); if (cb == NULL) { @@ -1695,7 +1975,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us } cb(value_change->address, value_change->req_id, value_change->service_handle, - value_change->att_handle, value_change->offset, + gatt_handle, value_change->offset, (char *)value_change->att_value, value_change->val_len, user_data); break; } @@ -1703,15 +1983,16 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_gatt_char_notify_change_t *value_change = param->param_data; bt_gatt_server_characteristic_notification_state_changed_cb cb; void *user_data = NULL; + bt_gatt_h gatt_handle = NULL; cb = __bt_gatt_attribute_get_notification_change_cb(value_change->service_handle, - value_change->att_handle, &user_data); + value_change->att_handle, &gatt_handle, &user_data); BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED"); if (cb == NULL) return; cb(value_change->att_notify, value_change->service_handle, - value_change->att_handle, user_data); + gatt_handle, user_data); break; } case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED: { @@ -1785,6 +2066,81 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us break; } /* LCOV_EXCL_STOP */ + case BLUETOOTH_EVENT_GATT_CLIENT_SERVICE_CHANGED: { + bt_gatt_service_change_t *service_change = + (bt_gatt_service_change_t *)(param->param_data); + const GSList *l = NULL; + bt_gatt_client_s *client = NULL; + bt_gatt_service_s *svc = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_CLIENT_SERVICE_CHANGED"); + + if (service_change == NULL) { + BT_ERR("service_change is NULL"); + return; + } + + _bt_convert_address_to_string(&device_addr, + &service_change->device_addr); + + client = _bt_gatt_get_client(device_addr); + g_free(device_addr); + device_addr = NULL; + + if (client == NULL) { + BT_ERR("There is NO matched client"); + break; + } + + if (service_change->change_type + == BLUETOOTH_GATT_SERVICE_CHANGE_TYPE_ADD) { + for (l = client->services; l; l = g_slist_next(l)) { + svc = l->data; + if (!g_strcmp0(svc->path, service_change->svc_path)) + break; + } + if (l) { + BT_INFO("already added service : %s", svc->path); + break; + } + + svc = _bt_gatt_client_add_service(client, + service_change->svc_path); + if (svc == NULL) { + BT_ERR("_bt_gatt_client_add_service is failed"); + break; + } + + if (client->connected && client->service_changed_cb) + client->service_changed_cb(client, + BT_GATT_CLIENT_SERVICE_ADDED, + svc->uuid, + client->service_changed_user_data); + } else { + char *removed_uuid = NULL; + + for (l = client->services; l; l = g_slist_next(l)) { + svc = l->data; + if (!g_strcmp0(svc->path, service_change->svc_path)) + break; + } + if (!l) { + BT_ERR("There is NO matched service"); + break; + } + + removed_uuid = g_strdup(svc->uuid); + bt_gatt_service_destroy((bt_gatt_h)svc); + + if (client->connected && client->service_changed_cb) + client->service_changed_cb(client, + BT_GATT_CLIENT_SERVICE_REMOVED, + removed_uuid, + client->service_changed_user_data); + g_free(removed_uuid); + } + break; + } case BLUETOOTH_EVENT_ADVERTISING_STARTED: BT_INFO("BLUETOOTH_EVENT_ADVERTISING_STARTED"); adv_handle = (int *)(param->param_data); @@ -1821,6 +2177,21 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_event_slot_container[event_index].user_data); break; + + case BLUETOOTH_EVENT_PASSKEY_NOTIFICATION: { + const char *address = NULL; + const char *passkey = NULL; + const char **passkey_info = param->param_data; + BT_INFO("BLUETOOTH_EVENT_PASSKEY_NOTIFICATION"); + + address = passkey_info[0]; + passkey = passkey_info[1]; + + ((bt_adapter_passkey_notification_cb)bt_event_slot_container[event_index].callback) + (address, passkey, bt_event_slot_container[event_index].user_data); + + break; + } case BLUETOOTH_EVENT_IPSP_CONNECTED: BT_INFO("BLUETOOTH_EVENT_IPSP_CONNECTED"); bt_ipsp_iface_info = (bt_ipsp_connection_info_t *)(param->param_data); @@ -1837,6 +2208,15 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us (_bt_get_error_code(param->result), FALSE, device_addr, bt_ipsp_iface_info->if_name, bt_event_slot_container[event_index].user_data); break; + case BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED: { + bt_device_att_mtu_info_s *mtu_info = NULL; + + BT_INFO("BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED"); + __bt_get_bt_device_att_mtu_info_s(&mtu_info, (bluetooth_le_att_mtu_info_t *)(param->param_data)); + ((bt_device_att_mtu_changed_cb)bt_event_slot_container[event_index].callback) + (_bt_get_error_code(param->result), mtu_info, bt_event_slot_container[event_index].user_data); + break; + } case BLUETOOTH_EVENT_LE_DATA_LENGTH_CHANGED: BT_INFO("__bt_le_set_data_length_changed_cb() will be called"); data_length_info = (bt_le_data_length_params_t *)(param->param_data); @@ -2019,63 +2399,93 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us case BLUETOOTH_EVENT_HF_RING_INDICATOR: BT_INFO("BLUETOOTH_EVENT_HF_RING_INDICATOR"); phone_number = (char *)(param->param_data); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_RING, phone_number, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_RINGING, phone_number, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_TERMINATED: BT_INFO("BLUETOOTH_EVENT_HF_CALL_TERMINATED"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_RELEASE, NULL, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_CALL_TERMINATED, NULL, + bt_event_slot_container[event_index].user_data); + break; + case BLUETOOTH_EVENT_HF_CALL_FAILED_TO_DIAL: + BT_INFO("BLUETOOTH_EVENT_HF_CALL_FAILED_TO_DIAL"); + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_FAILED_TO_DIALING, NULL, + bt_event_slot_container[event_index].user_data); + break; + case BLUETOOTH_EVENT_HF_CALL_IDLE: + BT_INFO("BLUETOOTH_EVENT_HF_CALL_IDLE"); + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_IDLE, NULL, + bt_event_slot_container[event_index].user_data); + break; + case BLUETOOTH_EVENT_HF_CALLSETUP_INCOMING: + BT_INFO("BLUETOOTH_EVENT_HF_CALLSETUP_INCOMING"); + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_INCOMING, NULL, + bt_event_slot_container[event_index].user_data); + break; + case BLUETOOTH_EVENT_HF_CALLSETUP_DIALING: + BT_INFO("BLUETOOTH_EVENT_HF_CALLSETUP_DIALING"); + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_DIALING, NULL, + bt_event_slot_container[event_index].user_data); + break; + case BLUETOOTH_EVENT_HF_CALLSETUP_ALERTING: + BT_INFO("BLUETOOTH_EVENT_HF_CALLSETUP_ALERTING"); + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_ALERTING, NULL, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_STARTED: BT_INFO("BLUETOOTH_EVENT_HF_CALL_STARTED"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_CALL_STARTED, NULL, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_CALL_STARTED, NULL, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_ENDED: BT_INFO("BLUETOOTH_EVENT_HF_CALL_ENDED"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_CALL_ENDED, NULL, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_CALL_ENDED, NULL, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED: BT_INFO("BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_VOICE_RECOGNITION_ENABLED, NULL, + ((bt_hf_remote_device_state_changed_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_DEVICE_STATE_VOICE_RECOGNITON, TRUE, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED: BT_INFO("BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_VOICE_RECOGNITION_DISABLED, NULL, + ((bt_hf_remote_device_state_changed_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_DEVICE_STATE_VOICE_RECOGNITON, FALSE, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_WAITING: BT_INFO("BLUETOOTH_EVENT_HF_CALL_WAITING"); phone_number = (char *)(param->param_data); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_WAITING, phone_number, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_WAITING, phone_number, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_ON_HOLD: BT_INFO("BLUETOOTH_EVENT_HF_CALL_ON_HOLD"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_HELD, NULL, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_HELD, NULL, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_UNHOLD: BT_INFO("BLUETOOTH_EVENT_HF_CALL_UNHOLD"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_UNHELD, NULL, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_UNHELD, NULL, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_CALL_SWAPPED: BT_INFO("BLUETOOTH_EVENT_HF_CALL_SWAPPED"); - ((bt_hf_call_handling_event_cb)bt_event_slot_container[event_index].callback) - (BT_HF_CALL_HANDLING_EVENT_SWAPPED, NULL, + ((bt_hf_remote_call_event_cb)bt_event_slot_container[event_index].callback) + (BT_HF_REMOTE_CALL_EVENT_SWAPPED, NULL, bt_event_slot_container[event_index].user_data); break; case BLUETOOTH_EVENT_HF_VOLUME_SPEAKER: { @@ -2108,6 +2518,17 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us (call_list, bt_event_slot_container[event_index].user_data); break; } + case BLUETOOTH_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED: { + bluetooth_hf_ciev_device_event_t *device_event = (bluetooth_hf_ciev_device_event_t *)(param->param_data); + + BT_INFO("BLUETOOTH_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED (status %d)(value %d)", + device_event->event, device_event->value); + + ((bt_hf_remote_device_state_changed_cb)bt_event_slot_container[event_index].callback) + ((bt_hf_remote_device_state_e) device_event->event, device_event->value, + bt_event_slot_container[event_index].user_data); + break; + } #endif case BLUETOOTH_EVENT_IPSP_INIT_STATE_CHANGED: { BT_DBG("BLUETOOTH_EVENT_IPSP_INIT_STATE_CHANGED"); /* LCOV_EXCL_LINE */ @@ -2121,7 +2542,6 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us } } - static void __bt_le_event_proxy(int event, bluetooth_event_param_t *param, void *user_data) { bt_adapter_le_device_scan_result_info_s *scan_info = NULL; @@ -2581,16 +3001,22 @@ static int __bt_get_cb_index(int event) case BLUETOOTH_EVENT_GATT_WRITE_DESC: return BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR; /* LCOV_EXCL_STOP */ + case BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED: + return BT_EVENT_GATT_ATT_MTU_CHANGE_STATUS; case BLUETOOTH_EVENT_ADVERTISING_STARTED: case BLUETOOTH_EVENT_ADVERTISING_STOPPED: return BT_EVENT_ADVERTISING_STATE_CHANGED; case BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED: return BT_EVENT_MANUFACTURER_DATA_CHANGED; /* LCOV_EXCL_LINE */ + case BLUETOOTH_EVENT_PASSKEY_NOTIFICATION: + return BT_EVENT_PASSKEY_NOTIFICATION_EVENT; case BLUETOOTH_EVENT_CONNECTABLE_CHANGED: return BT_EVENT_CONNECTABLE_CHANGED_EVENT; /* LCOV_EXCL_LINE */ case BLUETOOTH_EVENT_IPSP_CONNECTED: case BLUETOOTH_EVENT_IPSP_DISCONNECTED: return BT_EVENT_IPSP_CONNECTION_STATUS; /* LCOV_EXCL_LINE */ + case BLUETOOTH_EVENT_SUPPORTED_PROFILE_TRUSTED: + return BT_EVENT_SUPPORTED_TRUSTED_PROFILE_EVENT; case BLUETOOTH_EVENT_LE_DATA_LENGTH_CHANGED: return BT_EVENT_LE_DATA_LENGTH_CHANGED; /* LCOV_EXCL_LINE */ #ifdef TIZEN_WEARABLE @@ -2619,17 +3045,26 @@ static int __bt_get_cb_index(int event) case BLUETOOTH_EVENT_HF_CALL_TERMINATED: case BLUETOOTH_EVENT_HF_CALL_STARTED: case BLUETOOTH_EVENT_HF_CALL_ENDED: - case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED: - case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED: case BLUETOOTH_EVENT_HF_CALL_WAITING: case BLUETOOTH_EVENT_HF_CALL_ON_HOLD: case BLUETOOTH_EVENT_HF_CALL_UNHOLD: case BLUETOOTH_EVENT_HF_CALL_SWAPPED: - return BT_EVENT_HF_CALL_HANDLING_EVENT; + case BLUETOOTH_EVENT_HF_CALL_FAILED_TO_DIAL: + case BLUETOOTH_EVENT_HF_CALL_IDLE: + case BLUETOOTH_EVENT_HF_CALLSETUP_INCOMING: + case BLUETOOTH_EVENT_HF_CALLSETUP_DIALING: + case BLUETOOTH_EVENT_HF_CALLSETUP_ALERTING: + return BT_EVENT_HF_REMOTE_CALL_EVENT; + case BLUETOOTH_EVENT_HF_VENDOR_DEP_CMD: + return BT_EVENT_HF_VENDOR_DEP_CMD_EVENT; case BLUETOOTH_EVENT_HF_VOLUME_SPEAKER: return BT_EVENT_HF_SPEAKER_GAIN_CHANGE; case BLUETOOTH_EVENT_HF_CALL_STATUS: return BT_EVENT_HF_CALL_STATUS_UPDATED_EVENT; + case BLUETOOTH_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED: + case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED: + case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED: + return BT_EVENT_HF_CIEV_DEVICE_STATUS_CHANGED; #endif case BLUETOOTH_EVENT_IPSP_INIT_STATE_CHANGED: return BT_EVENT_IPSP_INIT_STATE_CHANGED; @@ -2651,8 +3086,19 @@ static void __bt_convert_lower_to_upper(char *origin) static void bt_gatt_client_handle_destroy(bt_gatt_h gatt_handle) { - if (gatt_handle) - bt_gatt_destroy(gatt_handle); + bt_gatt_common_s *handle = (bt_gatt_common_s *)gatt_handle; + + if (handle) { + if (handle->type == BT_GATT_TYPE_SERVICE) + bt_gatt_service_destroy(gatt_handle); + else if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) + bt_gatt_characteristic_destroy(gatt_handle); + else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) + bt_gatt_descriptor_destroy(gatt_handle); + else { + BT_ERR("Type is invalid(type:%d)", handle->type); + } + } } int _bt_gatt_client_update_all(bt_gatt_client_h client) diff --git a/src/bluetooth-device.c b/src/bluetooth-device.c index 35d4d9d..c042977 100644 --- a/src/bluetooth-device.c +++ b/src/bluetooth-device.c @@ -297,6 +297,11 @@ int bt_device_get_connection_state(const char *remote_address, return ret; } + if (connected_link == BLUETOOTH_CONNECTED_LINK_NONE) { + *connected = false; + return BT_ERROR_NONE; + } + if (connected_link == BLUETOOTH_CONNECTED_LINK_BREDR_LE) { *connected = true; return BT_ERROR_NONE; @@ -327,6 +332,16 @@ int bt_device_set_connection_state_changed_cb(bt_device_connection_state_changed return BT_ERROR_NONE; } +int bt_device_set_att_mtu_changed_cb(bt_device_att_mtu_changed_cb callback, void *user_data) +{ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + _bt_set_cb(BT_EVENT_GATT_ATT_MTU_CHANGE_STATUS, callback, user_data); + + return BT_ERROR_NONE; +} + int bt_device_unset_bond_created_cb(void) { BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); @@ -372,6 +387,92 @@ int bt_device_unset_connection_state_changed_cb(void) _bt_unset_cb(BT_EVENT_DEVICE_CONNECTION_STATUS); return BT_ERROR_NONE; } + +int bt_device_unset_att_mtu_changed_cb(void) +{ + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + _bt_unset_cb(BT_EVENT_DEVICE_CONNECTION_STATUS); + return BT_ERROR_NONE; +} + +int bt_device_enable_rssi_monitor(const char *remote_address, + bt_device_connection_link_type_e link_type, + int low_threshold, int in_range_threshold, + bt_rssi_monitor_enabled_cb cb_enable, + void *user_data_enable, + bt_rssi_alert_cb cb_alert, + void *user_data_alert) +{ + bluetooth_device_address_t addr_hex = { {0,} }; + int error_code = BT_ERROR_NONE; + bt_rssi_threshold_t rssi_threshold = { 0, }; + BT_DBG("Enable RSSI"); + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + rssi_threshold.high_threshold = 127; + rssi_threshold.low_threshold = low_threshold; + rssi_threshold.in_range_threshold = in_range_threshold; + + error_code = _bt_get_error_code(bluetooth_enable_rssi(&addr_hex, link_type, &rssi_threshold)); + if (error_code != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); + } else { + _bt_set_cb(BT_EVENT_RSSI_ENABLED_EVENT, cb_enable, user_data_enable); + _bt_set_cb(BT_EVENT_RSSI_ALERT_EVENT, cb_alert, user_data_alert); + } + + return error_code; +} + +int bt_device_disable_rssi_monitor(const char *remote_address, + bt_device_connection_link_type_e link_type, + bt_rssi_monitor_enabled_cb cb_disable, + void *user_data_disable) +{ + bluetooth_device_address_t addr_hex = { {0,} }; + int error_code = BT_ERROR_NONE; + bt_rssi_threshold_t rssi_threshold = { 0, }; + BT_DBG("Enable RSSI"); + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + error_code = _bt_get_error_code(bluetooth_enable_rssi(&addr_hex, link_type, &rssi_threshold)); + if (error_code != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); + else + _bt_set_cb(BT_EVENT_RSSI_ENABLED_EVENT, cb_disable, user_data_disable); + + return error_code; +} + +int bt_device_get_rssi_strength(const char *remote_address, + bt_device_connection_link_type_e link_type, + bt_rssi_strength_cb callback, void *user_data) +{ + bluetooth_device_address_t addr_hex = { {0,} }; + int error_code = BT_ERROR_NONE; + BT_DBG("Get RSSI Strength"); + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + error_code = _bt_get_error_code(bluetooth_get_rssi_strength(&addr_hex, link_type)); + if (error_code != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); + else + _bt_set_cb(BT_EVENT_GET_RSSI_EVENT, callback, user_data); + + return error_code; +} + + /* LCOV_EXCL_START */ int bt_device_le_conn_update(const char *device_address, const bt_le_conn_update_s *parameters) @@ -605,6 +706,199 @@ int bt_passkey_confirmation_reply(bool confirmation_reply) return error_code; } + +int bt_device_set_pin_code(const char *remote_address, const char *pin_code) +{ + int error_code = BT_ERROR_NONE; + bluetooth_device_address_t addr_hex = { {0,} }; + bluetooth_device_pin_code_t pin = { {0} }; + + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + BT_CHECK_INPUT_PARAMETER(pin_code); + if (strlen(pin_code) > BLUETOOTH_PIN_CODE_MAX_LENGTH) { + BT_ERR("INVALID_PARAMETER(0x%08x)", BT_ERROR_INVALID_PARAMETER); + return BT_ERROR_INVALID_PARAMETER; + } + + _bt_convert_address_to_hex(&addr_hex, remote_address); + strncpy(pin.pin_code, pin_code, BLUETOOTH_PIN_CODE_MAX_LENGTH); + pin.pin_code[BLUETOOTH_PIN_CODE_MAX_LENGTH] = '\0'; + + error_code = _bt_get_error_code(bluetooth_set_pin_code(&addr_hex, &pin)); + 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_device_unset_pin_code(const char *remote_address) +{ + int error_code = BT_ERROR_NONE; + bluetooth_device_address_t addr_hex = { {0,} }; + + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + error_code = _bt_get_error_code(bluetooth_unset_pin_code(&addr_hex)); + 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_device_update_le_connection_mode(const char *remote_address, bt_device_le_connection_mode_e mode) +{ + int ret; + bluetooth_device_address_t addr_hex = { {0,} }; + + BT_CHECK_INPUT_PARAMETER(remote_address); + + if (mode < BT_DEVICE_LE_CONNECTION_MODE_BALANCED || + mode > BT_DEVICE_LE_CONNECTION_MODE_LOW_ENERGY) { + return BT_ERROR_INVALID_PARAMETER; + } + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + ret = _bt_get_error_code(bluetooth_update_le_connection_mode(&addr_hex, mode)); + if (BT_ERROR_NONE != ret) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + + return ret; +} + +int bt_device_request_att_mtu(const char *remote_address, unsigned int mtu) +{ + int ret; + bluetooth_device_address_t addr_hex = { {0,} }; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + ret = _bt_get_error_code(bluetooth_request_att_mtu(&addr_hex, mtu)); + if (BT_ERROR_NONE != ret) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + + return ret; +} + +int bt_device_get_att_mtu(const char *remote_address, unsigned int *mtu) +{ + bluetooth_device_address_t addr_hex = { {0,} }; + int ret; + unsigned int mtu_value = 0; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); + + _bt_convert_address_to_hex(&addr_hex, remote_address); + + ret = _bt_get_error_code(bluetooth_get_att_mtu(&addr_hex, &mtu_value)); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + *mtu = mtu_value; + + return ret; + +} + +int bt_device_get_ida(const char *remote_rpa, char **id_address) +{ + bluetooth_device_address_t id_addr = { {0} }; + bluetooth_device_address_t addr_hex = { {0,} }; + int ret = BT_ERROR_NONE; + + BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_rpa); + + _bt_convert_address_to_hex(&addr_hex, remote_rpa); + + ret = bluetooth_get_device_ida(&addr_hex, &id_addr); + + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + ret = _bt_convert_address_to_string(id_address, &id_addr); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + return ret; +} + +int bt_device_set_profile_trusted(const char *device_address, + bt_trusted_profile_t profile, bool trust) +{ + bluetooth_device_address_t addr_hex = { {0,} }; + int error_code = BT_ERROR_NONE; + + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(device_address); + + _bt_convert_address_to_hex(&addr_hex, device_address); + error_code = _bt_get_error_code(bluetooth_set_profile_trusted(&addr_hex, + profile, trust)); + 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_device_get_profile_trusted(const char *device_address, + bt_trusted_profile_t profile, int *trust) +{ + bluetooth_device_address_t addr_hex = { {0,} }; + int profile_trusted; + int error_code = BT_ERROR_NONE; + + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(device_address); + + _bt_convert_address_to_hex(&addr_hex, device_address); + error_code = _bt_get_error_code(bluetooth_get_profile_trusted(&addr_hex, + profile, &profile_trusted)); + if (error_code != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code); + } + if (trust) + *trust = profile_trusted; + return error_code; +} + +int bt_device_set_trusted_profile_cb(bt_device_trusted_profiles_cb callback, void *user_data) +{ + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(callback); + _bt_set_cb(BT_EVENT_SUPPORTED_TRUSTED_PROFILE_EVENT, callback, user_data); + + return BT_ERROR_NONE; +} + +int bt_device_unset_trusted_profile_cb(void) +{ + BT_CHECK_INIT_STATUS(); + _bt_unset_cb(BT_EVENT_SUPPORTED_TRUSTED_PROFILE_EVENT); + return BT_ERROR_NONE; +} + int bt_device_le_set_data_length(const char *remote_address, unsigned int max_tx_Octets, unsigned int max_tx_Time) { diff --git a/src/bluetooth-gatt.c b/src/bluetooth-gatt.c index cd3e30d..4a12e37 100644 --- a/src/bluetooth-gatt.c +++ b/src/bluetooth-gatt.c @@ -32,6 +32,9 @@ static GSList *gatt_server_list = NULL; static bool is_gatt_server_initialized = false; static bool is_gatt_server_started = false; +bt_gatt_service_s* __bt_gatt_service_create(const char *uuid, + bt_gatt_service_type_e type); + #define BT_CHECK_GATT_SUPPORT() \ { \ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); \ @@ -57,35 +60,6 @@ int __bt_check_gatt_server_init_status(void) return BT_ERROR_NONE; } -static char *__convert_uuid_to_uuid128(const char *uuid) -{ - int len; - char *uuid128; - - len = strlen(uuid); - - switch (len) { - case 4: /* UUID 16bits */ - uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805F9B34FB", - uuid); - break; - - case 8: /* UUID 32bits */ - uuid128 = g_strdup_printf("%s-0000-1000-8000-00805F9B34FB", - uuid); - break; - - case 36: /* UUID 128bits */ - uuid128 = strdup(uuid); - break; - - default: - return NULL; - } - - return uuid128; -} - static int __get_gatt_handle_by_uuid(GSList *list, const char *uuid, bt_gatt_h *gatt_handle) { @@ -93,7 +67,7 @@ static int __get_gatt_handle_by_uuid(GSList *list, const char *uuid, char *uuid128_a; char *uuid128_b; - uuid128_a = __convert_uuid_to_uuid128(uuid); + uuid128_a = _bt_convert_uuid_to_uuid128(uuid); if (uuid128_a == NULL) { BT_ERR("Wrong type of uuid : %s", uuid); return BT_ERROR_INVALID_PARAMETER; @@ -102,7 +76,7 @@ static int __get_gatt_handle_by_uuid(GSList *list, const char *uuid, for (l = list; l; l = g_slist_next(l)) { bt_gatt_common_s *common = (bt_gatt_common_s *)l->data; - uuid128_b = __convert_uuid_to_uuid128(common->uuid); + uuid128_b = _bt_convert_uuid_to_uuid128(common->uuid); if (g_ascii_strcasecmp(uuid128_a, uuid128_b) == 0) { g_free(uuid128_b); break; @@ -110,6 +84,7 @@ static int __get_gatt_handle_by_uuid(GSList *list, const char *uuid, g_free(uuid128_b); } + g_free(uuid128_a); if (!l) return BT_ERROR_NO_DATA; @@ -119,16 +94,299 @@ static int __get_gatt_handle_by_uuid(GSList *list, const char *uuid, return BT_ERROR_NONE; } -const GSList *_bt_gatt_get_client_list(void) +bt_gatt_client_h _bt_gatt_get_client(const char *remote_addr) { - return gatt_client_list; + GSList *l; + + for (l = gatt_client_list; l; l = g_slist_next(l)) { + bt_gatt_client_s *client_s = l->data; + + if (client_s == NULL) + continue; + + if (!g_strcmp0(client_s->remote_address, remote_addr)) + return (bt_gatt_client_h)client_s; + } + + return NULL; } -const GSList *_bt_gatt_get_server_list(void) +const GSList* _bt_gatt_get_server_list(void) { return gatt_server_list; } +static void __bt_gatt_client_handle_destroy(bt_gatt_h gatt_handle) +{ + bt_gatt_common_s *handle = (bt_gatt_common_s*)gatt_handle; + + if (handle->type == BT_GATT_TYPE_SERVICE) + bt_gatt_service_destroy(gatt_handle); + else if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) + bt_gatt_characteristic_destroy(gatt_handle); + else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) + bt_gatt_descriptor_destroy(gatt_handle); +} + +bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, const char *path) +{ + int ret; + bt_gatt_client_s *client_s = client; + bt_gatt_service_s *svc = NULL; + bt_gatt_service_property_t property; + + if (client == NULL || path == NULL) { + BT_ERR("Invalid parameter"); + return NULL; + } + + memset(&property, 0x00, sizeof(property)); + + ret = bluetooth_gatt_get_service_property(path, &property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_service_property is failed"); + return NULL; + } + + svc = __bt_gatt_service_create(property.uuid, + BT_GATT_SERVICE_TYPE_PRIMARY); + if (svc == NULL) { + BT_ERR("svc is NULL"); + return NULL; + } + svc->role = BT_GATT_ROLE_CLIENT; + svc->parent = (void *)client_s; + svc->is_included_service = false; + svc->path = g_strdup(path); + + svc->include_handles = property.include_handles.handle; + property.include_handles.handle = NULL; + + svc->char_handles = property.char_handle.handle; + property.char_handle.handle = NULL; + + bluetooth_gatt_free_service_property(&property); + + client_s->services = g_slist_append(client_s->services, svc); + + return svc; +} + +int _bt_gatt_client_update_services(bt_gatt_client_h client) +{ + bt_gatt_client_s *client_s = client; + bluetooth_device_address_t addr_hex = { {0, } }; + bt_gatt_handle_info_t prim_svc; + int ret; + int i; + + _bt_convert_address_to_hex(&addr_hex, client_s->remote_address); + + ret = bluetooth_gatt_get_primary_services(&addr_hex, &prim_svc); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_primary_services is failed"); + return ret; + } + + g_slist_free_full(client_s->services, + __bt_gatt_client_handle_destroy); + client_s->services = NULL; + + if (prim_svc.count == 0) { + BT_INFO("There is no service"); + return BT_ERROR_NONE; + } + + for (i = 0; i < prim_svc.count; i++) { + BT_INFO("Service handle[%d] %s", i, prim_svc.handle[i]); + + if (!_bt_gatt_client_add_service(client, prim_svc.handle[i])) + BT_ERR("_bt_gatt_client_add_service is failed [%s]", + prim_svc.handle[i]); + } + g_strfreev(prim_svc.handle); + + return BT_ERROR_NONE; +} + +int _bt_gatt_client_update_include_services(bt_gatt_h service) +{ + bt_gatt_service_s *svc = service; + GSList *include_list = NULL; + int i; + + if (svc == NULL) + return BT_ERROR_INVALID_PARAMETER; + + if (svc->include_handles == NULL) + return BT_ERROR_NONE; + + for (i = 0; svc->include_handles[i]; i++) { + bt_gatt_service_s *sec_svc = NULL; + bt_gatt_service_property_t sec_property; + int ret; + + memset(&sec_property, 0x00, sizeof(sec_property)); + + ret = bluetooth_gatt_get_service_property( + svc->include_handles[i], &sec_property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_service_property is failed"); + continue; + } + + sec_svc = __bt_gatt_service_create(sec_property.uuid, + BT_GATT_SERVICE_TYPE_SECONDARY); + if (sec_svc == NULL) { + BT_ERR("svc is NULL"); + goto next; + } + sec_svc->role = BT_GATT_ROLE_CLIENT; + sec_svc->parent = (void *)svc; + sec_svc->is_included_service = true; + sec_svc->path = g_strdup(svc->include_handles[i]); + + sec_svc->char_handles = sec_property.char_handle.handle; + sec_property.char_handle.handle = NULL; + + include_list = g_slist_append(include_list, sec_svc); +next: + bluetooth_gatt_free_service_property(&sec_property); + } + + g_strfreev(svc->include_handles); + svc->include_handles = NULL; + + g_slist_free_full(svc->included_services, + __bt_gatt_client_handle_destroy); + + svc->included_services = include_list; + + return BT_ERROR_NONE; +} + +int _bt_gatt_client_update_characteristics(bt_gatt_h service) +{ + bt_gatt_service_s *svc = service; + GSList *chr_list = NULL; + int i; + + if (svc == NULL) + return BT_ERROR_INVALID_PARAMETER; + + if (svc->char_handles == NULL) + return BT_ERROR_NONE; + + for (i = 0; svc->char_handles[i]; i++) { + bt_gatt_characteristic_s *chr = NULL; + bt_gatt_char_property_t char_property; + int ret; + + memset(&char_property, 0x00, sizeof(char_property)); + + ret = bluetooth_gatt_get_characteristics_property( + svc->char_handles[i], &char_property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_characteristics_property is failed"); + continue; + } + + ret = bt_gatt_characteristic_create(char_property.uuid, 0, + char_property.permission, + (char *)char_property.val, + (int)char_property.val_len, (bt_gatt_h *)&chr); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_gatt_characteristic_create is failed"); + goto next; + } + + if (char_property.permission & BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE) + chr->write_type = BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE; + else if (char_property.permission & BT_GATT_PROPERTY_WRITE) + chr->write_type = BT_GATT_WRITE_TYPE_WRITE; + + chr->path = g_strdup(svc->char_handles[i]); + chr->parent = (void *)svc; + chr->role = BT_GATT_ROLE_CLIENT; + chr->desc_handles = char_property.char_desc_handle.handle; + char_property.char_desc_handle.handle = NULL; + + chr_list = g_slist_append(chr_list, chr); +next: + bluetooth_gatt_free_char_property(&char_property); + } + + g_strfreev(svc->char_handles); + svc->char_handles = NULL; + + g_slist_free_full(svc->characteristics, + __bt_gatt_client_handle_destroy); + + svc->characteristics = chr_list; + + return BT_ERROR_NONE; +} + +int _bt_gatt_client_update_descriptors(bt_gatt_h characteristic) +{ + bt_gatt_characteristic_s *chr = characteristic; + GSList *desc_list = NULL; + int i; + + if (chr == NULL) + return BT_ERROR_INVALID_PARAMETER; + + if (chr->desc_handles == NULL) + return BT_ERROR_NONE; + + for (i = 0; chr->desc_handles[i]; i++) { + bt_gatt_descriptor_s *desc = NULL; + bt_gatt_char_descriptor_property_t desc_property; + int ret; + + memset(&desc_property, 0x00, sizeof(desc_property)); + + ret = bluetooth_gatt_get_char_descriptor_property( + chr->desc_handles[i], &desc_property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_char_descriptor_property is failed"); + continue; + } + + ret = bt_gatt_descriptor_create(desc_property.uuid, 0, + (char*)desc_property.val, + (int)desc_property.val_len, + (bt_gatt_h *)&desc); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_gatt_characteristic_create is failed"); + goto next; + } + + desc->path = g_strdup(chr->desc_handles[i]); + desc->parent = (void *)characteristic; + desc->role = BT_GATT_ROLE_CLIENT; + + desc_list = g_slist_append(desc_list, desc); +next: + bluetooth_gatt_free_desc_property(&desc_property); + } + + g_strfreev(chr->desc_handles); + chr->desc_handles = NULL; + + g_slist_free_full(chr->descriptors, + __bt_gatt_client_handle_destroy); + + chr->descriptors = desc_list; + + return BT_ERROR_NONE; +} + #ifdef BT_ENABLE_LEGACY_GATT_CLIENT bool _bt_gatt_is_legacy_client_mode(void) { @@ -580,102 +838,6 @@ int bt_gatt_unset_connection_state_changed_cb(void) _bt_unset_cb(BT_EVENT_GATT_CONNECTION_STATUS); return BT_ERROR_NONE; } -/* LCOV_EXCL_START */ -int bt_gatt_get_uuid_specification_name(const char *uuid, char **name) -{ - BT_CHECK_GATT_SUPPORT(); - BT_CHECK_INIT_STATUS(); - BT_CHECK_INPUT_PARAMETER(uuid); - BT_CHECK_INPUT_PARAMETER(name); - - int i; - int offset = 0; - static struct { - const char *uuid; - const char *specification_name; - } bt_uuid_name[] = { - /* GATT Services */ - {"1800", "Generic Access"}, - {"1801", "Generic Attribute"}, - {"1802", "Immediate Alert"}, - {"1803", "Link Loss"}, - {"1804", "Tx Power"}, - {"1805", "Current Time Service"}, - {"1806", "Reference Time Update Service"}, - {"1807", "Next DST Change Service"}, - {"1808", "Glucose"}, - {"1809", "Health Thermometer"}, - {"180A", "Device Information"}, - {"180D", "Heart Rate"}, - {"180F", "Battery Service"}, - {"1810", "Blood Pressure"}, - {"1811", "Alert Notification Service"}, - {"1812", "Human Interface Device"}, - - /* GATT Declarations */ - {"2800", "Primary Service Declaration"}, - {"2801", "Secondary Service Declaration"}, - {"2802", "Include Declaration"}, - {"2803", "Characteristic Declaration"}, - - /* GATT Descriptors */ - {"2900", "Characteristic Extended Properties"}, - {"2901", "Characteristic User Description"}, - {"2902", "Client Characteristic Configuration"}, - {"2903", "Server Characteristic Configuration"}, - {"2904", "Characteristic Format"}, - {"2905", "Characteristic Aggregate Formate"}, - {"2906", "Valid Range"}, - {"2907", "External Report Reference"}, - {"2908", "Report Reference"}, - - /* GATT Characteristics */ - {"2A00", "Device Name"}, - {"2A01", "Appearance"}, - {"2A02", "Peripheral Privacy Flag"}, - {"2A03", "Reconnection Address"}, - {"2A04", "Peripheral Preferred Connection Parameters"}, - {"2A05", "Service Changed"}, - {"2A06", "Alert Level"}, - {"2A07", "Tx Power Level"}, - {"2A08", "Date Time"}, - {"2A09", "Day of Week"}, - {"2A0A", "Day Date Time"}, - {"2A19", "Battery Level"}, - {"2A1E", "Intermediate Temperature"}, - {"2A23", "System ID"}, - {"2A24", "Model Number String"}, - {"2A25", "Serial Number String"}, - {"2A26", "Firmware Revision String"}, - {"2A27", "Hardware Revision String"}, - {"2A28", "Software Revision String"}, - {"2A29", "Manufacturer Name String"}, - {"2A2A", "IEEE 11073-20601 Regulatory Certification Data List"}, - {"2A2B", "Current Time"}, - {"2A37", "Heart Rate Measurement"}, - {"2A38", "Body Sensor Location"}, - {"2A3F", "Alert Status"}, - {"2A46", "New Alert"}, - {"2A4A", "HID Information"}, - {"2A4C", "HID Control Point"}, - {"2A50", "PnP ID"}, - {NULL, NULL} - }; - - if (strlen(uuid) >= 8) - offset = 4; - - for (i = 0; bt_uuid_name[i].uuid; i++) { - if (!g_ascii_strncasecmp(uuid + offset, - bt_uuid_name[i].uuid, 4)) { - *name = g_strdup(bt_uuid_name[i].specification_name); - return BT_ERROR_NONE; - } - } - - *name = g_strdup("Unknown"); - return BT_ERROR_NONE; -} static void __bt_gatt_free_descriptor(bt_gatt_h gatt_handle) { @@ -689,10 +851,23 @@ static void __bt_gatt_free_descriptor(bt_gatt_h gatt_handle) static void __bt_gatt_free_characteristic(bt_gatt_h gatt_handle) { - bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; + int ret; + bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s*)gatt_handle; + + if (chr->role == BT_GATT_ROLE_CLIENT && chr->value_changed_cb && + chr->properties & + (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { + BT_DBG("Unwatch characteristic"); + ret = _bt_get_error_code(bluetooth_gatt_unwatch_characteristics( + chr->path)); + if (ret != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } g_slist_free_full(chr->descriptors, __bt_gatt_free_descriptor); + g_strfreev(chr->desc_handles); + g_free(chr->path); g_free(chr->uuid); g_free(chr->value); @@ -714,6 +889,9 @@ static void __bt_gatt_free_service(bt_gatt_h gatt_handle) _bt_convert_error_to_string(ret), ret); } + g_strfreev(svc->include_handles); + g_strfreev(svc->char_handles); + g_free(svc->path); g_free(svc->uuid); g_free(svc); @@ -871,28 +1049,6 @@ static int __get_data_type_int_size(bt_data_type_int_e format) } } -int bt_gatt_destroy(bt_gatt_h gatt_handle) -{ - bt_gatt_common_s *handle = (bt_gatt_common_s *)gatt_handle; - - BT_CHECK_GATT_SUPPORT(); - BT_CHECK_INIT_STATUS(); - BT_CHECK_INPUT_PARAMETER(gatt_handle); - - if (handle->type == BT_GATT_TYPE_SERVICE) - __bt_gatt_destroy_service(gatt_handle); - else if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) - __bt_gatt_destroy_characteristic(gatt_handle); - else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) - __bt_gatt_destroy_descriptor(gatt_handle); - else { - BT_ERR("Type is invalid(type:%d)", handle->type); - return BT_ERROR_INVALID_PARAMETER; - } - - return BT_ERROR_NONE; -} - int bt_gatt_service_destroy(bt_gatt_h gatt_handle) { bt_gatt_common_s *handle = (bt_gatt_common_s *)gatt_handle; @@ -1455,6 +1611,33 @@ int bt_gatt_get_type(bt_gatt_h gatt_handle, bt_gatt_type_e *gatt_type) return BT_ERROR_NONE; /* LCOV_EXCL_LINE */ } + +bt_gatt_service_s* __bt_gatt_service_create(const char *uuid, + bt_gatt_service_type_e type) +{ + bt_gatt_service_s *svc; + + if (uuid == NULL) + return NULL; + + svc = (bt_gatt_service_s*)g_malloc0(sizeof(bt_gatt_service_s)); + if (svc == NULL) + return NULL; + + svc->type = BT_GATT_TYPE_SERVICE; + if (strlen(uuid) == 8) + svc->uuid = _bt_convert_uuid_to_uuid128(uuid); + else + svc->uuid = strdup(uuid); + if (svc->uuid == NULL) { + g_free(svc); + return NULL; + } + svc->service_type = type; + + return svc; +} + /* LCOV_EXCL_START */ int bt_gatt_service_create(const char *uuid, bt_gatt_service_type_e type, bt_gatt_h *service) @@ -1467,27 +1650,16 @@ int bt_gatt_service_create(const char *uuid, bt_gatt_service_type_e type, BT_CHECK_INPUT_PARAMETER(uuid); BT_CHECK_INPUT_PARAMETER(service); - svc = (bt_gatt_service_s *)g_malloc0(sizeof(bt_gatt_service_s)); - if (svc == NULL) - return BT_ERROR_OUT_OF_MEMORY; - svc->type = BT_GATT_TYPE_SERVICE; - svc->role = BT_GATT_ROLE_SERVER; - if (is_gatt_server_started) { BT_ERR("Already Server started"); return BT_ERROR_OPERATION_FAILED; } - if (strlen(uuid) == 8) - svc->uuid = __convert_uuid_to_uuid128(uuid); - else - svc->uuid = strdup(uuid); - if (svc->uuid == NULL) { - g_free(svc); + svc = __bt_gatt_service_create(uuid, type); + if (svc == NULL) return BT_ERROR_OUT_OF_MEMORY; - } + svc->role = BT_GATT_ROLE_SERVER; svc->is_included_service = false; - svc->service_type = type; *service = (bt_gatt_h)svc; @@ -1603,8 +1775,15 @@ int bt_gatt_service_get_characteristic(bt_gatt_h service, const char *uuid, BT_CHECK_INPUT_PARAMETER(uuid); /* LCOV_EXCL_START */ BT_CHECK_INPUT_PARAMETER(characteristic); - ret = __get_gatt_handle_by_uuid(svc->characteristics, - uuid, &gatt_handle); + if (svc->char_handles) { + ret = _bt_gatt_client_update_characteristics(svc); + if (ret != BT_ERROR_NONE) { + BT_ERR("_bt_gatt_client_update_characteristics failed"); + return ret; + } + } + + ret = __get_gatt_handle_by_uuid(svc->characteristics, uuid, &gatt_handle); if (ret == BT_ERROR_NONE && gatt_handle != NULL) { *characteristic = gatt_handle; return BT_ERROR_NONE; @@ -1630,6 +1809,16 @@ int bt_gatt_service_foreach_characteristics(bt_gatt_h service, BT_CHECK_INPUT_PARAMETER(service); BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ + if (svc->char_handles) { + int ret; + + ret = _bt_gatt_client_update_characteristics(svc); + if (ret != BT_ERROR_NONE) { + BT_ERR("_bt_gatt_client_update_characteristics is failed"); + return ret; + } + } + total = g_slist_length(svc->characteristics); for (l = svc->characteristics; l; l = g_slist_next(l)) { @@ -1655,8 +1844,15 @@ int bt_gatt_service_get_included_service(bt_gatt_h service, const char *uuid, BT_CHECK_INPUT_PARAMETER(uuid); /* LCOV_EXCL_START */ BT_CHECK_INPUT_PARAMETER(included_service); - ret = __get_gatt_handle_by_uuid(svc->included_services, - uuid, &gatt_handle); + if (svc->include_handles) { + ret = _bt_gatt_client_update_include_services(svc); + if (ret != BT_ERROR_NONE) { + BT_ERR("_bt_gatt_client_update_include_services failed"); + return ret; + } + } + + ret = __get_gatt_handle_by_uuid(svc->included_services, uuid, &gatt_handle); if (ret == BT_ERROR_NONE && gatt_handle != NULL) { *included_service = gatt_handle; return BT_ERROR_NONE; @@ -1682,6 +1878,16 @@ int bt_gatt_service_foreach_included_services(bt_gatt_h service, BT_CHECK_INPUT_PARAMETER(service); BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_LINE */ + if (svc->include_handles) { + int ret; + + ret = _bt_gatt_client_update_include_services(svc); + if (ret != BT_ERROR_NONE) { + BT_ERR("_bt_gatt_client_update_include_services failed"); + return ret; + } + } + total = g_slist_length(svc->included_services); /* LCOV_EXCL_LINE */ for (l = svc->included_services; l; l = g_slist_next(l)) { @@ -1718,7 +1924,7 @@ int bt_gatt_characteristic_create(const char *uuid, int permissions, chr->type = BT_GATT_TYPE_CHARACTERISTIC; chr->role = BT_GATT_ROLE_SERVER; if (strlen(uuid) == 8) - chr->uuid = __convert_uuid_to_uuid128(uuid); + chr->uuid = _bt_convert_uuid_to_uuid128(uuid); else chr->uuid = g_strdup(uuid); if (chr->uuid == NULL) { @@ -1860,6 +2066,7 @@ int bt_gatt_characteristic_set_write_type(bt_gatt_h characteristic, bt_gatt_write_type_e write_type) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)characteristic; + int property; BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1871,8 +2078,27 @@ int bt_gatt_characteristic_set_write_type(bt_gatt_h characteristic, return BT_ERROR_INVALID_PARAMETER; /* LCOV_EXCL_LINE */ } - chr->write_type = write_type; + switch (write_type) { + case BT_GATT_WRITE_TYPE_WRITE: + property = BT_GATT_PROPERTY_WRITE; + break; + case BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE: + property = BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE; + break; +/* After ACR for BT_GATT_WRITE_TYPE_SIGNED_WRITE, will enable this code */ +#if 0 + case BT_GATT_WRITE_TYPE_SIGNED_WRITE: + property = BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES; + break; +#endif + default: + return BT_ERROR_NOT_SUPPORTED; + } + + if(!(chr->properties & property)) + return BT_ERROR_NOT_SUPPORTED; + chr->write_type = write_type; return BT_ERROR_NONE; } @@ -1890,6 +2116,19 @@ int bt_gatt_characteristic_get_descriptor(bt_gatt_h characteristic, BT_CHECK_INPUT_PARAMETER(uuid); /* LCOV_EXCL_START */ BT_CHECK_INPUT_PARAMETER(descriptor); + if (chr->type != BT_GATT_TYPE_CHARACTERISTIC) { + BT_ERR("Wrong type of GATT handle : %d", chr->type); + return BT_ERROR_INVALID_PARAMETER; + } + + if (chr->desc_handles) { + ret = _bt_gatt_client_update_descriptors(chr); + if (ret != BT_ERROR_NONE) { + BT_ERR("_bt_gatt_client_update_descriptors is failed"); + return ret; + } + } + ret = __get_gatt_handle_by_uuid(chr->descriptors, uuid, &gatt_handle); if (ret == BT_ERROR_NONE && gatt_handle != NULL) { *descriptor = gatt_handle; @@ -1919,6 +2158,16 @@ int bt_gatt_characteristic_foreach_descriptors(bt_gatt_h characteristic, return BT_ERROR_INVALID_PARAMETER; } + if (chr->desc_handles) { + int ret; + + ret = _bt_gatt_client_update_descriptors(chr); + if (ret != BT_ERROR_NONE) { + BT_ERR("_bt_gatt_client_update_descriptors is failed"); + return ret; + } + } + total = g_slist_length(chr->descriptors); i = 1; @@ -1954,13 +2203,14 @@ int bt_gatt_descriptor_create(const char *uuid, int permissions, desc->type = BT_GATT_TYPE_DESCRIPTOR; desc->role = BT_GATT_ROLE_SERVER; if (strlen(uuid) == 8) - desc->uuid = __convert_uuid_to_uuid128(uuid); + desc->uuid = _bt_convert_uuid_to_uuid128(uuid); else desc->uuid = g_strdup(uuid); if (desc->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; } + desc->permissions = permissions; desc->value_length = value_length; if (value_length > 0) { @@ -2259,16 +2509,17 @@ int bt_gatt_server_unregister_service(bt_gatt_server_h server, return BT_ERROR_SERVICE_NOT_FOUND; } - __bt_gatt_destroy_service(svc); + bt_gatt_service_destroy(svc); return BT_ERROR_NONE; } int bt_gatt_server_unregister_all_services(bt_gatt_server_h server) { - bt_gatt_server_s *serv = (bt_gatt_server_s *)server; int ret = BT_ERROR_NONE; + bt_gatt_server_s *serv = (bt_gatt_server_s*)server; + BT_CHECK_INIT_STATUS(); BT_CHECK_GATT_SERVER_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(server); @@ -2313,8 +2564,13 @@ int bt_gatt_server_send_response(int request_id, bluetooth_gatt_att_request_type int ret = BT_ERROR_NONE; BT_CHECK_INIT_STATUS(); - if (value_length < 0) - return BT_ERROR_INVALID_PARAMETER; + if (request_type == BLUETOOTH_GATT_REQUEST_TYPE_READ && + resp_status == BT_ERROR_NONE) { + BT_CHECK_INPUT_PARAMETER(value); + + if (value_length < 0) + return BT_ERROR_INVALID_PARAMETER; + } ret = _bt_get_error_code(bluetooth_gatt_send_response(request_id, request_type, resp_status, @@ -2451,6 +2707,7 @@ int bt_gatt_client_create(const char *remote_address, bt_gatt_client_h *client) { int ret = BT_ERROR_NONE; bt_gatt_client_s *client_s; + bool connected = false; GSList *l; BT_CHECK_GATT_SUPPORT(); @@ -2473,7 +2730,6 @@ int bt_gatt_client_create(const char *remote_address, bt_gatt_client_h *client) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; } - memset(client_s, 0x00, sizeof(*client_s)); client_s->remote_address = g_strdup(remote_address); if (client_s->remote_address == NULL) { @@ -2482,14 +2738,20 @@ int bt_gatt_client_create(const char *remote_address, bt_gatt_client_h *client) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; } - client_s->services_discovered = false; *client = (bt_gatt_client_h)client_s; gatt_client_list = g_slist_append(gatt_client_list, client_s); + if (bt_device_is_profile_connected(remote_address, BT_PROFILE_GATT, + &connected) != BT_ERROR_NONE) + BT_ERR("bt_device_is_profile_connected is failed"); + else + client_s->connected = connected; + + if (_bt_gatt_client_update_services(*client) == BT_ERROR_NONE) + client_s->services_discovered = true; - if (_bt_gatt_client_update_all(*client) == BT_ERROR_NONE) - client_s->services_discovered = true; + BT_INFO("GATT Client Handle is created"); return ret; /* LCOV_EXCL_STOP */ } @@ -2638,17 +2900,24 @@ int bt_gatt_client_write_value(bt_gatt_h gatt_handle, chr->path, (guint8 *)chr->value, chr->value_length, BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE)); +/* After ACR for BT_GATT_WRITE_TYPE_SIGNED_WRITE, will enable this code */ +#if 0 + + else if (chr->write_type == BT_GATT_WRITE_TYPE_SIGNED_WRITE) + ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( + chr->path, (guint8 *)chr->value, chr->value_length, + BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES)); +#endif else { BT_ERR("Unknow write type : %d", chr->write_type); + BT_ERR("path : %s", chr->path); ret = BT_ERROR_OPERATION_FAILED; } if (ret != BT_ERROR_NONE) { g_free(cb_data); BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } else { - if (chr->write_type != BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE) - _bt_set_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC, - callback, cb_data); + _bt_set_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC, callback, cb_data); } } else if (c->type == BT_GATT_TYPE_DESCRIPTOR) { bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; @@ -2659,11 +2928,9 @@ int bt_gatt_client_write_value(bt_gatt_h gatt_handle, desc->value_length)); if (ret != BT_ERROR_NONE) { g_free(cb_data); - BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } else { - _bt_set_cb(BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR, - callback, cb_data); + _bt_set_cb(BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR, callback, cb_data); } } else { BT_ERR("Invalid handle type for write "); diff --git a/src/bluetooth-hid.c b/src/bluetooth-hid.c index fd38b0a..0b8a11f 100644 --- a/src/bluetooth-hid.c +++ b/src/bluetooth-hid.c @@ -318,18 +318,21 @@ int bt_hid_device_send_rc_key_event(const char *remote_address, if (ret <= 0) { if (ret == -1) { /* write fail case */ - if (errno == EACCES || errno == EPERM) + if (errno == EACCES || errno == EPERM) { set_last_result(BT_ERROR_PERMISSION_DENIED); - else if (errno == EAGAIN || errno == EWOULDBLOCK) + BT_ERR("PERMISSION_DENIED, errno = %d", errno); + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { set_last_result(BT_ERROR_AGAIN); - else + BT_ERR("BT_ERROR_AGAIN, errno = %d", errno); + } else { set_last_result(BT_ERROR_OPERATION_FAILED); + BT_ERR("BT_ERROR_OPERATION_FAILED, errno = %d", errno); + } } else { ret = _bt_get_error_code(ret); set_last_result(ret); + BT_ERR("Write failed, ret = %d", ret); } - - BT_ERR("Write failed, ret = %d", ret); } return ret; @@ -345,24 +348,28 @@ int bt_hid_device_reply_to_report(const char *remote_address, BT_CHECK_HID_DEVICE_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(remote_address); + BT_CHECK_INPUT_PARAMETER(data); ret = bluetooth_hid_device_reply_to_report(remote_address, header_type, param_type, data, data_len); if (ret <= 0) { if (ret == -1) { /* write fail case */ - if (errno == EACCES || errno == EPERM) + if (errno == EACCES || errno == EPERM) { set_last_result(BT_ERROR_PERMISSION_DENIED); - else if (errno == EAGAIN || errno == EWOULDBLOCK) + BT_ERR("PERMISSION_DENIED, errno = %d", errno); + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { set_last_result(BT_ERROR_AGAIN); - else + BT_ERR("BT_ERROR_AGAIN, errno = %d", errno); + } else { set_last_result(BT_ERROR_OPERATION_FAILED); + BT_ERR("BT_ERROR_OPERATION_FAILED, errno = %d", errno); + } } else { ret = _bt_get_error_code(ret); set_last_result(ret); + BT_ERR("Write failed, ret = %d", ret); } - - BT_ERR("Write failed, ret = %d", ret); } return ret; diff --git a/src/bluetooth-socket.c b/src/bluetooth-socket.c index bd5d86d..c141dc3 100644 --- a/src/bluetooth-socket.c +++ b/src/bluetooth-socket.c @@ -237,18 +237,21 @@ int bt_socket_send_data(int socket_fd, const char *data, int length) if (ret <= 0) { if (ret == -1) { /* write fail case */ - if (errno == EACCES || errno == EPERM) + if (errno == EACCES || errno == EPERM) { set_last_result(BT_ERROR_PERMISSION_DENIED); - else if (errno == EAGAIN || errno == EWOULDBLOCK) + BT_ERR("PERMISSION_DENIED, errno = %d", errno); + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { set_last_result(BT_ERROR_AGAIN); - else + BT_ERR("BT_ERROR_AGAIN, errno = %d", errno); + } else { set_last_result(BT_ERROR_OPERATION_FAILED); + BT_ERR("BT_ERROR_OPERATION_FAILED, errno = %d", errno); + } } else { ret = _bt_get_error_code(ret); set_last_result(ret); + BT_ERR("Write failed, ret = %d", ret); } - - BT_ERR("Write failed, ret = %d", ret); } return ret; /* LCOV_EXCL_STOP */ diff --git a/test/bt_unit_test.c b/test/bt_unit_test.c index d3c1a32..ac374b5 100644 --- a/test/bt_unit_test.c +++ b/test/bt_unit_test.c @@ -2090,7 +2090,7 @@ bool __bt_gatt_print_info_cb(int total, char *str = NULL; bt_gatt_get_uuid(gatt_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); TC_PRT("[%d / %d] %s (%s)", index, total, @@ -2109,7 +2109,7 @@ void __bt_gatt_client_write_complete_cb(int result, char *str = NULL; bt_gatt_get_uuid(gatt_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); TC_PRT("Write %s for %s (%s)", result == BT_ERROR_NONE ? "Success" : "Fail", @@ -2128,7 +2128,7 @@ void __bt_gatt_client_read_complete_cb(int result, char *str = NULL; bt_gatt_get_uuid(gatt_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); TC_PRT("Read %s for %s (%s)", result == BT_ERROR_NONE ? "Success" : "Fail", @@ -2152,7 +2152,7 @@ bool __bt_gatt_client_foreach_desc_cb(int total, char *str = NULL; bt_gatt_get_uuid(desc_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); TC_PRT("\t\t[%d / %d] %s (%s)", index, total, @@ -2171,13 +2171,13 @@ bool __bt_gatt_client_foreach_chr_cb(int total, int ret; char *uuid = NULL; char *str = NULL; + int properties = 0; bt_gatt_get_uuid(chr_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); + bt_gatt_characteristic_get_properties(chr_handle, &properties); - TC_PRT("\t[%d / %d] %s (%s)", - index, total, - str ? str : "Unknown", uuid); + TC_PRT("\t[%d / %d] %s (%s) (0x%X)", index, total, str ? str : "Unknown", uuid, properties); __bt_gatt_client_print_value(chr_handle); g_free(str); @@ -2204,7 +2204,7 @@ bool __bt_gatt_client_foreach_svc_cb(int total, char *str = NULL; bt_gatt_get_uuid(svc_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); TC_PRT("[%d / %d] %s (%s)", index, total, @@ -2241,7 +2241,7 @@ bool __bt_hps_client_svc_cb(int total, char *str = NULL; bt_gatt_get_uuid(svc_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); if (!g_strcmp0(uuid, HPS_UUID)) { @@ -2400,7 +2400,7 @@ bool __bt_gatt_server_foreach_svc_cb(int total, char *str = NULL; bt_gatt_get_uuid(svc_handle, &uuid); - bt_gatt_get_uuid_specification_name(uuid, &str); + bt_get_uuid_name(uuid, &str); TC_PRT("[%d / %d] %s (%s)", index, total, str ? str : "Unknown", uuid); @@ -2468,7 +2468,7 @@ bool __bt_gatt_included_service_cb(bt_gatt_attribute_h service, bt_gatt_get_characteristic_declaration(service, &uuid, &value, &value_length); - bt_gatt_get_uuid_specification_name(uuid, &name); + bt_get_uuid_name(uuid, &name); TC_PRT("uuid: %s [%s]", uuid, name); g_free(uuid); @@ -6588,7 +6588,7 @@ int test_input_callback(void *data) if (ret < BT_ERROR_NONE) { TC_PRT("returns %s\n", __bt_get_error_message(ret)); } else { - bt_gatt_get_uuid_specification_name(uuid, &name); + bt_get_uuid_name(uuid, &name); TC_PRT("uuid: %s [%s]", uuid, name); g_free(name); g_free(uuid); @@ -6639,7 +6639,7 @@ int test_input_callback(void *data) if (ret < BT_ERROR_NONE) { TC_PRT("returns %s\n", __bt_get_error_message(ret)); } else { - bt_gatt_get_uuid_specification_name(uuid, &name); + bt_get_uuid_name(uuid, &name); TC_PRT("uuid: %s [%s]", uuid, name); for (i = 0; i < value_length; i++) |