diff --git a/components/bt/bluedroid/api/esp_blufi_api.c b/components/bt/bluedroid/api/esp_blufi_api.c index 70f5c9ce8..2fcbbab79 100644 --- a/components/bt/bluedroid/api/esp_blufi_api.c +++ b/components/bt/bluedroid/api/esp_blufi_api.c @@ -25,9 +25,9 @@ esp_err_t esp_blufi_register_callbacks(esp_blufi_callbacks_t *callbacks) { if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + if (callbacks == NULL) { return ESP_FAIL; } @@ -42,9 +42,9 @@ esp_err_t esp_blufi_send_wifi_conn_report(wifi_mode_t opmode, esp_blufi_sta_conn btc_blufi_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_BLUFI; msg.act = BTC_BLUFI_ACT_SEND_CFG_REPORT; @@ -62,9 +62,9 @@ esp_err_t esp_blufi_profile_init(void) btc_msg_t msg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_BLUFI; msg.act = BTC_BLUFI_ACT_INIT; @@ -77,9 +77,9 @@ esp_err_t esp_blufi_profile_deinit(void) btc_msg_t msg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_BLUFI; msg.act = BTC_BLUFI_ACT_DEINIT; diff --git a/components/bt/bluedroid/api/esp_bt_main.c b/components/bt/bluedroid/api/esp_bt_main.c index 3093b5640..c9fe4fc06 100644 --- a/components/bt/bluedroid/api/esp_bt_main.c +++ b/components/bt/bluedroid/api/esp_bt_main.c @@ -24,13 +24,13 @@ static bool esp_already_init = false; esp_bluedroid_status_t esp_bluedroid_get_status(void) { if (esp_already_init) { - if (esp_already_enable) { - return ESP_BLUEDROID_STATUS_ENABLED; - } else { - return ESP_BLUEDROID_STATUS_INITIALIZED; - } + if (esp_already_enable) { + return ESP_BLUEDROID_STATUS_ENABLED; + } else { + return ESP_BLUEDROID_STATUS_INITIALIZED; + } } else { - return ESP_BLUEDROID_STATUS_UNINITIALIZED; + return ESP_BLUEDROID_STATUS_UNINITIALIZED; } } diff --git a/components/bt/bluedroid/api/esp_gap_ble_api.c b/components/bt/bluedroid/api/esp_gap_ble_api.c index f9401d8c4..56bedc424 100644 --- a/components/bt/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/bluedroid/api/esp_gap_ble_api.c @@ -25,7 +25,7 @@ esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback) { if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } return (btc_profile_cb_set(BTC_PID_GAP_BLE, callback) == 0 ? ESP_OK : ESP_FAIL); } @@ -37,7 +37,7 @@ esp_err_t esp_ble_gap_config_adv_data(esp_ble_adv_data_t *adv_data) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } if (adv_data == NULL) { @@ -64,7 +64,7 @@ esp_err_t esp_ble_gap_set_scan_params(esp_ble_scan_params_t *scan_params) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } if (scan_params == NULL) { @@ -85,7 +85,7 @@ esp_err_t esp_ble_gap_start_scanning(uint32_t duration) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -102,7 +102,7 @@ esp_err_t esp_ble_gap_stop_scanning(void) btc_msg_t msg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -116,8 +116,8 @@ esp_err_t esp_ble_gap_start_advertising(esp_ble_adv_params_t *adv_params) btc_msg_t msg; btc_ble_gap_args_t arg; - if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -133,7 +133,7 @@ esp_err_t esp_ble_gap_stop_advertising(void) btc_msg_t msg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -150,7 +150,7 @@ esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -167,7 +167,7 @@ esp_err_t esp_ble_gap_set_pkt_data_len(esp_bd_addr_t remote_device, uint16_t tx_ btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -186,7 +186,7 @@ esp_err_t esp_ble_gap_set_rand_addr(esp_bd_addr_t rand_addr) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -204,7 +204,7 @@ esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -221,9 +221,9 @@ esp_err_t esp_ble_gap_set_device_name(const char *name) btc_ble_gap_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + if (strlen(name) > ESP_GAP_DEVICE_NAME_MAX) { return ESP_ERR_INVALID_ARG; } diff --git a/components/bt/bluedroid/api/esp_gattc_api.c b/components/bt/bluedroid/api/esp_gattc_api.c index 8b9cc99e8..4f68d81cc 100644 --- a/components/bt/bluedroid/api/esp_gattc_api.c +++ b/components/bt/bluedroid/api/esp_gattc_api.c @@ -23,9 +23,9 @@ esp_err_t esp_ble_gattc_register_callback(esp_gattc_cb_t callback) { if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + if (callback == NULL) { return ESP_FAIL; } @@ -40,9 +40,9 @@ esp_err_t esp_ble_gattc_app_register(uint16_t app_id) btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + if (app_id > ESP_APP_ID_MAX) { return ESP_ERR_INVALID_ARG; } @@ -61,7 +61,7 @@ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if) btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -78,9 +78,9 @@ esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, b btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_OPEN; @@ -97,7 +97,7 @@ esp_err_t esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id) btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -114,7 +114,7 @@ esp_err_t esp_ble_gattc_config_mtu (esp_gatt_if_t gattc_if, uint16_t conn_id, ui btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } if ((mtu < ESP_GATT_DEF_BLE_MTU_SIZE) || (mtu > ESP_GATT_MAX_MTU_SIZE)) { @@ -136,7 +136,7 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -163,7 +163,7 @@ esp_err_t esp_ble_gattc_get_characteristic(esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -192,9 +192,9 @@ esp_err_t esp_ble_gattc_get_descriptor(esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; @@ -223,7 +223,7 @@ esp_err_t esp_ble_gattc_get_included_service(esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -253,7 +253,7 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -278,7 +278,7 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -299,14 +299,14 @@ esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if, esp_gatt_id_t *char_id, uint16_t value_len, uint8_t *value, - esp_gatt_write_type_t write_type, + esp_gatt_write_type_t write_type, esp_gatt_auth_req_t auth_req) { btc_msg_t msg; btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -330,16 +330,16 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, esp_gatt_id_t *descr_id, uint16_t value_len, uint8_t *value, - esp_gatt_write_type_t write_type, + esp_gatt_write_type_t write_type, esp_gatt_auth_req_t auth_req) { btc_msg_t msg; btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_WRITE_CHAR_DESCR; @@ -369,7 +369,7 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -392,7 +392,7 @@ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -413,7 +413,7 @@ esp_gatt_status_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -436,7 +436,7 @@ esp_gatt_status_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if, btc_ble_gattc_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; diff --git a/components/bt/bluedroid/api/esp_gatts_api.c b/components/bt/bluedroid/api/esp_gatts_api.c index 71b5a4338..f5ebe59a2 100644 --- a/components/bt/bluedroid/api/esp_gatts_api.c +++ b/components/bt/bluedroid/api/esp_gatts_api.c @@ -22,10 +22,11 @@ #define COPY_TO_GATTS_ARGS(_gatt_args, _arg, _arg_type) memcpy(_gatt_args, _arg, sizeof(_arg_type)) + esp_err_t esp_ble_gatts_register_callback(esp_gatts_cb_t callback) { if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } return (btc_profile_cb_set(BTC_PID_GATTS, callback) == 0 ? ESP_OK : ESP_FAIL); } @@ -36,7 +37,7 @@ esp_err_t esp_ble_gatts_app_register(uint16_t app_id) btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } //if (app_id < ESP_APP_ID_MIN || app_id > ESP_APP_ID_MAX) { @@ -59,9 +60,9 @@ esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatts_if) btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTS; msg.act = BTC_GATTS_ACT_APP_UNREGISTER; @@ -77,7 +78,7 @@ esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if, btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -90,6 +91,26 @@ esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if, return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db, + esp_gatt_if_t gatts_if, + uint8_t max_nb_attr, + uint8_t srvc_inst_id) +{ + btc_msg_t msg; + btc_ble_gatts_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GATTS; + msg.act = BTC_GATTS_ACT_CREATE_ATTR_TAB; + arg.create_attr_tab.gatts_if = gatts_if; + arg.create_attr_tab.max_nb_attr = max_nb_attr; + arg.create_attr_tab.srvc_inst_id = srvc_inst_id; + arg.create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)gatts_attr_db; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t included_service_handle) { @@ -97,7 +118,7 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -111,46 +132,69 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid, - esp_gatt_perm_t perm, esp_gatt_char_prop_t property) + esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val, + esp_attr_control_t *control) { btc_msg_t msg; btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + + memset(&arg, 0, sizeof(btc_ble_gatts_args_t)); msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTS; msg.act = BTC_GATTS_ACT_ADD_CHAR; arg.add_char.service_handle = service_handle; arg.add_char.perm = perm; arg.add_char.property = property; + if (char_val != NULL) { + arg.add_char.char_val.attr_max_len = char_val->attr_max_len; + arg.add_char.char_val.attr_len = char_val->attr_len; + arg.add_char.char_val.attr_value = char_val->attr_value; + } + + if (control != NULL) { + arg.add_char.attr_control.auto_rsp = control->auto_rsp; + } memcpy(&arg.add_char.char_uuid, char_uuid, sizeof(esp_bt_uuid_t)); - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle, esp_bt_uuid_t *descr_uuid, - esp_gatt_perm_t perm) + esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val, + esp_attr_control_t *control) { btc_msg_t msg; btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } + memset(&arg, 0, sizeof(btc_ble_gatts_args_t)); msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTS; msg.act = BTC_GATTS_ACT_ADD_CHAR_DESCR; arg.add_descr.service_handle = service_handle; arg.add_descr.perm = perm; + + if (char_descr_val != NULL) { + arg.add_descr.descr_val.attr_max_len = char_descr_val->attr_max_len; + arg.add_descr.descr_val.attr_len = char_descr_val->attr_len; + arg.add_descr.descr_val.attr_value = char_descr_val->attr_value; + } + + if (control != NULL) { + arg.add_descr.attr_control.auto_rsp = control->auto_rsp; + } memcpy(&arg.add_descr.descr_uuid, descr_uuid, sizeof(esp_bt_uuid_t)); - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle) @@ -159,7 +203,7 @@ esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle) btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -176,7 +220,7 @@ esp_err_t esp_ble_gatts_start_service(uint16_t service_handle) btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -193,9 +237,9 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle) btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTS; msg.act = BTC_GATTS_ACT_STOP_SERVICE; @@ -212,7 +256,7 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -224,7 +268,8 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, arg.send_ind.value_len = value_len; arg.send_ind.value = value; - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), + btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id, @@ -234,7 +279,7 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -245,7 +290,32 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, arg.send_rsp.status = status; arg.send_rsp.rsp = rsp; - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), + btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value) +{ + btc_msg_t msg; + btc_ble_gatts_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GATTS; + msg.act = BTC_GATTS_ACT_SET_ATTR_VALUE; + arg.set_attr_val.length = length; + arg.set_attr_val.value = (uint8_t *)value; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), + btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value) +{ + if (attr_handle == ESP_GATT_ILLEGAL_HANDLE) { + return ESP_FAIL; + } + btc_gatts_get_attr_value(attr_handle, length, (uint8_t **)value); + return ESP_OK; } esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct) @@ -254,7 +324,7 @@ esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, b btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } msg.sig = BTC_SIG_API_CALL; @@ -264,7 +334,8 @@ esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, b arg.open.is_direct = is_direct; memcpy(&arg.open.remote_bda, remote_bda, sizeof(esp_bd_addr_t)); - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id) @@ -273,13 +344,14 @@ esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id) btc_ble_gatts_args_t arg; if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { - return ESP_ERR_INVALID_STATE; + return ESP_ERR_INVALID_STATE; } - + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTS; msg.act = BTC_GATTS_ACT_CLOSE; arg.close.conn_id = BTC_GATT_CREATE_CONN_ID(gatts_if, conn_id); - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } diff --git a/components/bt/bluedroid/api/include/esp_gap_ble_api.h b/components/bt/bluedroid/api/include/esp_gap_ble_api.h index f92143e6a..1d27edb88 100644 --- a/components/bt/bluedroid/api/include/esp_gap_ble_api.h +++ b/components/bt/bluedroid/api/include/esp_gap_ble_api.h @@ -40,42 +40,44 @@ extern "C" { /// GAP BLE callback event type typedef enum { - ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT = 0, /*!< When advertising data set complete, the event comes */ - ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT , /*!< When scan response data set complete, the event comes */ - ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT, /*!< When scan parameters set complete, the event comes */ - ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */ + ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT = 0, /*!< When advertising data set complete, the event comes */ + ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT, /*!< When scan response data set complete, the event comes */ + ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT, /*!< When scan parameters set complete, the event comes */ + ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */ } esp_gap_ble_cb_event_t; /// Advertising data maximum length -#define ESP_BLE_ADV_DATA_LEN_MAX 31 +#define ESP_BLE_ADV_DATA_LEN_MAX 31 +/// Scan response data maximum length +#define ESP_BLE_SCAN_RSP_DATA_LEN_MAX 31 /// The type of advertising data(not adv_type) typedef enum { - ESP_BLE_AD_TYPE_FLAG = 0x01, - ESP_BLE_AD_TYPE_16SRV_PART = 0x02, - ESP_BLE_AD_TYPE_16SRV_CMPL = 0x03, - ESP_BLE_AD_TYPE_32SRV_PART = 0x04, - ESP_BLE_AD_TYPE_32SRV_CMPL = 0x05, - ESP_BLE_AD_TYPE_128SRV_PART = 0x06, - ESP_BLE_AD_TYPE_128SRV_CMPL = 0x07, - ESP_BLE_AD_TYPE_NAME_SHORT = 0x08, - ESP_BLE_AD_TYPE_NAME_CMPL = 0x09, - ESP_BLE_AD_TYPE_TX_PWR = 0x0A, - ESP_BLE_AD_TYPE_DEV_CLASS = 0x0D, - ESP_BLE_AD_TYPE_SM_TK = 0x10, - ESP_BLE_AD_TYPE_SM_OOB_FLAG = 0x11, - ESP_BLE_AD_TYPE_INT_RANGE = 0x12, - ESP_BLE_AD_TYPE_SOL_SRV_UUID = 0x14, - ESP_BLE_AD_TYPE_128SOL_SRV_UUID = 0x15, - ESP_BLE_AD_TYPE_SERVICE_DATA = 0x16, - ESP_BLE_AD_TYPE_PUBLIC_TARGET = 0x17, - ESP_BLE_AD_TYPE_RANDOM_TARGET = 0x18, - ESP_BLE_AD_TYPE_APPEARANCE = 0x19, - ESP_BLE_AD_TYPE_ADV_INT = 0x1A, - ESP_BLE_AD_TYPE_32SOL_SRV_UUID = 0x1B, - ESP_BLE_AD_TYPE_32SERVICE_DATA = 0x1C, - ESP_BLE_AD_TYPE_128SERVICE_DATA = 0x1D, - ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE = 0xFF, + ESP_BLE_AD_TYPE_FLAG = 0x01, + ESP_BLE_AD_TYPE_16SRV_PART = 0x02, + ESP_BLE_AD_TYPE_16SRV_CMPL = 0x03, + ESP_BLE_AD_TYPE_32SRV_PART = 0x04, + ESP_BLE_AD_TYPE_32SRV_CMPL = 0x05, + ESP_BLE_AD_TYPE_128SRV_PART = 0x06, + ESP_BLE_AD_TYPE_128SRV_CMPL = 0x07, + ESP_BLE_AD_TYPE_NAME_SHORT = 0x08, + ESP_BLE_AD_TYPE_NAME_CMPL = 0x09, + ESP_BLE_AD_TYPE_TX_PWR = 0x0A, + ESP_BLE_AD_TYPE_DEV_CLASS = 0x0D, + ESP_BLE_AD_TYPE_SM_TK = 0x10, + ESP_BLE_AD_TYPE_SM_OOB_FLAG = 0x11, + ESP_BLE_AD_TYPE_INT_RANGE = 0x12, + ESP_BLE_AD_TYPE_SOL_SRV_UUID = 0x14, + ESP_BLE_AD_TYPE_128SOL_SRV_UUID = 0x15, + ESP_BLE_AD_TYPE_SERVICE_DATA = 0x16, + ESP_BLE_AD_TYPE_PUBLIC_TARGET = 0x17, + ESP_BLE_AD_TYPE_RANDOM_TARGET = 0x18, + ESP_BLE_AD_TYPE_APPEARANCE = 0x19, + ESP_BLE_AD_TYPE_ADV_INT = 0x1A, + ESP_BLE_AD_TYPE_32SOL_SRV_UUID = 0x1B, + ESP_BLE_AD_TYPE_32SERVICE_DATA = 0x1C, + ESP_BLE_AD_TYPE_128SERVICE_DATA = 0x1D, + ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE = 0xFF, } esp_ble_adv_data_type; /// Advertising mode @@ -109,37 +111,37 @@ typedef enum { /// Advertising parameters typedef struct { - uint16_t adv_int_min; /*!< Minimum advertising interval for - undirected and low duty cycle directed advertising. - Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second) - Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec */ - uint16_t adv_int_max; /*!< Maximum advertising interval for - undirected and low duty cycle directed advertising. - Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second) - Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec Advertising max interval */ - esp_ble_adv_type_t adv_type; /*!< Advertising type */ - esp_ble_addr_type_t own_addr_type; /*!< Owner bluetooth device address type */ - esp_bd_addr_t peer_addr; /*!< Peer device bluetooth device address */ - esp_ble_addr_type_t peer_addr_type; /*!< Peer device bluetooth device address type */ - esp_ble_adv_channel_t channel_map; /*!< Advertising channel map */ - esp_ble_adv_filter_t adv_filter_policy; /*!< Advertising filter policy */ + uint16_t adv_int_min; /*!< Minimum advertising interval for + undirected and low duty cycle directed advertising. + Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second) + Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec */ + uint16_t adv_int_max; /*!< Maximum advertising interval for + undirected and low duty cycle directed advertising. + Range: 0x0020 to 0x4000 Default: N = 0x0800 (1.28 second) + Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec Advertising max interval */ + esp_ble_adv_type_t adv_type; /*!< Advertising type */ + esp_ble_addr_type_t own_addr_type; /*!< Owner bluetooth device address type */ + esp_bd_addr_t peer_addr; /*!< Peer device bluetooth device address */ + esp_ble_addr_type_t peer_addr_type; /*!< Peer device bluetooth device address type */ + esp_ble_adv_channel_t channel_map; /*!< Advertising channel map */ + esp_ble_adv_filter_t adv_filter_policy; /*!< Advertising filter policy */ } esp_ble_adv_params_t; /// Advertising data content, according to "Supplement to the Bluetooth Core Specification" typedef struct { - bool set_scan_rsp; /*!< Set this advertising data as scan response or not*/ - bool include_name; /*!< Advertising data include device name or not */ - bool include_txpower; /*!< Advertising data include TX power */ - int min_interval; /*!< Advertising data show advertising min interval */ - int max_interval; /*!< Advertising data show advertising max interval */ - int appearance; /*!< External appearance of device */ - uint16_t manufacturer_len; /*!< Manufacturer data length */ - uint8_t *p_manufacturer_data; /*!< Manufacturer data point */ - uint16_t service_data_len; /*!< Service data length */ - uint8_t *p_service_data; /*!< Service data point */ - uint16_t service_uuid_len; /*!< Service uuid length */ - uint8_t *p_service_uuid; /*!< Service uuid array point */ - uint8_t flag; /*!< Advertising flag of discovery mode, see BLE_ADV_DATA_FLAG detail */ + bool set_scan_rsp; /*!< Set this advertising data as scan response or not*/ + bool include_name; /*!< Advertising data include device name or not */ + bool include_txpower; /*!< Advertising data include TX power */ + int min_interval; /*!< Advertising data show advertising min interval */ + int max_interval; /*!< Advertising data show advertising max interval */ + int appearance; /*!< External appearance of device */ + uint16_t manufacturer_len; /*!< Manufacturer data length */ + uint8_t *p_manufacturer_data; /*!< Manufacturer data point */ + uint16_t service_data_len; /*!< Service data length */ + uint8_t *p_service_data; /*!< Service data point */ + uint16_t service_uuid_len; /*!< Service uuid length */ + uint8_t *p_service_uuid; /*!< Service uuid array point */ + uint8_t flag; /*!< Advertising flag of discovery mode, see BLE_ADV_DATA_FLAG detail */ } esp_ble_adv_data_t; /// Own BD address source of the device @@ -160,53 +162,53 @@ typedef enum { /// Ble scan type typedef enum { - BLE_SCAN_TYPE_PASSIVE = 0x0, /*!< Passive scan */ - BLE_SCAN_TYPE_ACTIVE = 0x1, /*!< Active scan */ + BLE_SCAN_TYPE_PASSIVE = 0x0, /*!< Passive scan */ + BLE_SCAN_TYPE_ACTIVE = 0x1, /*!< Active scan */ } esp_ble_scan_type_t; /// Ble scan filter type typedef enum { - BLE_SCAN_FILTER_ALLOW_ALL = 0x0, /*!< Accept all : - 1. advertisement packets except directed advertising packets not addressed to this device (default). */ + BLE_SCAN_FILTER_ALLOW_ALL = 0x0, /*!< Accept all : + 1. advertisement packets except directed advertising packets not addressed to this device (default). */ BLE_SCAN_FILTER_ALLOW_ONLY_WLST = 0x1, /*!< Accept only : - 1. advertisement packets from devices where the advertiser’s address is in the White list. - 2. Directed advertising packets which are not addressed for this device shall be ignored. */ + 1. advertisement packets from devices where the advertiser’s address is in the White list. + 2. Directed advertising packets which are not addressed for this device shall be ignored. */ BLE_SCAN_FILTER_ALLOW_UND_RPA_DIR = 0x2, /*!< Accept all : - 1. undirected advertisement packets, and - 2. directed advertising packets where the initiator address is a resolvable private address, and - 3. directed advertising packets addressed to this device. */ + 1. undirected advertisement packets, and + 2. directed advertising packets where the initiator address is a resolvable private address, and + 3. directed advertising packets addressed to this device. */ BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR = 0x3, /*!< Accept all : - 1. advertisement packets from devices where the advertiser’s address is in the White list, and - 2. directed advertising packets where the initiator address is a resolvable private address, and - 3. directed advertising packets addressed to this device.*/ + 1. advertisement packets from devices where the advertiser’s address is in the White list, and + 2. directed advertising packets where the initiator address is a resolvable private address, and + 3. directed advertising packets addressed to this device.*/ } esp_ble_scan_filter_t; /// Ble scan parameters typedef struct { - esp_ble_scan_type_t scan_type; /*!< Scan type */ - esp_ble_addr_type_t own_addr_type; /*!< Owner address type */ - esp_ble_scan_filter_t scan_filter_policy; /*!< Scan filter policy */ - uint16_t scan_interval; /*!< Scan interval. This is defined as the time interval from - when the Controller started its last LE scan until it begins the subsequent LE scan. - Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) - Time = N * 0.625 msec - Time Range: 2.5 msec to 10.24 seconds*/ - uint16_t scan_window; /*!< Scan window. The duration of the LE scan. LE_Scan_Window - shall be less than or equal to LE_Scan_Interval - Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) - Time = N * 0.625 msec - Time Range: 2.5 msec to 10240 msec */ + esp_ble_scan_type_t scan_type; /*!< Scan type */ + esp_ble_addr_type_t own_addr_type; /*!< Owner address type */ + esp_ble_scan_filter_t scan_filter_policy; /*!< Scan filter policy */ + uint16_t scan_interval; /*!< Scan interval. This is defined as the time interval from + when the Controller started its last LE scan until it begins the subsequent LE scan. + Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) + Time = N * 0.625 msec + Time Range: 2.5 msec to 10.24 seconds*/ + uint16_t scan_window; /*!< Scan window. The duration of the LE scan. LE_Scan_Window + shall be less than or equal to LE_Scan_Interval + Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) + Time = N * 0.625 msec + Time Range: 2.5 msec to 10240 msec */ } esp_ble_scan_params_t; /// Connection update parameters typedef struct { - esp_bd_addr_t bda; /*!< Bluetooth device address */ - uint16_t min_int; /*!< Min connection interval */ - uint16_t max_int; /*!< Max connection interval */ - uint16_t latency; /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */ - uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80. - Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec - Time Range: 100 msec to 32 seconds */ + esp_bd_addr_t bda; /*!< Bluetooth device address */ + uint16_t min_int; /*!< Min connection interval */ + uint16_t max_int; /*!< Max connection interval */ + uint16_t latency; /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */ + uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80. + Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec + Time Range: 100 msec to 32 seconds */ } esp_ble_conn_update_params_t; /// Sub Event of ESP_GAP_BLE_SCAN_RESULT_EVT @@ -225,11 +227,11 @@ typedef enum { * result is scan response or advertising data or other */ typedef enum { - ESP_BLE_EVT_CONN_ADV = 0x00, /*!< Connectable undirected advertising (ADV_IND) */ - ESP_BLE_EVT_CONN_DIR_ADV = 0x01, /*!< Connectable directed advertising (ADV_DIRECT_IND) */ - ESP_BLE_EVT_DISC_ADV = 0x02, /*!< Scannable undirected advertising (ADV_SCAN_IND) */ - ESP_BLE_EVT_NON_CONN_ADV = 0x03, /*!< Non connectable undirected advertising (ADV_NONCONN_IND) */ - ESP_BLE_EVT_SCAN_RSP = 0x04, /*!< Scan Response (SCAN_RSP) */ + ESP_BLE_EVT_CONN_ADV = 0x00, /*!< Connectable undirected advertising (ADV_IND) */ + ESP_BLE_EVT_CONN_DIR_ADV = 0x01, /*!< Connectable directed advertising (ADV_DIRECT_IND) */ + ESP_BLE_EVT_DISC_ADV = 0x02, /*!< Scannable undirected advertising (ADV_SCAN_IND) */ + ESP_BLE_EVT_NON_CONN_ADV = 0x03, /*!< Non connectable undirected advertising (ADV_NONCONN_IND) */ + ESP_BLE_EVT_SCAN_RSP = 0x04, /*!< Scan Response (SCAN_RSP) */ } esp_ble_evt_type_t; /** @@ -240,34 +242,34 @@ typedef union { * @brief ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT */ struct ble_adv_data_cmpl_evt_param { - esp_bt_status_t status; /*!< Indicate the set advertising data operation success status */ - } adv_data_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT */ + esp_bt_status_t status; /*!< Indicate the set advertising data operation success status */ + } adv_data_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT */ struct ble_scan_rsp_data_cmpl_evt_param { - esp_bt_status_t status; /*!< Indicate the set scan response data operation success status */ - } scan_rsp_data_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT */ + esp_bt_status_t status; /*!< Indicate the set scan response data operation success status */ + } scan_rsp_data_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT */ struct ble_scan_param_cmpl_evt_param { - esp_bt_status_t status; /*!< Indicate the set scan param operation success status */ - } scan_param_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT */ + esp_bt_status_t status; /*!< Indicate the set scan param operation success status */ + } scan_param_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_SCAN_RESULT_EVT */ struct ble_scan_result_evt_param { - esp_gap_search_evt_t search_evt; /*!< Search event type */ - esp_bd_addr_t bda; /*!< Bluetooth device address which has been searched */ - esp_bt_dev_type_t dev_type; /*!< Device type */ - esp_ble_addr_type_t ble_addr_type; /*!< Ble device address type */ - esp_ble_evt_type_t ble_evt_type; /*!< Ble scan result event type */ - int rssi; /*!< Searched device's RSSI */ - uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX]; /*!< Received EIR */ - int flag; /*!< Advertising data flag bit */ - int num_resps; /*!< Scan result number */ - } scan_rst; /*!< Event parameter of ESP_GAP_BLE_SCAN_RESULT_EVT */ + esp_gap_search_evt_t search_evt; /*!< Search event type */ + esp_bd_addr_t bda; /*!< Bluetooth device address which has been searched */ + esp_bt_dev_type_t dev_type; /*!< Device type */ + esp_ble_addr_type_t ble_addr_type; /*!< Ble device address type */ + esp_ble_evt_type_t ble_evt_type; /*!< Ble scan result event type */ + int rssi; /*!< Searched device's RSSI */ + uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX]; /*!< Received EIR */ + int flag; /*!< Advertising data flag bit */ + int num_resps; /*!< Scan result number */ + } scan_rst; /*!< Event parameter of ESP_GAP_BLE_SCAN_RESULT_EVT */ } esp_ble_gap_cb_param_t; /** @@ -440,7 +442,8 @@ esp_err_t esp_ble_gap_set_device_name(const char *name); * @param[in] type - finding ADV data type * @param[out] length - return the length of ADV data not including type * - * @return pointer of ADV data + * @return - ESP_OK : success + * - other : failed * */ uint8_t *esp_ble_resolve_adv_data(uint8_t *adv_data, uint8_t type, uint8_t *length); diff --git a/components/bt/bluedroid/api/include/esp_gatt_defs.h b/components/bt/bluedroid/api/include/esp_gatt_defs.h index 7b119a62c..153a70273 100644 --- a/components/bt/bluedroid/api/include/esp_gatt_defs.h +++ b/components/bt/bluedroid/api/include/esp_gatt_defs.h @@ -22,106 +22,141 @@ extern "C" { #endif /// GATT INVALID UUID -#define ESP_GATT_ILLEGAL_UUID 0 +#define ESP_GATT_ILLEGAL_UUID 0 +/// GATT INVALID HANDLE +#define ESP_GATT_ILLEGAL_HANDLE 0 +/// GATT attribute max handle +#define ESP_GATT_ATTR_HANDLE_MAX 100 + /**@{ * All "ESP_GATT_UUID_xxx" is attribute types */ -#define ESP_GATT_UUID_PRI_SERVICE 0x2800 -#define ESP_GATT_UUID_SEC_SERVICE 0x2801 -#define ESP_GATT_UUID_INCLUDE_SERVICE 0x2802 -#define ESP_GATT_UUID_CHAR_DECLARE 0x2803 /* Characteristic Declaration*/ +#define ESP_GATT_UUID_IMMEDIATE_ALERT_SVC 0x1802 /* Immediate alert Service*/ +#define ESP_GATT_UUID_LINK_LOSS_SVC 0x1803 /* Link Loss Service*/ +#define ESP_GATT_UUID_TX_POWER_SVC 0x1804 /* TX Power Service*/ +#define ESP_GATT_UUID_CURRENT_TIME_SVC 0x1805 /* Current Time Service Service*/ +#define ESP_GATT_UUID_REF_TIME_UPDATE_SVC 0x1806 /* Reference Time Update Service*/ +#define ESP_GATT_UUID_NEXT_DST_CHANGE_SVC 0x1807 /* Next DST Change Service*/ +#define ESP_GATT_UUID_GLUCOSE_SVC 0x1808 /* Glucose Service*/ +#define ESP_GATT_UUID_HEALTH_THERMOM_SVC 0x1809 /* Health Thermometer Service*/ +#define ESP_GATT_UUID_DEVICE_INFO_SVC 0x180A /* Device Information Service*/ +#define ESP_GATT_UUID_HEART_RATE_SVC 0x180D /* Heart Rate Service*/ +#define ESP_GATT_UUID_PHONE_ALERT_STATUS_SVC 0x180E /* Phone Alert Status Service*/ +#define ESP_GATT_UUID_BATTERY_SERVICE_SVC 0x180F /* Battery Service*/ +#define ESP_GATT_UUID_BLOOD_PRESSURE_SVC 0x1810 /* Blood Pressure Service*/ +#define ESP_GATT_UUID_ALERT_NTF_SVC 0x1811 /* Alert Notification Service*/ +#define ESP_GATT_UUID_HID_SVC 0x1812 /* HID Service*/ +#define ESP_GATT_UUID_SCAN_PARAMETERS_SVC 0x1813 /* Scan Parameters Service*/ +#define ESP_GATT_UUID_RUNNING_SPEED_CADENCE_SVC 0x1814 /* Running Speed and Cadence Service*/ +#define ESP_GATT_UUID_CYCLING_SPEED_CADENCE_SVC 0x1816 /* Cycling Speed and Cadence Service*/ +#define ESP_GATT_UUID_CYCLING_POWER_SVC 0x1818 /* Cycling Power Service*/ +#define ESP_GATT_UUID_LOCATION_AND_NAVIGATION_SVC 0x1819 /* Location and Navigation Service*/ +#define ESP_GATT_UUID_USER_DATA_SVC 0x181C /* User Data Service*/ +#define ESP_GATT_UUID_WEIGHT_SCALE_SVC 0x181D /* Weight Scale Service*/ -#define ESP_GATT_UUID_CHAR_EXT_PROP 0x2900 /* Characteristic Extended Properties */ -#define ESP_GATT_UUID_CHAR_DESCRIPTION 0x2901 /* Characteristic User Description*/ -#define ESP_GATT_UUID_CHAR_CLIENT_CONFIG 0x2902 /* Client Characteristic Configuration */ -#define ESP_GATT_UUID_CHAR_SRVR_CONFIG 0x2903 /* Server Characteristic Configuration */ -#define ESP_GATT_UUID_CHAR_PRESENT_FORMAT 0x2904 /* Characteristic Presentation Format*/ -#define ESP_GATT_UUID_CHAR_AGG_FORMAT 0x2905 /* Characteristic Aggregate Format*/ -#define ESP_GATT_UUID_CHAR_VALID_RANGE 0x2906 /* Characteristic Valid Range */ -#define ESP_GATT_UUID_EXT_RPT_REF_DESCR 0x2907 -#define ESP_GATT_UUID_RPT_REF_DESCR 0x2908 +#define ESP_GATT_UUID_PRI_SERVICE 0x2800 +#define ESP_GATT_UUID_SEC_SERVICE 0x2801 +#define ESP_GATT_UUID_INCLUDE_SERVICE 0x2802 +#define ESP_GATT_UUID_CHAR_DECLARE 0x2803 /* Characteristic Declaration*/ + +#define ESP_GATT_UUID_CHAR_EXT_PROP 0x2900 /* Characteristic Extended Properties */ +#define ESP_GATT_UUID_CHAR_DESCRIPTION 0x2901 /* Characteristic User Description*/ +#define ESP_GATT_UUID_CHAR_CLIENT_CONFIG 0x2902 /* Client Characteristic Configuration */ +#define ESP_GATT_UUID_CHAR_SRVR_CONFIG 0x2903 /* Server Characteristic Configuration */ +#define ESP_GATT_UUID_CHAR_PRESENT_FORMAT 0x2904 /* Characteristic Presentation Format*/ +#define ESP_GATT_UUID_CHAR_AGG_FORMAT 0x2905 /* Characteristic Aggregate Format*/ +#define ESP_GATT_UUID_CHAR_VALID_RANGE 0x2906 /* Characteristic Valid Range */ +#define ESP_GATT_UUID_EXT_RPT_REF_DESCR 0x2907 +#define ESP_GATT_UUID_RPT_REF_DESCR 0x2908 /* GAP Profile Attributes */ -#define ESP_GATT_UUID_GAP_DEVICE_NAME 0x2A00 -#define ESP_GATT_UUID_GAP_ICON 0x2A01 -#define ESP_GATT_UUID_GAP_PREF_CONN_PARAM 0x2A04 -#define ESP_GATT_UUID_GAP_CENTRAL_ADDR_RESOL 0x2AA6 +#define ESP_GATT_UUID_GAP_DEVICE_NAME 0x2A00 +#define ESP_GATT_UUID_GAP_ICON 0x2A01 +#define ESP_GATT_UUID_GAP_PREF_CONN_PARAM 0x2A04 +#define ESP_GATT_UUID_GAP_CENTRAL_ADDR_RESOL 0x2AA6 /* Attribute Profile Attribute UUID */ -#define ESP_GATT_UUID_GATT_SRV_CHGD 0x2A05 +#define ESP_GATT_UUID_GATT_SRV_CHGD 0x2A05 /* Link ESP_Loss Service */ -#define ESP_GATT_UUID_ALERT_LEVEL 0x2A06 /* Alert Level */ -#define ESP_GATT_UUID_TX_POWER_LEVEL 0x2A07 /* TX power level */ +#define ESP_GATT_UUID_ALERT_LEVEL 0x2A06 /* Alert Level */ +#define ESP_GATT_UUID_TX_POWER_LEVEL 0x2A07 /* TX power level */ /* Current Time Service */ -#define ESP_GATT_UUID_CURRENT_TIME 0x2A2B /* Current Time */ -#define ESP_GATT_UUID_LOCAL_TIME_INFO 0x2A0F /* Local time info */ -#define ESP_GATT_UUID_REF_TIME_INFO 0x2A14 /* reference time information */ +#define ESP_GATT_UUID_CURRENT_TIME 0x2A2B /* Current Time */ +#define ESP_GATT_UUID_LOCAL_TIME_INFO 0x2A0F /* Local time info */ +#define ESP_GATT_UUID_REF_TIME_INFO 0x2A14 /* reference time information */ /* Network availability Profile */ -#define ESP_GATT_UUID_NW_STATUS 0x2A18 /* network availability status */ -#define ESP_GATT_UUID_NW_TRIGGER 0x2A1A /* Network availability trigger */ +#define ESP_GATT_UUID_NW_STATUS 0x2A18 /* network availability status */ +#define ESP_GATT_UUID_NW_TRIGGER 0x2A1A /* Network availability trigger */ /* Phone alert */ -#define ESP_GATT_UUID_ALERT_STATUS 0x2A3F /* alert status */ -#define ESP_GATT_UUID_RINGER_CP 0x2A40 /* ringer control point */ -#define ESP_GATT_UUID_RINGER_SETTING 0x2A41 /* ringer setting */ +#define ESP_GATT_UUID_ALERT_STATUS 0x2A3F /* alert status */ +#define ESP_GATT_UUID_RINGER_CP 0x2A40 /* ringer control point */ +#define ESP_GATT_UUID_RINGER_SETTING 0x2A41 /* ringer setting */ /* Glucose Service */ -#define ESP_GATT_UUID_GM_MEASUREMENT 0x2A18 -#define ESP_GATT_UUID_GM_CONTEXT 0x2A34 -#define ESP_GATT_UUID_GM_CONTROL_POINT 0x2A52 -#define ESP_GATT_UUID_GM_FEATURE 0x2A51 +#define ESP_GATT_UUID_GM_MEASUREMENT 0x2A18 +#define ESP_GATT_UUID_GM_CONTEXT 0x2A34 +#define ESP_GATT_UUID_GM_CONTROL_POINT 0x2A52 +#define ESP_GATT_UUID_GM_FEATURE 0x2A51 /* device information characteristic */ -#define ESP_GATT_UUID_SYSTEM_ID 0x2A23 -#define ESP_GATT_UUID_MODEL_NUMBER_STR 0x2A24 -#define ESP_GATT_UUID_SERIAL_NUMBER_STR 0x2A25 -#define ESP_GATT_UUID_FW_VERSION_STR 0x2A26 -#define ESP_GATT_UUID_HW_VERSION_STR 0x2A27 -#define ESP_GATT_UUID_SW_VERSION_STR 0x2A28 -#define ESP_GATT_UUID_MANU_NAME 0x2A29 -#define ESP_GATT_UUID_IEEE_DATA 0x2A2A -#define ESP_GATT_UUID_PNP_ID 0x2A50 +#define ESP_GATT_UUID_SYSTEM_ID 0x2A23 +#define ESP_GATT_UUID_MODEL_NUMBER_STR 0x2A24 +#define ESP_GATT_UUID_SERIAL_NUMBER_STR 0x2A25 +#define ESP_GATT_UUID_FW_VERSION_STR 0x2A26 +#define ESP_GATT_UUID_HW_VERSION_STR 0x2A27 +#define ESP_GATT_UUID_SW_VERSION_STR 0x2A28 +#define ESP_GATT_UUID_MANU_NAME 0x2A29 +#define ESP_GATT_UUID_IEEE_DATA 0x2A2A +#define ESP_GATT_UUID_PNP_ID 0x2A50 /* HID characteristics */ -#define ESP_GATT_UUID_HID_INFORMATION 0x2A4A -#define ESP_GATT_UUID_HID_REPORT_MAP 0x2A4B -#define ESP_GATT_UUID_HID_CONTROL_POINT 0x2A4C -#define ESP_GATT_UUID_HID_REPORT 0x2A4D -#define ESP_GATT_UUID_HID_PROTO_MODE 0x2A4E -#define ESP_GATT_UUID_HID_BT_KB_INPUT 0x2A22 -#define ESP_GATT_UUID_HID_BT_KB_OUTPUT 0x2A32 -#define ESP_GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33 +#define ESP_GATT_UUID_HID_INFORMATION 0x2A4A +#define ESP_GATT_UUID_HID_REPORT_MAP 0x2A4B +#define ESP_GATT_UUID_HID_CONTROL_POINT 0x2A4C +#define ESP_GATT_UUID_HID_REPORT 0x2A4D +#define ESP_GATT_UUID_HID_PROTO_MODE 0x2A4E +#define ESP_GATT_UUID_HID_BT_KB_INPUT 0x2A22 +#define ESP_GATT_UUID_HID_BT_KB_OUTPUT 0x2A32 +#define ESP_GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33 + + /// Heart Rate Measurement +#define ESP_GATT_HEART_RATE_MEAS 0x2A37 +/// Body Sensor Location +#define ESP_GATT_BODY_SENSOR_LOCATION 0x2A38 +/// Heart Rate Control Point +#define ESP_GATT_HEART_RATE_CNTL_POINT 0x2A39 /* Battery Service characteristics */ -#define ESP_GATT_UUID_BATTERY_LEVEL 0x2A19 +#define ESP_GATT_UUID_BATTERY_LEVEL 0x2A19 /* Sensor Service */ -#define ESP_GATT_UUID_SC_CONTROL_POINT 0x2A55 -#define ESP_GATT_UUID_SENSOR_LOCATION 0x2A5D +#define ESP_GATT_UUID_SC_CONTROL_POINT 0x2A55 +#define ESP_GATT_UUID_SENSOR_LOCATION 0x2A5D /* Runners speed and cadence service */ -#define ESP_GATT_UUID_RSC_MEASUREMENT 0x2A53 -#define ESP_GATT_UUID_RSC_FEATURE 0x2A54 +#define ESP_GATT_UUID_RSC_MEASUREMENT 0x2A53 +#define ESP_GATT_UUID_RSC_FEATURE 0x2A54 /* Cycling speed and cadence service */ -#define ESP_GATT_UUID_CSC_MEASUREMENT 0x2A5B -#define ESP_GATT_UUID_CSC_FEATURE 0x2A5C +#define ESP_GATT_UUID_CSC_MEASUREMENT 0x2A5B +#define ESP_GATT_UUID_CSC_FEATURE 0x2A5C /* Scan ESP_Parameter characteristics */ -#define ESP_GATT_UUID_SCAN_INT_WINDOW 0x2A4F -#define ESP_GATT_UUID_SCAN_REFRESH 0x2A31 +#define ESP_GATT_UUID_SCAN_INT_WINDOW 0x2A4F +#define ESP_GATT_UUID_SCAN_REFRESH 0x2A31 /** * @} */ /// Attribute write data type from the client typedef enum { - ESP_GATT_PREP_WRITE_CANCEL = 0x00, /*!< Prepare write cancel */ - ESP_GATT_PREP_WRITE_EXEC = 0x01, /*!< Prepare write execute */ + ESP_GATT_PREP_WRITE_CANCEL = 0x00, /*!< Prepare write cancel */ + ESP_GATT_PREP_WRITE_EXEC = 0x01, /*!< Prepare write execute */ } esp_gatt_prep_write_type; /** @@ -178,23 +213,23 @@ typedef enum { * @brief Gatt Connection reason enum */ typedef enum { - ESP_GATT_CONN_UNKNOWN = 0, /*!< Gatt connection unknown */ - ESP_GATT_CONN_L2C_FAILURE = 1, /*!< General L2cap failure */ - ESP_GATT_CONN_TIMEOUT = 0x08, /*!< Connection timeout */ - ESP_GATT_CONN_TERMINATE_PEER_USER = 0x13, /*!< Connection terminate by peer user */ - ESP_GATT_CONN_TERMINATE_LOCAL_HOST = 0x16, /*!< Connectionterminated by local host */ - ESP_GATT_CONN_FAIL_ESTABLISH = 0x3e, /*!< Connection fail to establish */ - ESP_GATT_CONN_LMP_TIMEOUT = 0x22, /*!< Connection fail for LMP response tout */ - ESP_GATT_CONN_CONN_CANCEL = 0x0100, /*!< L2CAP connection cancelled */ - ESP_GATT_CONN_NONE = 0x0101 /*!< No connection to cancel */ + ESP_GATT_CONN_UNKNOWN = 0, /*!< Gatt connection unknown */ + ESP_GATT_CONN_L2C_FAILURE = 1, /*!< General L2cap failure */ + ESP_GATT_CONN_TIMEOUT = 0x08, /*!< Connection timeout */ + ESP_GATT_CONN_TERMINATE_PEER_USER = 0x13, /*!< Connection terminate by peer user */ + ESP_GATT_CONN_TERMINATE_LOCAL_HOST = 0x16, /*!< Connectionterminated by local host */ + ESP_GATT_CONN_FAIL_ESTABLISH = 0x3e, /*!< Connection fail to establish */ + ESP_GATT_CONN_LMP_TIMEOUT = 0x22, /*!< Connection fail for LMP response tout */ + ESP_GATT_CONN_CONN_CANCEL = 0x0100, /*!< L2CAP connection cancelled */ + ESP_GATT_CONN_NONE = 0x0101 /*!< No connection to cancel */ } esp_gatt_conn_reason_t; /** * @brief Gatt id, include uuid and instance id */ typedef struct { - esp_bt_uuid_t uuid; /*!< UUID */ - uint8_t inst_id; /*!< Instance id */ + esp_bt_uuid_t uuid; /*!< UUID */ + uint8_t inst_id; /*!< Instance id */ } __attribute__((packed)) esp_gatt_id_t; /** @@ -202,19 +237,19 @@ typedef struct { * (uuid and instance id) and primary flag */ typedef struct { - esp_gatt_id_t id; /*!< Gatt id, include uuid and instance */ - bool is_primary; /*!< This service is primary or not */ + esp_gatt_id_t id; /*!< Gatt id, include uuid and instance */ + bool is_primary; /*!< This service is primary or not */ } __attribute__((packed)) esp_gatt_srvc_id_t; /** * @brief Gatt authentication request type */ typedef enum { - ESP_GATT_AUTH_REQ_NONE = 0, - ESP_GATT_AUTH_REQ_NO_MITM = 1, /* unauthenticated encryption */ - ESP_GATT_AUTH_REQ_MITM = 2, /* authenticated encryption */ - ESP_GATT_AUTH_REQ_SIGNED_NO_MITM = 3, - ESP_GATT_AUTH_REQ_SIGNED_MITM = 4, + ESP_GATT_AUTH_REQ_NONE = 0, + ESP_GATT_AUTH_REQ_NO_MITM = 1, /* unauthenticated encryption */ + ESP_GATT_AUTH_REQ_MITM = 2, /* authenticated encryption */ + ESP_GATT_AUTH_REQ_SIGNED_NO_MITM = 3, + ESP_GATT_AUTH_REQ_SIGNED_MITM = 4, } esp_gatt_auth_req_t; /** @@ -246,32 +281,101 @@ typedef enum { /// GATT maximum attribute length #define ESP_GATT_MAX_ATTR_LEN 600 //as same as GATT_MAX_ATTR_LEN + +/** + * @brief Attribute description (used to create database) + */ + typedef struct + { + uint16_t uuid_length; /*!< UUID length */ + uint8_t *uuid_p; /*!< UUID value */ + uint16_t perm; /*!< Attribute permission */ + uint16_t max_length; /*!< Maximum length of the element*/ + uint16_t length; /*!< Current length of the element*/ + uint8_t *value; /*!< Element value array*/ + } esp_attr_desc_t; + + +/** + * @brief attribute auto respose flag + */ +typedef struct +{ +#define ESP_GATT_RSP_BY_APP 0 +#define ESP_GATT_AUTO_RSP 1 + uint8_t auto_rsp; /*!< need the app response to the client if need_rsp set to 1*/ +} esp_attr_control_t; + + +/** + * @brief attribute type added to the gatt server database + */ +typedef struct +{ + esp_attr_control_t attr_control; /*!< The attribue control type*/ + esp_attr_desc_t att_desc; /*!< The attribue type*/ +} esp_gatts_attr_db_t; + + +/** + * @brief set the attribute value type + */ +typedef struct +{ + uint16_t attr_max_len; /*!< attribute max value length */ + uint16_t attr_len; /*!< attribute current value length */ + uint8_t *attr_value; /*!< the pointer to attribute value */ +} esp_attr_value_t; + + +/** + * @brief Gatt include service entry element + */ +typedef struct +{ + uint16_t start_hdl; /*!< Gatt start handle value of included service */ + uint16_t end_hdl; /*!< Gatt end handle value of included service */ + uint16_t uuid; /*!< Gatt attribute value UUID of included service */ +} esp_gatts_incl_svc_desc_t; /*!< Gatt include service entry element */ + +/** + * @brief Gatt include 128 bit service entry element + */ +typedef struct +{ + uint16_t start_hdl; /*!< Gatt start handle value of included 128 bit service */ + uint16_t end_hdl; /*!< Gatt end handle value of included 128 bit service */ +} esp_gatts_incl128_svc_desc_t; /*!< Gatt include 128 bit service entry element */ + + + + /// Gatt attribute value typedef struct { - uint8_t value[ESP_GATT_MAX_ATTR_LEN]; /*!< Gatt attribute value */ - uint16_t handle; /*!< Gatt attribute handle */ - uint16_t offset; /*!< Gatt attribute value offset */ - uint16_t len; /*!< Gatt attribute value length */ - uint8_t auth_req; /*!< Gatt authentication request */ + uint8_t value[ESP_GATT_MAX_ATTR_LEN]; /*!< Gatt attribute value */ + uint16_t handle; /*!< Gatt attribute handle */ + uint16_t offset; /*!< Gatt attribute value offset */ + uint16_t len; /*!< Gatt attribute value length */ + uint8_t auth_req; /*!< Gatt authentication request */ } esp_gatt_value_t; /// GATT remote read request response type typedef union { - esp_gatt_value_t attr_value; /*!< Gatt attribute structure */ - uint16_t handle; /*!< Gatt attribute handle */ + esp_gatt_value_t attr_value; /*!< Gatt attribute structure */ + uint16_t handle; /*!< Gatt attribute handle */ } esp_gatt_rsp_t; /** * @brief Gatt write type */ typedef enum { - ESP_GATT_WRITE_TYPE_NO_RSP = 1, /*!< Gatt write attribute need no response */ - ESP_GATT_WRITE_TYPE_RSP, /*!< Gatt write attribute need remote response */ + ESP_GATT_WRITE_TYPE_NO_RSP = 1, /*!< Gatt write attribute need no response */ + ESP_GATT_WRITE_TYPE_RSP, /*!< Gatt write attribute need remote response */ } esp_gatt_write_type_t; #define ESP_GATT_IF_NONE 0xff /*!< If callback report gattc_if/gatts_if as this macro, means this event is not correspond to any app */ -typedef uint8_t esp_gatt_if_t; /*!< Gatt interface type, different application on GATT client use different gatt_if */ +typedef uint8_t esp_gatt_if_t; /*!< Gatt interface type, different application on GATT client use different gatt_if */ #ifdef __cplusplus } diff --git a/components/bt/bluedroid/api/include/esp_gatts_api.h b/components/bt/bluedroid/api/include/esp_gatts_api.h index d0fc055a7..b18039ce7 100644 --- a/components/bt/bluedroid/api/include/esp_gatts_api.h +++ b/components/bt/bluedroid/api/include/esp_gatts_api.h @@ -25,29 +25,31 @@ extern "C" { /// GATT Server callback function events typedef enum { - ESP_GATTS_REG_EVT = 0, /*!< When register application id, the event comes */ - ESP_GATTS_READ_EVT = 1, /*!< When gatt client request read operation, the event comes */ - ESP_GATTS_WRITE_EVT = 2, /*!< When gatt client request write operation, the event comes */ - ESP_GATTS_EXEC_WRITE_EVT = 3, /*!< When gatt client request execute write, the event comes */ - ESP_GATTS_MTU_EVT = 4, /*!< When set mtu complete, the event comes */ - ESP_GATTS_CONF_EVT = 5, /*!< When receive confirm, the event comes */ - ESP_GATTS_UNREG_EVT = 6, /*!< When unregister application id, the event comes */ - ESP_GATTS_CREATE_EVT = 7, /*!< When create service complete, the event comes */ - ESP_GATTS_ADD_INCL_SRVC_EVT = 8, /*!< When add included service complete, the event comes */ - ESP_GATTS_ADD_CHAR_EVT = 9, /*!< When add characteristic complete, the event comes */ - ESP_GATTS_ADD_CHAR_DESCR_EVT = 10, /*!< When add descriptor complete, the event comes */ - ESP_GATTS_DELETE_EVT = 11, /*!< When delete service complete, the event comes */ - ESP_GATTS_START_EVT = 12, /*!< When start service complete, the event comes */ - ESP_GATTS_STOP_EVT = 13, /*!< When stop service complete, the event comes */ - ESP_GATTS_CONNECT_EVT = 14, /*!< When gatt client connect, the event comes */ - ESP_GATTS_DISCONNECT_EVT = 15, /*!< When gatt client disconnect, the event comes */ - ESP_GATTS_OPEN_EVT = 16, /*!< When connect to peer, the event comes */ - ESP_GATTS_CANCEL_OPEN_EVT = 17, /*!< When disconnect from peer, the event comes */ - ESP_GATTS_CLOSE_EVT = 18, /*!< When gatt server close, the event comes */ - ESP_GATTS_LISTEN_EVT = 19, /*!< When gatt listen to be connected the event comes */ - ESP_GATTS_CONGEST_EVT = 20, /*!< When congest happen, the event comes */ - /* following is extra event */ - ESP_GATTS_RESPONSE_EVT = 21, /*!< When gatt send response complete, the event comes */ + ESP_GATTS_REG_EVT = 0, /*!< When register application id, the event comes */ + ESP_GATTS_READ_EVT = 1, /*!< When gatt client request read operation, the event comes */ + ESP_GATTS_WRITE_EVT = 2, /*!< When gatt client request write operation, the event comes */ + ESP_GATTS_EXEC_WRITE_EVT = 3, /*!< When gatt client request execute write, the event comes */ + ESP_GATTS_MTU_EVT = 4, /*!< When set mtu complete, the event comes */ + ESP_GATTS_CONF_EVT = 5, /*!< When receive confirm, the event comes */ + ESP_GATTS_UNREG_EVT = 6, /*!< When unregister application id, the event comes */ + ESP_GATTS_CREATE_EVT = 7, /*!< When create service complete, the event comes */ + ESP_GATTS_ADD_INCL_SRVC_EVT = 8, /*!< When add included service complete, the event comes */ + ESP_GATTS_ADD_CHAR_EVT = 9, /*!< When add characteristic complete, the event comes */ + ESP_GATTS_ADD_CHAR_DESCR_EVT = 10, /*!< When add descriptor complete, the event comes */ + ESP_GATTS_DELETE_EVT = 11, /*!< When delete service complete, the event comes */ + ESP_GATTS_START_EVT = 12, /*!< When start service complete, the event comes */ + ESP_GATTS_STOP_EVT = 13, /*!< When stop service complete, the event comes */ + ESP_GATTS_CONNECT_EVT = 14, /*!< When gatt client connect, the event comes */ + ESP_GATTS_DISCONNECT_EVT = 15, /*!< When gatt client disconnect, the event comes */ + ESP_GATTS_OPEN_EVT = 16, /*!< When connect to peer, the event comes */ + ESP_GATTS_CANCEL_OPEN_EVT = 17, /*!< When disconnect from peer, the event comes */ + ESP_GATTS_CLOSE_EVT = 18, /*!< When gatt server close, the event comes */ + ESP_GATTS_LISTEN_EVT = 19, /*!< When gatt listen to be connected the event comes */ + ESP_GATTS_CONGEST_EVT = 20, /*!< When congest happen, the event comes */ + /* following is extra event */ + ESP_GATTS_RESPONSE_EVT = 21, /*!< When gatt send response complete, the event comes */ + ESP_GATTS_CREAT_ATTR_TAB_EVT = 22, + ESP_GATTS_SET_ATTR_VAL_EVT = 23, } esp_gatts_cb_event_t; /** @@ -58,64 +60,66 @@ typedef union { * @brief ESP_GATTS_REG_EVT */ struct gatts_reg_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t app_id; /*!< Application id which input in register API */ - } reg; /*!< Gatt server callback param of ESP_GATTS_REG_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t app_id; /*!< Application id which input in register API */ + } reg; /*!< Gatt server callback param of ESP_GATTS_REG_EVT */ /** * @brief ESP_GATTS_READ_EVT */ struct gatts_read_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint32_t trans_id; /*!< Transfer id */ - esp_bd_addr_t bda; /*!< The bluetooth device address which been read */ - uint16_t handle; /*!< The attribute handle */ - uint16_t offset; /*!< Offset of the value, if the value is too long */ - bool is_long; /*!< The value is too long or not */ - } read; /*!< Gatt server callback param of ESP_GATTS_READ_EVT */ + uint16_t conn_id; /*!< Connection id */ + uint32_t trans_id; /*!< Transfer id */ + esp_bd_addr_t bda; /*!< The bluetooth device address which been read */ + uint16_t handle; /*!< The attribute handle */ + uint16_t offset; /*!< Offset of the value, if the value is too long */ + bool is_long; /*!< The value is too long or not */ + bool need_rsp; /*!< The read operation need to do response */ + } read; /*!< Gatt server callback param of ESP_GATTS_READ_EVT */ + /** * @brief ESP_GATTS_WRITE_EVT */ struct gatts_write_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint32_t trans_id; /*!< Transfer id */ - esp_bd_addr_t bda; /*!< The bluetooth device address which been written */ - uint16_t handle; /*!< The attribute handle */ - uint16_t offset; /*!< Offset of the value, if the value is too long */ - bool need_rsp; /*!< The write operation need to do response */ - bool is_prep; /*!< This write operation is prepare write */ - uint16_t len; /*!< The write attribute value length */ - uint8_t *value; /*!< The write attribute value */ - } write; /*!< Gatt server callback param of ESP_GATTS_WRITE_EVT */ + uint16_t conn_id; /*!< Connection id */ + uint32_t trans_id; /*!< Transfer id */ + esp_bd_addr_t bda; /*!< The bluetooth device address which been written */ + uint16_t handle; /*!< The attribute handle */ + uint16_t offset; /*!< Offset of the value, if the value is too long */ + bool need_rsp; /*!< The write operation need to do response */ + bool is_prep; /*!< This write operation is prepare write */ + uint16_t len; /*!< The write attribute value length */ + uint8_t *value; /*!< The write attribute value */ + } write; /*!< Gatt server callback param of ESP_GATTS_WRITE_EVT */ /** * @brief ESP_GATTS_EXEC_WRITE_EVT */ struct gatts_exec_write_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint32_t trans_id; /*!< Transfer id */ - esp_bd_addr_t bda; /*!< The bluetooth device address which been written */ -#define ESP_GATT_PREP_WRITE_CANCEL 0x00 -#define ESP_GATT_PREP_WRITE_EXEC 0x01 - uint8_t exec_write_flag; /*!< Execute write flag */ - } exec_write; /*!< Gatt server callback param of ESP_GATTS_EXEC_WRITE_EVT */ + uint16_t conn_id; /*!< Connection id */ + uint32_t trans_id; /*!< Transfer id */ + esp_bd_addr_t bda; /*!< The bluetooth device address which been written */ +#define ESP_GATT_PREP_WRITE_CANCEL 0x00 /*!< Prepare write flag to indicate cancel prepare write */ +#define ESP_GATT_PREP_WRITE_EXEC 0x01 /*!< Prepare write flag to indicate execute prepare write */ + uint8_t exec_write_flag; /*!< Execute write flag */ + } exec_write; /*!< Gatt server callback param of ESP_GATTS_EXEC_WRITE_EVT */ /** * @brief ESP_GATTS_MTU_EVT */ struct gatts_mtu_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint16_t mtu; /*!< MTU size */ - } mtu; /*!< Gatt server callback param of ESP_GATTS_MTU_EVT */ + uint16_t conn_id; /*!< Connection id */ + uint16_t mtu; /*!< MTU size */ + } mtu; /*!< Gatt server callback param of ESP_GATTS_MTU_EVT */ /** * @brief ESP_GATTS_CONF_EVT */ struct gatts_conf_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - } conf; /*!< Gatt server callback param of ESP_GATTS_CONF_EVT (confirm) */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t conn_id; /*!< Connection id */ + } conf; /*!< Gatt server callback param of ESP_GATTS_CONF_EVT (confirm) */ /** * @brief ESP_GATTS_UNREG_EVT @@ -125,81 +129,81 @@ typedef union { * @brief ESP_GATTS_CREATE_EVT */ struct gatts_create_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t service_handle; /*!< Service attribute handle */ - esp_gatt_srvc_id_t service_id; /*!< Service id, include service uuid and other information */ - } create; /*!< Gatt server callback param of ESP_GATTS_CREATE_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t service_handle; /*!< Service attribute handle */ + esp_gatt_srvc_id_t service_id; /*!< Service id, include service uuid and other information */ + } create; /*!< Gatt server callback param of ESP_GATTS_CREATE_EVT */ /** * @brief ESP_GATTS_ADD_INCL_SRVC_EVT */ struct gatts_add_incl_srvc_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t attr_handle; /*!< Included service attribute handle */ - uint16_t service_handle; /*!< Service attribute handle */ - } add_incl_srvc; /*!< Gatt server callback param of ESP_GATTS_ADD_INCL_SRVC_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t attr_handle; /*!< Included service attribute handle */ + uint16_t service_handle; /*!< Service attribute handle */ + } add_incl_srvc; /*!< Gatt server callback param of ESP_GATTS_ADD_INCL_SRVC_EVT */ /** * @brief ESP_GATTS_ADD_CHAR_EVT */ struct gatts_add_char_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t attr_handle; /*!< Characteristic attribute handle */ - uint16_t service_handle; /*!< Service attribute handle */ - esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */ - } add_char; /*!< Gatt server callback param of ESP_GATTS_ADD_CHAR_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t attr_handle; /*!< Characteristic attribute handle */ + uint16_t service_handle; /*!< Service attribute handle */ + esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */ + } add_char; /*!< Gatt server callback param of ESP_GATTS_ADD_CHAR_EVT */ /** * @brief ESP_GATTS_ADD_CHAR_DESCR_EVT */ struct gatts_add_char_descr_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t attr_handle; /*!< Descriptor attribute handle */ - uint16_t service_handle; /*!< Service attribute handle */ - esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */ - } add_char_descr; /*!< Gatt server callback param of ESP_GATTS_ADD_CHAR_DESCR_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t attr_handle; /*!< Descriptor attribute handle */ + uint16_t service_handle; /*!< Service attribute handle */ + esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */ + } add_char_descr; /*!< Gatt server callback param of ESP_GATTS_ADD_CHAR_DESCR_EVT */ /** * @brief ESP_GATTS_DELETE_EVT */ struct gatts_delete_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t service_handle; /*!< Service attribute handle */ - } del; /*!< Gatt server callback param of ESP_GATTS_DELETE_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t service_handle; /*!< Service attribute handle */ + } del; /*!< Gatt server callback param of ESP_GATTS_DELETE_EVT */ /** * @brief ESP_GATTS_START_EVT */ struct gatts_start_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t service_handle; /*!< Service attribute handle */ - } start; /*!< Gatt server callback param of ESP_GATTS_START_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t service_handle; /*!< Service attribute handle */ + } start; /*!< Gatt server callback param of ESP_GATTS_START_EVT */ /** * @brief ESP_GATTS_STOP_EVT */ struct gatts_stop_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t service_handle; /*!< Service attribute handle */ - } stop; /*!< Gatt server callback param of ESP_GATTS_STOP_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t service_handle; /*!< Service attribute handle */ + } stop; /*!< Gatt server callback param of ESP_GATTS_STOP_EVT */ /** * @brief ESP_GATTS_CONNECT_EVT */ struct gatts_connect_evt_param { - uint16_t conn_id; /*!< Connection id */ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - bool is_connected; /*!< Indicate it is connected or not */ - } connect; /*!< Gatt server callback param of ESP_GATTS_CONNECT_EVT */ + uint16_t conn_id; /*!< Connection id */ + esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ + bool is_connected; /*!< Indicate it is connected or not */ + } connect; /*!< Gatt server callback param of ESP_GATTS_CONNECT_EVT */ /** * @brief ESP_GATTS_DISCONNECT_EVT */ struct gatts_disconnect_evt_param { - uint16_t conn_id; /*!< Connection id */ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - bool is_connected; /*!< Indicate it is connected or not */ - } disconnect; /*!< Gatt server callback param of ESP_GATTS_DISCONNECT_EVT */ + uint16_t conn_id; /*!< Connection id */ + esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ + bool is_connected; /*!< Indicate it is connected or not */ + } disconnect; /*!< Gatt server callback param of ESP_GATTS_DISCONNECT_EVT */ /** * @brief ESP_GATTS_OPEN_EVT @@ -217,17 +221,38 @@ typedef union { * @brief ESP_GATTS_CONGEST_EVT */ struct gatts_congest_evt_param { - uint16_t conn_id; /*!< Connection id */ - bool congested; /*!< Congested or not */ - } congest; /*!< Gatt server callback param of ESP_GATTS_CONGEST_EVT */ + uint16_t conn_id; /*!< Connection id */ + bool congested; /*!< Congested or not */ + } congest; /*!< Gatt server callback param of ESP_GATTS_CONGEST_EVT */ /** * @brief ESP_GATTS_RESPONSE_EVT */ struct gatts_rsp_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - uint16_t handle; /*!< Attribute handle which send response */ - } rsp; /*!< Gatt server callback param of ESP_GATTS_RESPONSE_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + uint16_t handle; /*!< Attribute handle which send response */ + } rsp; /*!< Gatt server callback param of ESP_GATTS_RESPONSE_EVT */ + + /** + * @brief ESP_GATTS_CREAT_ATTR_TAB_EVT + */ + struct gatts_add_attr_tab_evt_param{ + esp_gatt_status_t status; /*!< Operation status */ + esp_bt_uuid_t svc_uuid; /*!< Service uuid type */ + uint16_t num_handle; /*!< The number of the attribute handle to be added to the gatts database */ + uint16_t *handles; /*!< The number to the handles */ + } add_attr_tab; /*!< Gatt server callback param of ESP_GATTS_CREAT_ATTR_TAB_EVT */ + + + /** + * @brief ESP_GATTS_SET_ATTR_VAL_EVT + */ + struct gatts_set_attr_val_evt_param{ + uint16_t srvc_handle; /*!< The service handle */ + uint16_t attr_handle; /*!< The attribute handle */ + esp_gatt_status_t status; /*!< Operation status*/ + } set_attr_val; /*!< Gatt server callback param of ESP_GATTS_SET_ATTR_VAL_EVT */ + } esp_ble_gatts_cb_param_t; /** @@ -294,7 +319,22 @@ esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if, esp_gatt_srvc_id_t *service_id, uint16_t num_handle); - +/** + * @brief Create a service attribute tab. + * @param[in] gatts_attr_db: the pointer to the service attr tab + * @param[in] gatts_if: GATT server access interface + * @param[in] max_nb_attr: the number of attribute to be added to the service database. + * @param[in] srvc_inst_id: the instance id of the service + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db, + esp_gatt_if_t gatts_if, + uint8_t max_nb_attr, + uint8_t srvc_inst_id); /** * @brief This function is called to add an included service. After included * service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT @@ -321,6 +361,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i * @param[in] char_uuid : Characteristic UUID. * @param[in] perm : Characteristic value declaration attribute permission. * @param[in] property : Characteristic Properties + * @param[in] char_val : Characteristic value + * @param[in] control : attribute response control byte * * @return * - ESP_OK : success @@ -328,7 +370,8 @@ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t i * */ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid, - esp_gatt_perm_t perm, esp_gatt_char_prop_t property); + esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val, + esp_attr_control_t *control); /** @@ -340,15 +383,17 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_ * be added. * @param[in] perm: descriptor access permission. * @param[in] descr_uuid: descriptor UUID. - * + * @param[in] char_descr_val : Characteristic descriptor value + * @param[in] control : attribute response control byte * @return * - ESP_OK : success * - other : failed * */ esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle, - esp_bt_uuid_t *descr_uuid, - esp_gatt_perm_t perm); + esp_bt_uuid_t *descr_uuid, + esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val, + esp_attr_control_t *control); @@ -396,7 +441,8 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle); /** - * @brief This function is called to read a characteristics descriptor. + * @brief Send indicate or notify to GATT client. + * Set param need_confirm as false will send notification, otherwise indication. * * @param[in] gatts_if: GATT server access interface * @param[in] conn_id - connection id to indicate. @@ -432,6 +478,35 @@ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, esp_gatt_status_t status, esp_gatt_rsp_t *rsp); +/** + * @brief This function is called to set the attribute value by the application + * + * @param[in] attr_handle: the attribute handle which to be set + * @param[in] length: the value length + * @param[in] value: the pointer to the attribute value + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value); + +/** + * @brief Retrieve attribute value + * + * @param[in] attr_handle: Attribute handle. + * @param[out] length: pointer to the attribute value length + * @param[out] value: Pointer to attribute value payload, the value cannot be modified by user + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value); + + /** * @brief Open a direct open connection or add a background auto connection * diff --git a/components/bt/bluedroid/bta/gatt/bta_gatts_act.c b/components/bt/bluedroid/bta/gatt/bta_gatts_act.c index 04bb3ee7c..83d5e4d7d 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gatts_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gatts_act.c @@ -34,7 +34,6 @@ #include "bta_gatts_int.h" #include "bta_gatts_co.h" #include "btm_ble_api.h" -// #include "btif/include/btif_debug_conn.h" #include static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range); @@ -404,10 +403,22 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg) UINT16 attr_id = 0; tBTA_GATTS cb_data; + tGATT_ATTR_VAL *p_attr_val = NULL; + tGATTS_ATTR_CONTROL *p_control = NULL; + + if(p_msg->api_add_char.attr_val.attr_max_len != 0){ + p_attr_val = &p_msg->api_add_char.attr_val; + } + + if(p_msg->api_add_char.control.auto_rsp != 0){ + p_control = &p_msg->api_add_char.control; + } + + attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific, &p_msg->api_add_char.char_uuid, p_msg->api_add_char.perm, - p_msg->api_add_char.property); + p_msg->api_add_char.property, p_attr_val, p_control); cb_data.add_result.server_if = p_rcb->gatt_if; cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific; cb_data.add_result.attr_id = attr_id; @@ -420,11 +431,15 @@ void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg) } else { cb_data.add_result.status = BTA_GATT_ERROR; } + if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){ + GKI_freebuf(p_attr_val->attr_val); + } if (p_rcb->p_cback) { (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data); } } + /******************************************************************************* ** ** Function bta_gatts_add_char_descr @@ -439,10 +454,20 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx]; UINT16 attr_id = 0; tBTA_GATTS cb_data; + tGATT_ATTR_VAL *p_attr_val = NULL; + tGATTS_ATTR_CONTROL *p_control = NULL; + if (p_msg->api_add_char_descr.attr_val.attr_max_len != 0) { + p_attr_val = &p_msg->api_add_char_descr.attr_val; + } + + if (p_msg->api_add_char_descr.control.auto_rsp != 0) { + p_control = &p_msg->api_add_char_descr.control; + } attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific, p_msg->api_add_char_descr.perm, - &p_msg->api_add_char_descr.descr_uuid); + &p_msg->api_add_char_descr.descr_uuid, p_attr_val, + p_control); cb_data.add_result.server_if = p_rcb->gatt_if; cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific; @@ -456,12 +481,50 @@ void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_ } else { cb_data.add_result.status = BTA_GATT_ERROR; } + if((p_attr_val != NULL) && (p_attr_val->attr_val != NULL)){ + GKI_freebuf(p_attr_val->attr_val); + } if (p_rcb->p_cback) { (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data); } } + +/******************************************************************************* +** +** Function bta_gatts_add_char_descr +** +** Description action function to add characteristic descriptor. +** +** Returns none. +** +*******************************************************************************/ +void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg) +{ + tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx]; + UINT16 attr_id = 0; + tBTA_GATTS cb_data; + tBTA_GATT_STATUS gatts_status; + gatts_status = GATTS_SetAttributeValue(p_msg->api_add_char_descr.hdr.layer_specific, + p_msg->api_set_val.length, + p_msg->api_set_val.value); + + cb_data.attr_val.server_if = p_rcb->gatt_if; + cb_data.attr_val.service_id = p_msg->api_set_val.hdr.layer_specific; + cb_data.attr_val.attr_id = attr_id; + cb_data.attr_val.status = gatts_status; + + if (p_rcb->p_cback) { + (*p_rcb->p_cback)(BTA_GATTS_SET_ATTR_VAL_EVT, &cb_data); + } +} + +void bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value) +{ + GATTS_GetAttributeValue(attr_handle, length, value); +} + /******************************************************************************* ** ** Function bta_gatts_delete_service diff --git a/components/bt/bluedroid/bta/gatt/bta_gatts_api.c b/components/bt/bluedroid/bta/gatt/bta_gatts_api.c index d54935120..94f1d407e 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gatts_api.c +++ b/components/bt/bluedroid/bta/gatt/bta_gatts_api.c @@ -215,10 +215,14 @@ void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id) ** *******************************************************************************/ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid, - tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property) + tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val, + tBTA_GATTS_ATTR_CONTROL *control) { tBTA_GATTS_API_ADD_CHAR *p_buf; - + UINT16 len = 0; + if(attr_val != NULL){ + len = attr_val->attr_len; + } if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL) { memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR)); @@ -226,6 +230,19 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid, p_buf->hdr.layer_specific = service_id; p_buf->perm = perm; p_buf->property = property; + if(control !=NULL){ + p_buf->control.auto_rsp = control->auto_rsp; + } + if(attr_val != NULL){ + APPL_TRACE_DEBUG("!!!!!!attr_val->attr_len = %x\n",attr_val->attr_len); + APPL_TRACE_DEBUG("!!!!!!!attr_val->attr_max_len = %x\n",attr_val->attr_max_len); + p_buf->attr_val.attr_len = attr_val->attr_len; + p_buf->attr_val.attr_max_len = attr_val->attr_max_len; + p_buf->attr_val.attr_val = (uint8_t *)GKI_getbuf(len); + if(p_buf->attr_val.attr_val != NULL){ + memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len); + } + } if (p_char_uuid) { memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID)); @@ -253,22 +270,43 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid, *******************************************************************************/ void BTA_GATTS_AddCharDescriptor (UINT16 service_id, tBTA_GATT_PERM perm, - tBT_UUID *p_descr_uuid) + tBT_UUID *p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val, + tBTA_GATTS_ATTR_CONTROL *control) { tBTA_GATTS_API_ADD_DESCR *p_buf; - UINT16 len = sizeof(tBTA_GATTS_API_ADD_DESCR); + UINT16 value_len = 0; - - if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL) { - memset(p_buf, 0, len); + if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_DESCR))) != NULL) { + memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_DESCR)); p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT; p_buf->hdr.layer_specific = service_id; p_buf->perm = perm; + if(control != NULL){ + p_buf->control.auto_rsp = control->auto_rsp; + } + if (p_descr_uuid) { memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID)); } + + if(attr_val != NULL){ + p_buf->attr_val.attr_len = attr_val->attr_len; + p_buf->attr_val.attr_max_len = attr_val->attr_max_len; + value_len = attr_val->attr_len; + if (value_len != 0){ + p_buf->attr_val.attr_val = (uint8_t*)GKI_getbuf(value_len); + if(p_buf->attr_val.attr_val != NULL){ + memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, value_len); + } + else{ + APPL_TRACE_ERROR("Allocate fail for %s\n", __func__); + + } + } + } + bta_sys_sendmsg(p_buf); } return; @@ -276,14 +314,14 @@ void BTA_GATTS_AddCharDescriptor (UINT16 service_id, } /******************************************************************************* -** -** Function BTA_GATTS_DeleteService -** -** Description This function is called to delete a service. When this is done, -** a callback event BTA_GATTS_DELETE_EVT is report with the status. -** -** Parameters service_id: service_id to be deleted. -** + ** + ** Function BTA_GATTS_DeleteService + ** + ** Description This function is called to delete a service. When this is done, + ** a callback event BTA_GATTS_DELETE_EVT is report with the status. + ** + ** Parameters service_id: service_id to be deleted. + ** ** Returns returns none. ** *******************************************************************************/ @@ -433,6 +471,29 @@ void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id, } +void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value) +{ + tBTA_GATTS_API_SET_ATTR_VAL *p_buf; + if((p_buf = (tBTA_GATTS_API_SET_ATTR_VAL *)GKI_getbuf( + sizeof(tBTA_GATTS_API_SET_ATTR_VAL))) != NULL){ + p_buf->hdr.event = BTA_GATTS_API_SET_ATTR_VAL_EVT; + p_buf->hdr.layer_specific = attr_handle; + p_buf->length = length; + if(value != NULL){ + if((p_buf->value = (UINT8 *)GKI_getbuf(length)) != NULL){ + memcpy(p_buf->value, value, length); + } + } + + bta_sys_sendmsg(p_buf); + } + +} + +void BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value) +{ + bta_gatts_get_attr_value(attr_handle, length, value); +} /******************************************************************************* ** diff --git a/components/bt/bluedroid/bta/gatt/bta_gatts_main.c b/components/bt/bluedroid/bta/gatt/bta_gatts_main.c index d59115d42..4306709c8 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gatts_main.c +++ b/components/bt/bluedroid/bta/gatt/bta_gatts_main.c @@ -104,29 +104,30 @@ BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg) case BTA_GATTS_API_RSP_EVT: bta_gatts_send_rsp(p_cb, (tBTA_GATTS_DATA *) p_msg); break; - + case BTA_GATTS_API_SET_ATTR_VAL_EVT:{ + UINT16 attr_id = ((tBTA_GATTS_DATA *) p_msg)->api_set_val.hdr.layer_specific; + p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id(p_cb, attr_id); + bta_gatts_set_attr_value(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg); + break; + } case BTA_GATTS_API_LISTEN_EVT: bta_gatts_listen(p_cb, (tBTA_GATTS_DATA *) p_msg); break; - - case BTA_GATTS_API_ADD_INCL_SRVC_EVT: case BTA_GATTS_API_ADD_CHAR_EVT: case BTA_GATTS_API_ADD_DESCR_EVT: case BTA_GATTS_API_DEL_SRVC_EVT: case BTA_GATTS_API_START_SRVC_EVT: case BTA_GATTS_API_STOP_SRVC_EVT: - p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb, ((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific); if (p_srvc_cb != NULL) { bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg); } else { - APPL_TRACE_ERROR("service not created"); + APPL_TRACE_ERROR("service not created\n"); } break; - default: break; } diff --git a/components/bt/bluedroid/bta/include/bta_gatt_api.h b/components/bt/bluedroid/bta/include/bta_gatt_api.h index d10ca46ae..f4c0e06f0 100644 --- a/components/bt/bluedroid/bta/include/bta_gatt_api.h +++ b/components/bt/bluedroid/bta/include/bta_gatt_api.h @@ -109,41 +109,41 @@ typedef UINT8 tBTA_GATT_STATUS; /* Client callback function events */ -#define BTA_GATTC_REG_EVT 0 /* GATT client is registered. */ -#define BTA_GATTC_DEREG_EVT 1 /* GATT client deregistered event */ -#define BTA_GATTC_OPEN_EVT 2 /* GATTC open request status event */ -#define BTA_GATTC_READ_CHAR_EVT 3 /* GATT read characteristic event */ -#define BTA_GATTC_WRITE_CHAR_EVT 4 /* GATT write characteristic or char descriptor event */ -#define BTA_GATTC_CLOSE_EVT 5 /* GATTC close request status event */ -#define BTA_GATTC_SEARCH_CMPL_EVT 6 /* GATT discovery complete event */ -#define BTA_GATTC_SEARCH_RES_EVT 7 /* GATT discovery result event */ -#define BTA_GATTC_READ_DESCR_EVT 8 /* GATT read characterisitc descriptor event */ -#define BTA_GATTC_WRITE_DESCR_EVT 9 /* GATT write characteristic descriptor event */ -#define BTA_GATTC_NOTIF_EVT 10 /* GATT attribute notification event */ -#define BTA_GATTC_PREP_WRITE_EVT 11 /* GATT prepare write event */ -#define BTA_GATTC_EXEC_EVT 12 /* execute write complete event */ -#define BTA_GATTC_ACL_EVT 13 /* ACL up event */ -#define BTA_GATTC_CANCEL_OPEN_EVT 14 /* cancel open event */ -#define BTA_GATTC_SRVC_CHG_EVT 15 /* service change event */ -#define BTA_GATTC_LISTEN_EVT 16 /* listen event */ -#define BTA_GATTC_ENC_CMPL_CB_EVT 17 /* encryption complete callback event */ -#define BTA_GATTC_CFG_MTU_EVT 18 /* configure MTU complete event */ -#define BTA_GATTC_ADV_DATA_EVT 19 /* ADV data event */ -#define BTA_GATTC_MULT_ADV_ENB_EVT 20 /* Enable Multi ADV event */ -#define BTA_GATTC_MULT_ADV_UPD_EVT 21 /* Update parameter event */ -#define BTA_GATTC_MULT_ADV_DATA_EVT 22 /* Multi ADV data event */ -#define BTA_GATTC_MULT_ADV_DIS_EVT 23 /* Disable Multi ADV event */ -#define BTA_GATTC_CONGEST_EVT 24 /* Congestion event */ -#define BTA_GATTC_BTH_SCAN_ENB_EVT 25 /* Enable batch scan event */ -#define BTA_GATTC_BTH_SCAN_CFG_EVT 26 /* Config storage event */ -#define BTA_GATTC_BTH_SCAN_RD_EVT 27 /* Batch scan reports read event */ -#define BTA_GATTC_BTH_SCAN_THR_EVT 28 /* Batch scan threshold event */ -#define BTA_GATTC_BTH_SCAN_PARAM_EVT 29 /* Batch scan param event */ -#define BTA_GATTC_BTH_SCAN_DIS_EVT 30 /* Disable batch scan event */ -#define BTA_GATTC_SCAN_FLT_CFG_EVT 31 /* Scan filter config event */ -#define BTA_GATTC_SCAN_FLT_PARAM_EVT 32 /* Param filter event */ -#define BTA_GATTC_SCAN_FLT_STATUS_EVT 33 /* Filter status event */ -#define BTA_GATTC_ADV_VSC_EVT 34 /* ADV VSC event */ +#define BTA_GATTC_REG_EVT 0 /* GATT client is registered. */ +#define BTA_GATTC_DEREG_EVT 1 /* GATT client deregistered event */ +#define BTA_GATTC_OPEN_EVT 2 /* GATTC open request status event */ +#define BTA_GATTC_READ_CHAR_EVT 3 /* GATT read characteristic event */ +#define BTA_GATTC_WRITE_CHAR_EVT 4 /* GATT write characteristic or char descriptor event */ +#define BTA_GATTC_CLOSE_EVT 5 /* GATTC close request status event */ +#define BTA_GATTC_SEARCH_CMPL_EVT 6 /* GATT discovery complete event */ +#define BTA_GATTC_SEARCH_RES_EVT 7 /* GATT discovery result event */ +#define BTA_GATTC_READ_DESCR_EVT 8 /* GATT read characterisitc descriptor event */ +#define BTA_GATTC_WRITE_DESCR_EVT 9 /* GATT write characteristic descriptor event */ +#define BTA_GATTC_NOTIF_EVT 10 /* GATT attribute notification event */ +#define BTA_GATTC_PREP_WRITE_EVT 11 /* GATT prepare write event */ +#define BTA_GATTC_EXEC_EVT 12 /* execute write complete event */ +#define BTA_GATTC_ACL_EVT 13 /* ACL up event */ +#define BTA_GATTC_CANCEL_OPEN_EVT 14 /* cancel open event */ +#define BTA_GATTC_SRVC_CHG_EVT 15 /* service change event */ +#define BTA_GATTC_LISTEN_EVT 16 /* listen event */ +#define BTA_GATTC_ENC_CMPL_CB_EVT 17 /* encryption complete callback event */ +#define BTA_GATTC_CFG_MTU_EVT 18 /* configure MTU complete event */ +#define BTA_GATTC_ADV_DATA_EVT 19 /* ADV data event */ +#define BTA_GATTC_MULT_ADV_ENB_EVT 20 /* Enable Multi ADV event */ +#define BTA_GATTC_MULT_ADV_UPD_EVT 21 /* Update parameter event */ +#define BTA_GATTC_MULT_ADV_DATA_EVT 22 /* Multi ADV data event */ +#define BTA_GATTC_MULT_ADV_DIS_EVT 23 /* Disable Multi ADV event */ +#define BTA_GATTC_CONGEST_EVT 24 /* Congestion event */ +#define BTA_GATTC_BTH_SCAN_ENB_EVT 25 /* Enable batch scan event */ +#define BTA_GATTC_BTH_SCAN_CFG_EVT 26 /* Config storage event */ +#define BTA_GATTC_BTH_SCAN_RD_EVT 27 /* Batch scan reports read event */ +#define BTA_GATTC_BTH_SCAN_THR_EVT 28 /* Batch scan threshold event */ +#define BTA_GATTC_BTH_SCAN_PARAM_EVT 29 /* Batch scan param event */ +#define BTA_GATTC_BTH_SCAN_DIS_EVT 30 /* Disable batch scan event */ +#define BTA_GATTC_SCAN_FLT_CFG_EVT 31 /* Scan filter config event */ +#define BTA_GATTC_SCAN_FLT_PARAM_EVT 32 /* Param filter event */ +#define BTA_GATTC_SCAN_FLT_STATUS_EVT 33 /* Filter status event */ +#define BTA_GATTC_ADV_VSC_EVT 34 /* ADV VSC event */ typedef UINT8 tBTA_GATTC_EVT; @@ -151,7 +151,7 @@ typedef tGATT_IF tBTA_GATTC_IF; typedef struct { UINT16 unit; /* as UUIUD defined by SIG */ - UINT16 descr; /* as UUID as defined by SIG */ + UINT16 descr; /* as UUID as defined by SIG */ tGATT_FORMAT format; INT8 exp; UINT8 name_spc; /* The name space of the description */ @@ -165,7 +165,7 @@ typedef UINT16 tBTA_GATT_CLT_CHAR_CONFIG; /* characteristic descriptor: server configuration value */ #define BTA_GATT_SVR_CONFIG_NONE GATT_SVR_CONFIG_NONE /* 0x0000 */ -#define BTA_GATT_SVR_CONFIG_BROADCAST GATT_SVR_CONFIG_BROADCAST /* 0x0001 */ +#define BTA_GATT_SVR_CONFIG_BROADCAST GATT_SVR_CONFIG_BROADCAST /* 0x0001 */ typedef UINT16 tBTA_GATT_SVR_CHAR_CONFIG; /* Characteristic Aggregate Format attribute value @@ -367,8 +367,8 @@ typedef struct { // btla-specific -- typedef struct { - tBTA_GATTC_IF client_if; - BD_ADDR remote_bda; + tBTA_GATTC_IF client_if; + BD_ADDR remote_bda; } tBTA_GATTC_ENC_CMPL_CB; typedef union { @@ -395,7 +395,6 @@ typedef void (tBTA_GATTC_ENB_CBACK)(tBTA_GATT_STATUS status); /* Client callback function */ typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data); - /* GATT Server Data Structure */ /* Server callback function events */ #define BTA_GATTS_REG_EVT 0 @@ -419,6 +418,7 @@ typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data); #define BTA_GATTS_CLOSE_EVT 18 #define BTA_GATTS_LISTEN_EVT 19 #define BTA_GATTS_CONGEST_EVT 20 +#define BTA_GATTS_SET_ATTR_VAL_EVT 21 typedef UINT8 tBTA_GATTS_EVT; typedef tGATT_IF tBTA_GATTS_IF; @@ -434,20 +434,22 @@ typedef tGATT_IF tBTA_GATTS_IF; #define BTA_GATT_PERM_WRITE_SIGNED GATT_PERM_WRITE_SIGNED /* bit 7 - 0x0080 */ #define BTA_GATT_PERM_WRITE_SIGNED_MITM GATT_PERM_WRITE_SIGNED_MITM /* bit 8 - 0x0100 */ typedef UINT16 tBTA_GATT_PERM; +typedef tGATT_ATTR_VAL tBTA_GATT_ATTR_VAL; +typedef tGATTS_ATTR_CONTROL tBTA_GATTS_ATTR_CONTROL; #define BTA_GATTS_INVALID_APP 0xff #define BTA_GATTS_INVALID_IF 0 /* definition of characteristic properties */ -#define BTA_GATT_CHAR_PROP_BIT_BROADCAST GATT_CHAR_PROP_BIT_BROADCAST /* 0x01 */ -#define BTA_GATT_CHAR_PROP_BIT_READ GATT_CHAR_PROP_BIT_READ /* 0x02 */ -#define BTA_GATT_CHAR_PROP_BIT_WRITE_NR GATT_CHAR_PROP_BIT_WRITE_NR /* 0x04 */ -#define BTA_GATT_CHAR_PROP_BIT_WRITE GATT_CHAR_PROP_BIT_WRITE /* 0x08 */ -#define BTA_GATT_CHAR_PROP_BIT_NOTIFY GATT_CHAR_PROP_BIT_NOTIFY /* 0x10 */ -#define BTA_GATT_CHAR_PROP_BIT_INDICATE GATT_CHAR_PROP_BIT_INDICATE /* 0x20 */ -#define BTA_GATT_CHAR_PROP_BIT_AUTH GATT_CHAR_PROP_BIT_AUTH /* 0x40 */ -#define BTA_GATT_CHAR_PROP_BIT_EXT_PROP GATT_CHAR_PROP_BIT_EXT_PROP /* 0x80 */ +#define BTA_GATT_CHAR_PROP_BIT_BROADCAST GATT_CHAR_PROP_BIT_BROADCAST /* 0x01 */ +#define BTA_GATT_CHAR_PROP_BIT_READ GATT_CHAR_PROP_BIT_READ /* 0x02 */ +#define BTA_GATT_CHAR_PROP_BIT_WRITE_NR GATT_CHAR_PROP_BIT_WRITE_NR /* 0x04 */ +#define BTA_GATT_CHAR_PROP_BIT_WRITE GATT_CHAR_PROP_BIT_WRITE /* 0x08 */ +#define BTA_GATT_CHAR_PROP_BIT_NOTIFY GATT_CHAR_PROP_BIT_NOTIFY /* 0x10 */ +#define BTA_GATT_CHAR_PROP_BIT_INDICATE GATT_CHAR_PROP_BIT_INDICATE /* 0x20 */ +#define BTA_GATT_CHAR_PROP_BIT_AUTH GATT_CHAR_PROP_BIT_AUTH /* 0x40 */ +#define BTA_GATT_CHAR_PROP_BIT_EXT_PROP GATT_CHAR_PROP_BIT_EXT_PROP /* 0x80 */ typedef UINT8 tBTA_GATT_CHAR_PROP; #ifndef BTA_GATTC_CHAR_DESCR_MAX @@ -476,8 +478,8 @@ typedef tGATTS_SRV_CHG tBTA_GATTS_SRV_CHG; typedef tGATTS_SRV_CHG_REQ tBTA_GATTS_SRV_CHG_REQ; typedef tGATTS_SRV_CHG_RSP tBTA_GATTS_SRV_CHG_RSP; -#define BTA_GATT_TRANSPORT_LE GATT_TRANSPORT_LE -#define BTA_GATT_TRANSPORT_BR_EDR GATT_TRANSPORT_BR_EDR +#define BTA_GATT_TRANSPORT_LE GATT_TRANSPORT_LE +#define BTA_GATT_TRANSPORT_BR_EDR GATT_TRANSPORT_BR_EDR #define BTA_GATT_TRANSPORT_LE_BR_EDR GATT_TRANSPORT_LE_BR_EDR typedef UINT8 tBTA_GATT_TRANSPORT; @@ -539,6 +541,13 @@ typedef struct { // btla-specific -- } tBTA_GATTS_ADD_RESULT; +typedef struct{ + tBTA_GATTS_IF server_if; + UINT16 service_id; + UINT16 attr_id; + tBTA_GATT_STATUS status; +}tBAT_GATTS_ATTR_VAL_RESULT; + typedef struct { tBTA_GATTS_IF server_if; UINT16 service_id; @@ -566,17 +575,18 @@ typedef struct { /* GATTS callback data */ typedef union { - tBTA_GATTS_REG_OPER reg_oper; - tBTA_GATTS_CREATE create; - tBTA_GATTS_SRVC_OPER srvc_oper; - tBTA_GATT_STATUS status; /* BTA_GATTS_LISTEN_EVT */ - tBTA_GATTS_ADD_RESULT add_result; /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT - add char : BTA_GATTS_ADD_CHAR_EVT - add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */ - tBTA_GATTS_REQ req_data; - tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */ - tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */ - tBTA_GATTS_CONF confirm; /* BTA_GATTS_CONF_EVT callback data */ + tBTA_GATTS_REG_OPER reg_oper; + tBTA_GATTS_CREATE create; + tBTA_GATTS_SRVC_OPER srvc_oper; + tBTA_GATT_STATUS status; /* BTA_GATTS_LISTEN_EVT */ + tBTA_GATTS_ADD_RESULT add_result; /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT + add char : BTA_GATTS_ADD_CHAR_EVT + add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */ + tBAT_GATTS_ATTR_VAL_RESULT attr_val; + tBTA_GATTS_REQ req_data; + tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */ + tBTA_GATTS_CONGEST congest; /* BTA_GATTS_CONGEST_EVT callback data */ + tBTA_GATTS_CONF confirm; /* BTA_GATTS_CONF_EVT callback data */ } tBTA_GATTS; /* GATTS enable callback function */ @@ -1193,8 +1203,9 @@ extern void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_servi ** Returns None ** *******************************************************************************/ -extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid, - tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property); +extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid, + tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val, + tBTA_GATTS_ATTR_CONTROL *control); /******************************************************************************* ** @@ -1214,8 +1225,9 @@ extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_ ** *******************************************************************************/ extern void BTA_GATTS_AddCharDescriptor (UINT16 service_id, - tBTA_GATT_PERM perm, - tBT_UUID *p_descr_uuid); + tBTA_GATT_PERM perm, + tBT_UUID *p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val, + tBTA_GATTS_ATTR_CONTROL *control); /******************************************************************************* ** @@ -1296,6 +1308,38 @@ extern void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id, tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg); + +/******************************************************************************* +** +** Function BTA_SetAttributeValue +** +** Description This function is called to set the attribute value in the gatt database +** +** Parameters attr_handle - the attribute value handle. +** length - the value length which has been set to the attribute. +** value - the pointer to the value +** +** Returns None +** +*******************************************************************************/ +extern void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value); + + +/******************************************************************************* +** +** Function BTA_GetAttributeValue +** +** Description This function is called to get the attribute value in the gatt database +** +** Parameters attr_handle - the attribute value handle. +** length - the value length which has been set to the attribute. +** value - the pointer to the value +** +** Returns None +** +*******************************************************************************/ +extern void BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value); + /******************************************************************************* ** ** Function BTA_GATTS_Open diff --git a/components/bt/bluedroid/bta/include/bta_gatts_int.h b/components/bt/bluedroid/bta/include/bta_gatts_int.h index f934c4ac6..0f9e689ac 100644 --- a/components/bt/bluedroid/bta/include/bta_gatts_int.h +++ b/components/bt/bluedroid/bta/include/bta_gatts_int.h @@ -48,6 +48,7 @@ enum { BTA_GATTS_API_START_SRVC_EVT, BTA_GATTS_API_STOP_SRVC_EVT, BTA_GATTS_API_RSP_EVT, + BTA_GATTS_API_SET_ATTR_VAL_EVT, BTA_GATTS_API_OPEN_EVT, BTA_GATTS_API_CANCEL_OPEN_EVT, BTA_GATTS_API_CLOSE_EVT, @@ -91,19 +92,21 @@ typedef struct { tBT_UUID char_uuid; tBTA_GATT_PERM perm; tBTA_GATT_CHAR_PROP property; - + tBTA_GATTS_ATTR_CONTROL control; + tBTA_GATT_ATTR_VAL attr_val; } tBTA_GATTS_API_ADD_CHAR; typedef struct { BT_HDR hdr; UINT16 included_service_id; - } tBTA_GATTS_API_ADD_INCL_SRVC; typedef struct { - BT_HDR hdr; - tBT_UUID descr_uuid; - tBTA_GATT_PERM perm; + BT_HDR hdr; + tBT_UUID descr_uuid; + tBTA_GATT_PERM perm; + tBTA_GATTS_ATTR_CONTROL control; + tBTA_GATT_ATTR_VAL attr_val; } tBTA_GATTS_API_ADD_DESCR; typedef struct { @@ -121,6 +124,12 @@ typedef struct { tBTA_GATTS_RSP *p_rsp; } tBTA_GATTS_API_RSP; +typedef struct{ + BT_HDR hdr; + UINT16 length; + UINT8 *value; +}tBTA_GATTS_API_SET_ATTR_VAL; + typedef struct { BT_HDR hdr; tBTA_GATT_TRANSPORT transport; @@ -156,6 +165,7 @@ typedef union { tBTA_GATTS_API_START api_start; tBTA_GATTS_API_INDICATION api_indicate; tBTA_GATTS_API_RSP api_rsp; + tBTA_GATTS_API_SET_ATTR_VAL api_set_val; tBTA_GATTS_API_OPEN api_open; tBTA_GATTS_API_CANCEL_OPEN api_cancel_open; @@ -169,7 +179,7 @@ typedef struct { BOOLEAN in_use; tBT_UUID app_uuid; tBTA_GATTS_CBACK *p_cback; - tBTA_GATTS_IF gatt_if; + tBTA_GATTS_IF gatt_if; } tBTA_GATTS_RCB; /* service registration control block */ @@ -219,6 +229,8 @@ extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); +extern void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); +extern void bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value); extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg); diff --git a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c index e88c775f5..7866ca0f8 100644 --- a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c +++ b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c @@ -88,6 +88,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) tBTA_GATTS_RSP rsp; LOG_DEBUG("blufi profile cb event = %x\n", event); + switch (event) { case BTA_GATTS_REG_EVT: LOG_DEBUG("REG: status %d, app_uuid %04x, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.uuid.uu.uuid16, p_data->reg_oper.server_if); @@ -187,7 +188,8 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) //add the frist blufi characteristic --> write characteristic BTA_GATTS_AddCharacteristic(blufi_env.handle_srvc, &blufi_char_uuid_p2e, (GATT_PERM_WRITE), - (GATT_CHAR_PROP_BIT_WRITE)); + (GATT_CHAR_PROP_BIT_WRITE), + NULL, NULL); break; case BTA_GATTS_ADD_CHAR_EVT: switch (p_data->add_result.char_uuid.uu.uuid16) { @@ -196,14 +198,16 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) BTA_GATTS_AddCharacteristic(blufi_env.handle_srvc, &blufi_char_uuid_e2p, (GATT_PERM_READ), - (GATT_PERM_READ | GATT_CHAR_PROP_BIT_NOTIFY)); + (GATT_PERM_READ | GATT_CHAR_PROP_BIT_NOTIFY), + NULL, NULL); break; case BLUFI_CHAR_E2P_UUID: /* ESP32 to Phone */ blufi_env.handle_char_e2p = p_data->add_result.attr_id; BTA_GATTS_AddCharDescriptor (blufi_env.handle_srvc, (GATT_PERM_READ | GATT_PERM_WRITE), - &blufi_descr_uuid_e2p); + &blufi_descr_uuid_e2p, + NULL, NULL); break; default: break; diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c index 9bc41d2ab..2ba3ec0f1 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c @@ -20,20 +20,52 @@ #include "btc_manage.h" #include "btc_gatts.h" #include "btc_gatt_util.h" - +#include "future.h" +#include "btc_main.h" #include "esp_gatts_api.h" #define A2C_GATTS_EVT(_bta_event) (_bta_event) //BTA TO BTC EVT #define C2A_GATTS_EVT(_btc_event) (_btc_event) //BTC TO BTA EVT +typedef struct { + future_t *complete_future; + uint16_t svc_start_hdl; + esp_bt_uuid_t svc_uuid; + bool is_tab_creat_svc; + uint8_t num_handle; + uint8_t handle_idx; + uint16_t handles[ESP_GATT_ATTR_HANDLE_MAX]; +} esp_btc_creat_tab_t; + +static esp_btc_creat_tab_t btc_creat_tab_env; + static inline void btc_gatts_cb_to_app(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { esp_gatts_cb_t btc_gatts_cb = (esp_gatts_cb_t)btc_profile_cb_get(BTC_PID_GATTS); if (btc_gatts_cb) { - btc_gatts_cb(event, gatts_if, param); + btc_gatts_cb(event, gatts_if, param); } } +static inline void btc_gatts_uuid_format_convert(esp_bt_uuid_t* dest_uuid, uint16_t src_uuid_len, uint8_t* src_uuid_p) +{ + dest_uuid->len = src_uuid_len; + if(src_uuid_len == ESP_UUID_LEN_16){ + dest_uuid->uuid.uuid16 = src_uuid_p[0] + (src_uuid_p[1]<<8); + } + else if(src_uuid_len == ESP_UUID_LEN_32){ + dest_uuid->uuid.uuid32 = src_uuid_p[0] + (src_uuid_p[1]<<8) + (src_uuid_p[2]<<16) + (src_uuid_p[3]<<24); + } + else if(src_uuid_len == ESP_UUID_LEN_128){ + memcpy(dest_uuid->uuid.uuid128, src_uuid_p, src_uuid_len); + } + else{ + LOG_ERROR("%s wrong uuid length %d\n", __func__, src_uuid_len); + } + +} + + void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { btc_ble_gatts_args_t *dst = (btc_ble_gatts_args_t *) p_dest; @@ -59,6 +91,56 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } } break; + + } + case BTC_GATTS_ACT_ADD_CHAR:{ + if (src->add_char.char_val.attr_value != NULL){ + dst->add_char.char_val.attr_value = (uint8_t *)GKI_getbuf(src->add_char.char_val.attr_len); + if(dst->add_char.char_val.attr_value != NULL){ + memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value, + src->add_char.char_val.attr_len); + }else{ + LOG_ERROR("%s %d no mem\n", __func__, msg->act); + } + } + break; + } + case BTC_GATTS_ACT_ADD_CHAR_DESCR:{ + if(src->add_descr.descr_val.attr_value != NULL){ + dst->add_descr.descr_val.attr_value = (uint8_t *)GKI_getbuf(src->add_descr.descr_val.attr_len); + if(dst->add_descr.descr_val.attr_value != NULL){ + memcpy(dst->add_descr.descr_val.attr_value, src->add_descr.descr_val.attr_value, + src->add_descr.descr_val.attr_len); + }else{ + LOG_ERROR("%s %d no mem\n", __func__, msg->act); + } + } + break; + } + case BTC_GATTS_ACT_CREATE_ATTR_TAB:{ + uint8_t num_attr = src->create_attr_tab.max_nb_attr; + if(src->create_attr_tab.gatts_attr_db != NULL){ + dst->create_attr_tab.gatts_attr_db = (esp_gatts_attr_db_t *)GKI_getbuf(sizeof(esp_gatts_attr_db_t)*num_attr); + if(dst->create_attr_tab.gatts_attr_db != NULL){ + memcpy(dst->create_attr_tab.gatts_attr_db, src->create_attr_tab.gatts_attr_db, + sizeof(esp_gatts_attr_db_t)*num_attr); + }else{ + LOG_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + } + case BTC_GATTS_ACT_SET_ATTR_VALUE:{ + uint8_t len = src->set_attr_val.length; + if(src->set_attr_val.value){ + dst->set_attr_val.value = (uint8_t *)GKI_getbuf(len); + if(dst->set_attr_val.value != NULL){ + memcpy(dst->set_attr_val.value, src->set_attr_val.value, len); + }else{ + LOG_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; } default: LOG_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act); @@ -91,6 +173,175 @@ void btc_gatts_arg_deep_free(btc_msg_t *msg) } +static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, + esp_gatt_if_t gatts_if, + uint8_t max_nb_attr, + uint8_t srvc_inst_id) +{ + uint16_t uuid = 0; + future_t *future_p; + esp_ble_gatts_cb_param_t param; + + //set the attribute table create service flag to ture + btc_creat_tab_env.is_tab_creat_svc = true; + btc_creat_tab_env.num_handle = max_nb_attr; + for(int i = 0; i < max_nb_attr; i++){ + if(gatts_attr_db[i].att_desc.uuid_length== ESP_UUID_LEN_16){ + uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]); + } + future_p = future_new(); + if (future_p == NULL) { + LOG_ERROR("%s failed:no mem\n", __func__); + return ; + } + btc_creat_tab_env.complete_future = future_p; + btc_creat_tab_env.handle_idx = i; + switch(uuid) + { + case ESP_GATT_UUID_PRI_SERVICE:{ + tBTA_GATT_SRVC_ID srvc_id; + esp_gatt_srvc_id_t esp_srvc_id; + + esp_srvc_id.id.inst_id = srvc_inst_id; + btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.length, + gatts_attr_db[i].att_desc.value); + + btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id); + BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid, + srvc_inst_id, max_nb_attr, true); + + if (future_await(future_p) == FUTURE_FAIL) { + LOG_ERROR("%s failed\n", __func__); + return; + } + break; + } + case ESP_GATT_UUID_SEC_SERVICE:{ + tBTA_GATT_SRVC_ID srvc_id; + esp_gatt_srvc_id_t esp_srvc_id; + + esp_srvc_id.id.inst_id = srvc_inst_id; + btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.uuid_length, + gatts_attr_db[i].att_desc.uuid_p); + btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id); + BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid, + srvc_inst_id, max_nb_attr, false); + if (future_await(future_p) == FUTURE_FAIL) { + LOG_ERROR("%s failed\n", __func__); + return; + } + break; + } + case ESP_GATT_UUID_INCLUDE_SERVICE:{ + esp_gatts_incl_svc_desc_t *incl_svc_desc = (esp_gatts_incl_svc_desc_t *)gatts_attr_db[i].att_desc.value; + + if(incl_svc_desc!= NULL){ + if(btc_creat_tab_env.svc_start_hdl != 0){ + BTA_GATTS_AddIncludeService(btc_creat_tab_env.svc_start_hdl, + incl_svc_desc->start_hdl); + + if (future_await(future_p) == FUTURE_FAIL) { + LOG_ERROR("%s failed\n", __func__); + return; + } + } + } + break; + } + case ESP_GATT_UUID_CHAR_DECLARE:{ + uint16_t svc_hal = 0; + tBT_UUID bta_char_uuid; + tGATT_ATTR_VAL attr_val; + esp_bt_uuid_t uuid_temp; + tBTA_GATT_PERM perm; + tBTA_GATTS_ATTR_CONTROL control; + uint8_t char_property; + + if(btc_creat_tab_env.svc_start_hdl != 0){ + svc_hal = btc_creat_tab_env.svc_start_hdl; + if((gatts_attr_db[i].att_desc.value) == NULL){ + LOG_ERROR("%s Characteristic declaration should not be NULL\n", __func__); + } + else{ + char_property = (uint8_t)(*(uint8_t*)(gatts_attr_db[i].att_desc.value)); + perm = gatts_attr_db[i+1].att_desc.perm; + attr_val.attr_len = gatts_attr_db[i+1].att_desc.length; + attr_val.attr_max_len = gatts_attr_db[i+1].att_desc.max_length; + btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i+1].att_desc.uuid_length,gatts_attr_db[i+1].att_desc.uuid_p); + btc_to_bta_uuid(&bta_char_uuid, &uuid_temp); + attr_val.attr_val = gatts_attr_db[i+1].att_desc.value; + control.auto_rsp = gatts_attr_db[i+1].attr_control.auto_rsp; + BTA_GATTS_AddCharacteristic (svc_hal, &bta_char_uuid, + perm, char_property, &attr_val, &control); + + if (future_await(future_p) == FUTURE_FAIL) { + LOG_ERROR("%s failed\n", __func__); + return; + } + } + } + + break; + } + case ESP_GATT_UUID_CHAR_EXT_PROP: + case ESP_GATT_UUID_CHAR_DESCRIPTION: + case ESP_GATT_UUID_CHAR_CLIENT_CONFIG: + case ESP_GATT_UUID_CHAR_SRVR_CONFIG: + case ESP_GATT_UUID_CHAR_PRESENT_FORMAT: + case ESP_GATT_UUID_CHAR_AGG_FORMAT: + case ESP_GATT_UUID_CHAR_VALID_RANGE: + case ESP_GATT_UUID_EXT_RPT_REF_DESCR: + case ESP_GATT_UUID_RPT_REF_DESCR:{ + uint16_t svc_hal = btc_creat_tab_env.svc_start_hdl; + tBT_UUID bta_char_uuid; + esp_bt_uuid_t uuid_temp; + tGATT_ATTR_VAL attr_val; + tBTA_GATT_PERM perm = gatts_attr_db[i].att_desc.perm; + tBTA_GATTS_ATTR_CONTROL control; + + if(svc_hal != 0){ + attr_val.attr_len = gatts_attr_db[i].att_desc.length; + attr_val.attr_max_len = gatts_attr_db[i].att_desc.max_length; + attr_val.attr_val = gatts_attr_db[i].att_desc.value; + btc_gatts_uuid_format_convert(&uuid_temp, gatts_attr_db[i].att_desc.uuid_length, + gatts_attr_db[i].att_desc.uuid_p); + btc_to_bta_uuid(&bta_char_uuid, &uuid_temp); + control.auto_rsp = gatts_attr_db[i].attr_control.auto_rsp; + BTA_GATTS_AddCharDescriptor(svc_hal, perm, &bta_char_uuid, &attr_val, &control); + + if (future_await(future_p) == FUTURE_FAIL) { + LOG_ERROR("%s failed\n", __func__); + return; + } + } + break; + } + default: + break; + } + + + } + + param.add_attr_tab.status = ESP_GATT_OK; + param.add_attr_tab.num_handle = max_nb_attr; + param.add_attr_tab.handles = btc_creat_tab_env.handles; + memcpy(¶m.add_attr_tab.svc_uuid, &btc_creat_tab_env.svc_uuid, sizeof(esp_bt_uuid_t)); + + btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m); + //reset the env after sent the data to app + memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t)); + + //release the flag vaule to false after finish the service created. + btc_creat_tab_env.is_tab_creat_svc = false; +} + +void btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value) +{ + + BTA_GetAttributeValue(attr_handle, length, value); +} + static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_src) { @@ -137,7 +388,6 @@ static void btc_gatts_cb_param_copy_free(btc_msg_t *msg, tBTA_GATTS *p_data) GKI_freebuf(p_data->req_data.p_data); } break; - default: break; } @@ -148,11 +398,43 @@ static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) { bt_status_t status; btc_msg_t msg; - + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GATTS; msg.act = event; + if(btc_creat_tab_env.is_tab_creat_svc && btc_creat_tab_env.complete_future){ + switch(event){ + case BTA_GATTS_CREATE_EVT:{ + //save the service handle to the btc module after used + //the attribute table method to creat a service + bta_to_btc_uuid(&btc_creat_tab_env.svc_uuid, &p_data->create.uuid); + uint8_t index = btc_creat_tab_env.handle_idx; + btc_creat_tab_env.svc_start_hdl = p_data->create.service_id; + btc_creat_tab_env.handles[index] = p_data->create.service_id; + break; + } + case BTA_GATTS_ADD_INCL_SRVC_EVT:{ + uint8_t index = btc_creat_tab_env.handle_idx; + btc_creat_tab_env.handles[index] = p_data->add_result.attr_id; + break; + } + case BTA_GATTS_ADD_CHAR_EVT:{ + uint8_t index = btc_creat_tab_env.handle_idx; + btc_creat_tab_env.handles[index] = p_data->add_result.attr_id - 1; + btc_creat_tab_env.handles[index+1] = p_data->add_result.attr_id; + break; + } + case BTA_GATTS_ADD_CHAR_DESCR_EVT:{ + uint8_t index = btc_creat_tab_env.handle_idx; + btc_creat_tab_env.handles[index] = p_data->add_result.attr_id; + break; + } + default: + break; + } + future_ready(btc_creat_tab_env.complete_future, FUTURE_SUCCESS); + } status = btc_transfer_context(&msg, p_data, sizeof(tBTA_GATTS), btc_gatts_cb_param_copy_req); @@ -187,6 +469,12 @@ void btc_gatts_call_handler(btc_msg_t *msg) srvc_id.is_primary); break; } + case BTC_GATTS_ACT_CREATE_ATTR_TAB: + btc_gatts_act_create_attr_tab(arg->create_attr_tab.gatts_attr_db, + arg->create_attr_tab.gatts_if, + arg->create_attr_tab.max_nb_attr, + arg->create_attr_tab.srvc_inst_id); + break; case BTC_GATTS_ACT_DELETE_SERVICE: BTA_GATTS_DeleteService(arg->delete_srvc.service_handle); break; @@ -204,13 +492,17 @@ void btc_gatts_call_handler(btc_msg_t *msg) btc_to_bta_uuid(&uuid, &arg->add_char.char_uuid); BTA_GATTS_AddCharacteristic(arg->add_char.service_handle, &uuid, - arg->add_char.perm, arg->add_char.property); + arg->add_char.perm, arg->add_char.property, + (tGATT_ATTR_VAL *)&arg->add_char.char_val, + (tBTA_GATTS_ATTR_CONTROL *)&arg->add_char.attr_control); break; } case BTC_GATTS_ACT_ADD_CHAR_DESCR: { tBT_UUID uuid; btc_to_bta_uuid(&uuid, &arg->add_descr.descr_uuid); - BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid); + BTA_GATTS_AddCharDescriptor(arg->add_descr.service_handle, arg->add_descr.perm, &uuid, + (tBTA_GATT_ATTR_VAL *)&arg->add_descr.descr_val, + (tBTA_GATTS_ATTR_CONTROL *)&arg->add_descr.attr_control); break; } case BTC_GATTS_ACT_SEND_INDICATE: @@ -236,6 +528,9 @@ void btc_gatts_call_handler(btc_msg_t *msg) btc_gatts_cb_to_app(ESP_GATTS_RESPONSE_EVT, BTC_GATT_GET_GATT_IF(arg->send_rsp.conn_id), ¶m); break; } + case BTC_GATTS_ACT_SET_ATTR_VALUE: + + break; case BTC_GATTS_ACT_OPEN: { // Ensure device is in inquiry database tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE; @@ -309,6 +604,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg) param.read.offset = p_data->req_data.p_data->read_req.offset; param.read.is_long = p_data->req_data.p_data->read_req.is_long; + param.read.need_rsp = p_data->req_data.p_data->read_req.need_rsp; btc_gatts_cb_to_app(ESP_GATTS_READ_EVT, gatts_if, ¶m); break; } @@ -359,6 +655,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg) param.create.service_id.is_primary = p_data->create.is_primary; param.create.service_id.id.inst_id = p_data->create.svc_instance; bta_to_btc_uuid(¶m.create.service_id.id.uuid, &p_data->create.uuid); + btc_gatts_cb_to_app(ESP_GATTS_CREATE_EVT, gatts_if, ¶m); break; case BTA_GATTS_ADD_INCL_SRVC_EVT: @@ -391,6 +688,7 @@ void btc_gatts_cb_handler(btc_msg_t *msg) gatts_if = p_data->srvc_oper.server_if; param.del.status = p_data->srvc_oper.status; param.del.service_handle = p_data->srvc_oper.service_id; + btc_gatts_cb_to_app(ESP_GATTS_DELETE_EVT, gatts_if, ¶m); break; case BTA_GATTS_START_EVT: @@ -424,11 +722,11 @@ void btc_gatts_cb_handler(btc_msg_t *msg) btc_gatts_cb_to_app(ESP_GATTS_DISCONNECT_EVT, gatts_if, ¶m); break; case BTA_GATTS_OPEN_EVT: - // do nothing + // do nothing case BTA_GATTS_CANCEL_OPEN_EVT: - // do nothing + // do nothing case BTA_GATTS_CLOSE_EVT: - // do nothing + // do nothing case BTA_GATTS_LISTEN_EVT: // do nothing break; @@ -438,6 +736,13 @@ void btc_gatts_cb_handler(btc_msg_t *msg) param.congest.congested = p_data->congest.congested; btc_gatts_cb_to_app(ESP_GATTS_CONGEST_EVT, gatts_if, ¶m); break; + case BTA_GATTS_SET_ATTR_VAL_EVT: + gatts_if = p_data->attr_val.server_if; + param.set_attr_val.srvc_handle = p_data->attr_val.service_id; + param.set_attr_val.attr_handle = p_data->attr_val.attr_id; + param.set_attr_val.status = p_data->attr_val.status; + btc_gatts_cb_to_app(ESP_GATTS_SET_ATTR_VAL_EVT, gatts_if, ¶m); + break; default: // do nothing break; diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gatts.h b/components/bt/bluedroid/btc/profile/std/include/btc_gatts.h index 4ad276f3e..caae44de4 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gatts.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gatts.h @@ -24,6 +24,7 @@ typedef enum { BTC_GATTS_ACT_APP_REGISTER = 0, BTC_GATTS_ACT_APP_UNREGISTER, BTC_GATTS_ACT_CREATE_SERVICE, + BTC_GATTS_ACT_CREATE_ATTR_TAB, BTC_GATTS_ACT_DELETE_SERVICE, BTC_GATTS_ACT_START_SERVICE, BTC_GATTS_ACT_STOP_SERVICE, @@ -32,6 +33,7 @@ typedef enum { BTC_GATTS_ACT_ADD_CHAR_DESCR, BTC_GATTS_ACT_SEND_INDICATE, BTC_GATTS_ACT_SEND_RESPONSE, + BTC_GATTS_ACT_SET_ATTR_VALUE, BTC_GATTS_ACT_OPEN, BTC_GATTS_ACT_CLOSE, } btc_gatts_act_t; @@ -42,46 +44,67 @@ typedef union { struct app_reg_args { uint16_t app_id; } app_reg; + //BTC_GATTS_ACT_APP_UNREGISTER, struct app_unreg_args { esp_gatt_if_t gatts_if; } app_unreg; + //BTC_GATTS_ACT_CREATE_SERVICE, struct create_srvc_args { esp_gatt_if_t gatts_if; esp_gatt_srvc_id_t service_id; uint16_t num_handle; } create_srvc; + + //BTC_GATTS_ACT_CREATE_ATTR_TAB + struct create_attr_tab_args{ + esp_gatt_if_t gatts_if; + uint8_t srvc_inst_id; + uint8_t max_nb_attr; + esp_gatts_attr_db_t *gatts_attr_db; + }create_attr_tab; + //BTC_GATTS_ACT_DELETE_SERVICE, struct delete_srvc_args { uint16_t service_handle; } delete_srvc; + //BTC_GATTS_ACT_START_SERVICE, struct start_srvc_args { uint16_t service_handle; } start_srvc; + //BTC_GATTS_ACT_STOP_SERVICE, struct stop_srvc_args { uint16_t service_handle; } stop_srvc; + //BTC_GATTS_ACT_ADD_INCLUDE_SERVICE, struct add_incl_srvc_args { uint16_t service_handle; uint16_t included_service_handle; } add_incl_srvc; + //BTC_GATTS_ACT_ADD_CHAR, struct add_char_args { uint16_t service_handle; esp_bt_uuid_t char_uuid; esp_gatt_perm_t perm; esp_gatt_char_prop_t property; + esp_attr_control_t attr_control; + esp_attr_value_t char_val; } add_char; + //BTC_GATTS_ACT_ADD_CHAR_DESCR, struct add_descr_args { - uint16_t service_handle; + uint16_t service_handle; esp_bt_uuid_t descr_uuid; esp_gatt_perm_t perm; + esp_attr_control_t attr_control; + esp_attr_value_t descr_val; } add_descr; + //BTC_GATTS_ACT_SEND_INDICATE, struct send_indicate_args { uint16_t conn_id; @@ -90,6 +113,7 @@ typedef union { uint16_t value_len; uint8_t *value; } send_ind; + //BTC_GATTS_ACT_SEND_RESPONSE, struct send_rsp_args { uint16_t conn_id; @@ -97,21 +121,32 @@ typedef union { esp_gatt_status_t status; esp_gatt_rsp_t *rsp; } send_rsp; + + //BTC_GATTS_SET_ATTR_VALUE + struct set_attr_val_args{ + uint16_t length; + uint8_t *value; + } set_attr_val; + //BTC_GATTS_ACT_OPEN, struct open_args { esp_gatt_if_t gatts_if; esp_bd_addr_t remote_bda; bool is_direct; } open; + //BTC_GATTS_ACT_CLOSE, struct close_args { uint16_t conn_id; } close; + } btc_ble_gatts_args_t; void btc_gatts_call_handler(btc_msg_t *msg); void btc_gatts_cb_handler(btc_msg_t *msg); void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, uint8_t **value); + #endif /* __BTC_GATTS_H__ */ diff --git a/components/bt/bluedroid/hci/packet_fragmenter.c b/components/bt/bluedroid/hci/packet_fragmenter.c index bd46041c3..9294cb5bb 100644 --- a/components/bt/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/bluedroid/hci/packet_fragmenter.c @@ -150,13 +150,10 @@ static void reassemble_and_dispatch(BT_HDR *packet) LOG_DEBUG("%s found unfinished packet for handle with start packet. Dropping old.\n", __func__); LOG_DEBUG("partial_packet->len = %x, offset = %x\n", partial_packet->len, partial_packet->len); - //for (int i = 0; i < partial_packet->len; i++) { - // LOG_ERROR("%x", partial_packet->data[i]); - //} - //LOG_ERROR("\n"); + hash_map_erase(partial_packets, (void *)(uintptr_t)handle); - //buffer_allocator->free(partial_packet); - //LOG_ERROR("+++++++++++++++++++\n"); + + } uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE; diff --git a/components/bt/bluedroid/stack/gap/gap_ble.c b/components/bt/bluedroid/stack/gap/gap_ble.c index b560fad65..bf9ea0836 100644 --- a/components/bt/bluedroid/stack/gap/gap_ble.c +++ b/components/bt/bluedroid/stack/gap/gap_ble.c @@ -392,7 +392,8 @@ void gap_attr_db_init(void) */ uuid.len = LEN_UUID_16; uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME; - p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ); + p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ, + NULL, NULL); p_db_attr ++; /* add Icon characteristic @@ -401,7 +402,8 @@ void gap_attr_db_init(void) p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, - GATT_CHAR_PROP_BIT_READ); + GATT_CHAR_PROP_BIT_READ, + NULL, NULL); p_db_attr ++; #if ((defined BTM_PERIPHERAL_ENABLED) && (BTM_PERIPHERAL_ENABLED == TRUE)) @@ -416,7 +418,8 @@ void gap_attr_db_init(void) p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, - GATT_CHAR_PROP_BIT_READ); + GATT_CHAR_PROP_BIT_READ, + NULL, NULL); p_db_attr ++; #endif @@ -424,7 +427,8 @@ void gap_attr_db_init(void) uuid.len = LEN_UUID_16; uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL; p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, - GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ); + GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ, + NULL, NULL); p_db_attr->attr_value.addr_resolution = 0; p_db_attr++; diff --git a/components/bt/bluedroid/stack/gatt/gatt_api.c b/components/bt/bluedroid/stack/gatt/gatt_api.c index c464508da..7a9d125a9 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_api.c +++ b/components/bt/bluedroid/stack/gatt/gatt_api.c @@ -151,10 +151,10 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, tBT_UUID *p_app_uuid128; - GATT_TRACE_API ("GATTS_CreateService" ); + GATT_TRACE_API ("GATTS_CreateService\n" ); if (p_reg == NULL) { - GATT_TRACE_ERROR ("Inavlid gatt_if=%d", gatt_if); + GATT_TRACE_ERROR ("Inavlid gatt_if=%d\n", gatt_if); return (0); } @@ -162,7 +162,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL) { s_hdl = p_list->asgn_range.s_handle; - GATT_TRACE_DEBUG ("Service already been created!!"); + GATT_TRACE_DEBUG ("Service already been created!!\n"); } else { if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER)) { s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl; @@ -184,13 +184,13 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, /* check for space */ if (num_handles > (0xFFFF - s_hdl + 1)) { - GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u", s_hdl, num_handles); + GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u\n", s_hdl, num_handles); return (0); } if ( (p_list = gatt_alloc_hdl_buffer()) == NULL) { /* No free entry */ - GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks"); + GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks\n"); return (0); } @@ -210,7 +210,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, /* add a pending new service change item to the list */ if ( (p_buf = gatt_add_pending_new_srv_start(&p_list->asgn_range)) == NULL) { /* No free entry */ - GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks"); + GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks\n"); if (p_list) { gatt_remove_an_item_from_list(p_list_info, p_list); @@ -219,12 +219,12 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, return (0); } - GATT_TRACE_DEBUG ("Add a new srv chg item"); + GATT_TRACE_DEBUG ("Add a new srv chg item\n"); } } if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles)) { - GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed"); + GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed\n"); if (p_list) { gatt_remove_an_item_from_list(p_list_info, p_list); gatt_free_hdl_buffer(p_list); @@ -236,12 +236,6 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, return (0); } - GATT_TRACE_DEBUG ("GATTS_CreateService(success): handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d", - num_handles, p_list->asgn_range.s_handle , p_list->asgn_range.e_handle, - ((p_list->asgn_range.svc_uuid.len == 2) ? "uuid16" : "uuid128" ), - p_list->asgn_range.svc_uuid.uu.uuid16, - p_list->asgn_range.is_primary); - return (s_hdl); } @@ -295,25 +289,27 @@ UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle ** *******************************************************************************/ UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid, - tGATT_PERM perm, tGATT_CHAR_PROP property) + tGATT_PERM perm, tGATT_CHAR_PROP property, + tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control) { tGATT_HDL_LIST_ELEM *p_decl; if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL) { - GATT_TRACE_DEBUG("Service not created"); + GATT_TRACE_DEBUG("Service not created\n"); return 0; } /* data validity checking */ if ( ((property & GATT_CHAR_PROP_BIT_AUTH) && !(perm & GATT_WRITE_SIGNED_PERM)) || ((perm & GATT_WRITE_SIGNED_PERM) && !(property & GATT_CHAR_PROP_BIT_AUTH)) ) { - GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x ", property, perm); + GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x\n ", property, perm); return 0; } return gatts_add_characteristic(&p_decl->svc_db, perm, property, - p_char_uuid); + p_char_uuid, + attr_val, control); } /******************************************************************************* ** @@ -336,7 +332,7 @@ UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid, *******************************************************************************/ UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, tGATT_PERM perm, - tBT_UUID *p_descr_uuid) + tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control) { tGATT_HDL_LIST_ELEM *p_decl; @@ -353,7 +349,8 @@ UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, return gatts_add_char_descr(&p_decl->svc_db, perm, - p_descr_uuid); + p_descr_uuid, + attr_val, control); } /******************************************************************************* @@ -493,9 +490,9 @@ tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle, gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]); - GATT_TRACE_DEBUG ("allocated i_sreg=%d ", i_sreg); + GATT_TRACE_DEBUG ("allocated i_sreg=%d\n", i_sreg); - GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x", + GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x\n", p_sreg->s_hdl, p_sreg->e_hdl, p_sreg->type, p_sreg->service_instance, p_sreg->sdp_handle); @@ -676,16 +673,16 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id, tGATT_REG *p_reg = gatt_get_regcb(gatt_if); tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(tcb_idx); - GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x", + GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x\n", conn_id, trans_id, status); if ( (p_reg == NULL) || (p_tcb == NULL)) { - GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u ", conn_id); + GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u\n", conn_id); return (tGATT_STATUS) GATT_INVALID_CONN_ID; } if (p_tcb->sr_cmd.trans_id != trans_id) { - GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x", + GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x\n", conn_id, p_tcb->sr_cmd.op_code); return (GATT_WRONG_STATE); @@ -696,6 +693,69 @@ tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id, return cmd_sent; } + +/******************************************************************************* +** +** Function GATTS_SetAttributeValue +** +** Description This function sends to set the attribute value . +** +** Parameter attr_handle:the attribute handle +** length: the attribute length +** value: the value to be set to the attribute in the database +** +** Returns GATT_SUCCESS if successfully sent; otherwise error code. +** +*******************************************************************************/ +tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value) +{ + tGATT_STATUS status; + tGATT_HDL_LIST_ELEM *p_decl = NULL; + + GATT_TRACE_DEBUG("GATTS_SetAttributeValue: attr_handle: %u length: %u \n", + attr_handle, length); + + if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) { + GATT_TRACE_DEBUG("Service not created\n"); + return GATT_INVALID_HANDLE; + } + + status = gatts_set_attribute_value(&p_decl->svc_db, attr_handle, length, value); + return status; + +} + + +/******************************************************************************* +** +** Function GATTS_GetAttributeValue +** +** Description This function sends to set the attribute value . +** +** Parameter attr_handle: the attribute handle +** length:the attribute value length in the database +** value: the attribute value out put +** +** Returns GATT_SUCCESS if successfully sent; otherwise error code. +** +*******************************************************************************/ +tGATT_STATUS GATTS_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value) +{ + tGATT_STATUS status; + tGATT_HDL_LIST_ELEM *p_decl; + + GATT_TRACE_DEBUG("GATTS_GetAttributeValue: attr_handle: %u\n", + attr_handle); + + if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) { + GATT_TRACE_ERROR("Service not created\n"); + return GATT_INVALID_HANDLE; + } + + status = gatts_get_attribute_value(&p_decl->svc_db, attr_handle, length, value); + return status; +} + /*******************************************************************************/ /* GATT Profile Srvr Functions */ /*******************************************************************************/ @@ -1132,7 +1192,7 @@ tGATT_IF GATT_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info) break; } } - GATT_TRACE_API ("allocated gatt_if=%d", gatt_if); + GATT_TRACE_API ("allocated gatt_if=%d\n", gatt_if); return gatt_if; } diff --git a/components/bt/bluedroid/stack/gatt/gatt_attr.c b/components/bt/bluedroid/stack/gatt/gatt_attr.c index 496882839..421b17cab 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_attr.c +++ b/components/bt/bluedroid/stack/gatt/gatt_attr.c @@ -279,21 +279,24 @@ void gatt_profile_db_init (void) GATT_StartIf(gatt_cb.gatt_if); service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE); + GATT_TRACE_ERROR ("GATTS_CreateService: handle of service handle%x", service_handle); + /* add Service Changed characteristic */ uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD; gatt_cb.gattp_attr.service_change = 0; gatt_cb.gattp_attr.handle = - gatt_cb.handle_of_h_r = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE); + gatt_cb.handle_of_h_r = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE, + NULL, NULL); - GATT_TRACE_DEBUG ("gatt_profile_db_init: handle of service changed%d", - gatt_cb.handle_of_h_r ); + GATT_TRACE_DEBUG ("gatt_profile_db_init: handle of service changed%d\n", + gatt_cb.handle_of_h_r); /* start service */ status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED ); - GATT_TRACE_DEBUG ("gatt_profile_db_init: gatt_if=%d start status%d", + GATT_TRACE_DEBUG ("gatt_profile_db_init: gatt_if=%d start status%d\n", gatt_cb.gatt_if, status); } diff --git a/components/bt/bluedroid/stack/gatt/gatt_db.c b/components/bt/bluedroid/stack/gatt/gatt_db.c index 2e74c7d2d..fd27959d9 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_db.c +++ b/components/bt/bluedroid/stack/gatt/gatt_db.c @@ -45,7 +45,7 @@ static BOOLEAN copy_extra_byte_in_db(tGATT_SVC_DB *p_db, void **p_dst, UINT16 le static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri); static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code, - UINT16 handle, UINT16 offset, UINT32 trans_id); + UINT16 handle, UINT16 offset, UINT32 trans_id, BOOLEAN need_rsp); /******************************************************************************* ** @@ -65,12 +65,12 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN GKI_init_q(&p_db->svc_buffer); if (!allocate_svc_db_buf(p_db)) { - GATT_TRACE_ERROR("gatts_init_service_db failed, no resources"); + GATT_TRACE_ERROR("gatts_init_service_db failed, no resources\n"); return FALSE; } - GATT_TRACE_DEBUG("gatts_init_service_db"); - GATT_TRACE_DEBUG("s_hdl = %d num_handle = %d", s_hdl, num_handle ); + GATT_TRACE_DEBUG("gatts_init_service_db\n"); + GATT_TRACE_DEBUG("s_hdl = %d num_handle = %d\n", s_hdl, num_handle ); /* update service database information */ p_db->next_handle = s_hdl; @@ -94,7 +94,7 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db) { if (!p_db || !p_db->p_attr_list) { - GATT_TRACE_ERROR("service DB empty"); + GATT_TRACE_ERROR("service DB empty\n"); return NULL; } else { @@ -127,28 +127,28 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr, } if (!(perm & GATT_READ_ALLOWED)) { - GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT"); + GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT\n"); return GATT_READ_NOT_PERMIT; } if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) && !(sec_flag & BTM_SEC_FLAG_ENCRYPTED)) { - GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION"); + GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION\n"); return GATT_INSUF_AUTHENTICATION; } if ((perm & GATT_READ_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { - GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required"); + GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required\n"); return GATT_INSUF_AUTHENTICATION; } if ((perm & GATT_READ_ENCRYPTED_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { - GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION"); + GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION\n"); return GATT_INSUF_ENCRYPTION; } if ( (perm & GATT_READ_ENCRYPTED_REQUIRED) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) { - GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE"); + GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE\n"); return GATT_INSUF_KEY_SIZE; } @@ -163,7 +163,7 @@ static tGATT_STATUS gatts_check_attr_readability(tGATT_ATTR16 *p_attr, case GATT_UUID_CHAR_CLIENT_CONFIG: case GATT_UUID_CHAR_SRVR_CONFIG: case GATT_UUID_CHAR_PRESENT_FORMAT: - GATT_TRACE_ERROR("GATT_NOT_LONG"); + GATT_TRACE_ERROR("GATT_NOT_LONG\n"); return GATT_NOT_LONG; default: @@ -206,7 +206,7 @@ static tGATT_STATUS read_attr_value (void *p_attr, tGATT_STATUS status; tGATT_ATTR16 *p_attr16 = (tGATT_ATTR16 *)p_attr; - GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d", + GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d\n", p_attr16->uuid, p_attr16->permission, sec_flag, @@ -268,7 +268,18 @@ static tGATT_STATUS read_attr_value (void *p_attr, status = GATT_SUCCESS; } } else { /* characteristic description or characteristic value */ - status = GATT_PENDING; + + if (p_attr16->control.auto_rsp == GATT_RSP_BY_STACK) { + if (p_attr16->p_value != NULL && p_attr16->p_value->attr_val.attr_val != NULL) { + uint8_t *value = p_attr16->p_value->attr_val.attr_val + offset; + len = (mtu >= p_attr16->p_value->attr_val.attr_len) ? (p_attr16->p_value->attr_val.attr_len) : mtu; + ARRAY_TO_STREAM(p, value, len); + } + status = GATT_STACK_RSP; + + } else { + status = GATT_PENDING; + } } *p_len = len; @@ -341,8 +352,9 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, status = read_attr_value ((void *)p_attr, 0, &p, FALSE, (UINT16)(*p_len - 2), &len, sec_flag, key_size); - if (status == GATT_PENDING) { - status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id); + if (status == GATT_PENDING || status == GATT_STACK_RSP) { + BOOLEAN need_rsp = (status != GATT_STACK_RSP); + status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id, need_rsp); /* one callback at a time */ break; @@ -445,12 +457,12 @@ UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e *******************************************************************************/ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, tGATT_CHAR_PROP property, - tBT_UUID *p_char_uuid) + tBT_UUID *p_char_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control) { tGATT_ATTR16 *p_char_decl, *p_char_val; tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}}; - GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x", perm, property); + GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x\n", perm, property); if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL) { if (!copy_extra_byte_in_db(p_db, (void **)&p_char_decl->p_value, sizeof(tGATT_CHAR_DECL))) { @@ -467,8 +479,30 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, p_char_decl->p_value->char_decl.property = property; p_char_decl->p_value->char_decl.char_val_handle = p_char_val->handle; + if (control != NULL) { + p_char_val->control.auto_rsp = control->auto_rsp; + } else { + p_char_val->control.auto_rsp = GATT_RSP_DEFAULT; - p_char_val->p_value = NULL; + } + + if (attr_val != NULL) { + if (!copy_extra_byte_in_db(p_db, (void **)&p_char_val->p_value, sizeof(tGATT_ATTR_VAL))) { + deallocate_attr_in_db(p_db, p_char_val); + return 0; + } + GATT_TRACE_DEBUG("attr_val->attr_len = %x, attr_val->attr_max_len = %x\n", attr_val->attr_len, attr_val->attr_max_len); + GATT_TRACE_DEBUG("attribute handle = %x\n", p_char_val->handle); + p_char_val->p_value->attr_val.attr_len = attr_val->attr_len; + p_char_val->p_value->attr_val.attr_max_len = attr_val->attr_max_len; + p_char_val->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len); + if (p_char_val->p_value->attr_val.attr_val != NULL) { + GATT_TRACE_DEBUG("attribute value not NULL"); + memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len); + } + } else { + p_char_val->p_value = NULL; + } return p_char_val->handle; } @@ -542,24 +576,227 @@ UINT8 gatt_convertchar_descr_type(tBT_UUID *p_descr_uuid) ** *******************************************************************************/ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, - tBT_UUID *p_descr_uuid) + tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control) { tGATT_ATTR16 *p_char_dscptr; - GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x", p_descr_uuid->uu.uuid16); + GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x\n", p_descr_uuid->uu.uuid16); /* Add characteristic descriptors */ - if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, - p_descr_uuid, - perm)) - == NULL) { + if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_descr_uuid, perm)) == NULL) { GATT_TRACE_DEBUG("gatts_add_char_descr Fail for adding char descriptors."); return 0; } else { + if (control != NULL) { + p_char_dscptr->control.auto_rsp = control->auto_rsp; + } + if (attr_val != NULL) { + if (!copy_extra_byte_in_db(p_db, (void **)&p_char_dscptr->p_value, sizeof(tGATT_ATTR_VAL))) { + deallocate_attr_in_db(p_db, p_char_dscptr); + return 0; + } + p_char_dscptr->p_value->attr_val.attr_len = attr_val->attr_len; + p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len; + if (attr_val->attr_val != NULL) { + p_char_dscptr->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len); + if (p_char_dscptr->p_value->attr_val.attr_val != NULL) { + memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len); + memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len); + } + } + } return p_char_dscptr->handle; } } + +/******************************************************************************* +** +** Function gatts_set_attribute_value +** +** Description This function add the attribute value in the database +** +** Parameter p_db: database pointer. +** attr_handle: the attribute handle +** length: the attribute value length +** value: the pointer to the data to be set to the attribute value in the database +** +** Returns Status of the operation. +** +*******************************************************************************/ +tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle, + UINT16 length, UINT8 *value) +{ + tGATT_ATTR16 *p_cur; + + if (p_db == NULL) { + GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db is NULL.\n"); + return GATT_INVALID_PDU; + } + if (p_db->p_attr_list == NULL) { + GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db->p_attr_list is NULL.\n"); + return GATT_INVALID_PDU; + } + + p_cur = (tGATT_ATTR16 *) p_db->p_attr_list; + + while (p_cur != NULL) { + if (p_cur->handle == attr_handle) { + + if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) { + switch (p_cur->uuid) { + case GATT_UUID_PRI_SERVICE: + case GATT_UUID_SEC_SERVICE: + case GATT_UUID_CHAR_DECLARE: + case GATT_UUID_INCLUDE_SERVICE: + return GATT_NOT_FOUND; + default: + if (p_cur->p_value->attr_val.attr_max_len < length) { + GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length"); + return GATT_INVALID_ATTR_LEN; + } else { + memcpy(p_cur->p_value->attr_val.attr_val, value, length); + p_cur->p_value->attr_val.attr_len = length; + } + break; + } + } else { + if (p_cur->p_value->attr_val.attr_max_len < length) { + GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length"); + } else { + memcpy(p_cur->p_value->attr_val.attr_val, value, length); + p_cur->p_value->attr_val.attr_len = length; + } + + } + + break; + + } + + p_cur = p_cur->p_next; + } + + return GATT_SUCCESS; +} + + +/******************************************************************************* +** +** Function gatts_get_attribute_value +** +** Description This function get the attribute value in the database +** +** Parameter p_db: database pointer. +** attr_handle: the attribute handle +** length: the attribute value length +** value: the pointer to the data to be get to the attribute value in the database +** +** Returns Status of the operation. +** +*******************************************************************************/ +tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle, + UINT16 *length, UINT8 **value) +{ + tGATT_ATTR16 *p_cur; + GATT_TRACE_DEBUG("***********%s*************\n", __func__); + GATT_TRACE_DEBUG("attr_handle = %x\n", attr_handle); + if (p_db == NULL) { + GATT_TRACE_ERROR("gatts_get_attribute_value Fail:p_db is NULL.\n"); + return GATT_INVALID_PDU; + } + if (p_db->p_attr_list == NULL) { + GATT_TRACE_ERROR("gatts_get_attribute_value Fail:p_db->p_attr_list is NULL.\n"); + return GATT_INVALID_PDU; + } + + p_cur = (tGATT_ATTR16 *) p_db->p_attr_list; + + while (p_cur != NULL) { + LOG_ERROR("p_ur->handle = %x\n", p_cur->handle); + if (p_cur->handle == attr_handle) { + + if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) { + switch (p_cur->uuid) { + case GATT_UUID_CHAR_DECLARE: + case GATT_UUID_INCLUDE_SERVICE: + break; + default: + if (p_cur->p_value->attr_val.attr_len != 0) { + *length = p_cur->p_value->attr_val.attr_len; + *value = p_cur->p_value->attr_val.attr_val; + return GATT_SUCCESS; + } else { + GATT_TRACE_ERROR("gatts_get_attribute_vaule failt:the value length is 0"); + return GATT_INVALID_ATTR_LEN; + } + break; + } + } else { + if (p_cur->p_value->attr_val.attr_len != 0) { + *length = p_cur->p_value->attr_val.attr_len; + *value = p_cur->p_value->attr_val.attr_val; + return GATT_SUCCESS; + } else { + GATT_TRACE_ERROR("gatts_get_attribute_vaule failed:the value length is 0"); + return GATT_INVALID_ATTR_LEN; + } + + } + + break; + + } + + + p_cur = p_cur->p_next; + } + + return GATT_NOT_FOUND; +} + +BOOLEAN gatts_is_auto_response(UINT16 attr_handle) +{ + tGATT_HDL_LIST_ELEM *p_decl = NULL; + BOOLEAN rsp = FALSE; + tGATT_SVC_DB *p_db = NULL; + if ((p_decl = gatt_find_hdl_buffer_by_attr_handle(attr_handle)) == NULL) { + GATT_TRACE_DEBUG("Service not created\n"); + return rsp; + } + + p_db = &p_decl->svc_db; + + tGATT_ATTR16 *p_cur, *p_next; + + if (p_db == NULL) { + GATT_TRACE_DEBUG("gatts_get_attribute_value Fail:p_db is NULL.\n"); + return rsp; + } + if (p_db->p_attr_list == NULL) { + GATT_TRACE_DEBUG("gatts_get_attribute_value Fail:p_db->p_attr_list is NULL.\n"); + return rsp; + } + + p_cur = (tGATT_ATTR16 *) p_db->p_attr_list; + p_next = (tGATT_ATTR16 *) p_cur->p_next; + + for (; p_cur != NULL && p_next != NULL; + p_cur = p_next, p_next = (tGATT_ATTR16 *)p_next->p_next) { + if (p_cur->handle == attr_handle) { + if (p_cur->p_value != NULL && p_cur->control.auto_rsp == GATT_RSP_BY_STACK) { + rsp = true; + return rsp; + } + + } + + } + + return rsp; + +} + /*******************************************************************************/ /* Service Attribute Database Query Utility Functions */ /*******************************************************************************/ @@ -605,8 +842,9 @@ tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb, (BOOLEAN)(op_code == GATT_REQ_READ_BLOB), mtu, p_len, sec_flag, key_size); - if (status == GATT_PENDING) { - status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id); + if ((status == GATT_PENDING) || (status == GATT_STACK_RSP)) { + BOOLEAN need_rsp = (status != GATT_STACK_RSP); + status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id, need_rsp); } break; } @@ -614,6 +852,42 @@ tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb, } } + + return status; +} + +tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db, + UINT16 handle, UINT16 offset, + UINT8 *p_value, UINT16 len) +{ + tGATT_STATUS status = GATT_NOT_FOUND; + tGATT_ATTR16 *p_attr; + + if (p_db && p_db->p_attr_list) { + p_attr = (tGATT_ATTR16 *)p_db->p_attr_list; + + while (p_attr && handle >= p_attr->handle) { + if (p_attr->handle == handle ) { + if (p_attr->control.auto_rsp == GATT_RSP_BY_APP) { + return GATT_APP_RSP; + } + + if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >= + offset + len)) { + memcpy(p_attr->p_value->attr_val.attr_val + offset, p_value, len); + p_attr->p_value->attr_val.attr_len = len + offset; + return GATT_SUCCESS; + } else { + return GATT_NOT_LONG; + } + } + + p_attr = (tGATT_ATTR16 *)p_attr->p_next; + + } + + } + return status; } @@ -661,6 +935,8 @@ tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, return status; } + + /******************************************************************************* ** ** Function gatts_write_attr_perm_check @@ -835,7 +1111,7 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER UINT16 len = sizeof(tGATT_ATTR128); if (p_uuid == NULL) { - GATT_TRACE_ERROR("illegal UUID"); + GATT_TRACE_ERROR("illegal UUID\n"); return NULL; } @@ -845,17 +1121,17 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER len = sizeof(tGATT_ATTR32); } - GATT_TRACE_DEBUG("allocate attr %d bytes ", len); + GATT_TRACE_DEBUG("allocate attr %d bytes\n", len); if (p_db->end_handle <= p_db->next_handle) { - GATT_TRACE_DEBUG("handle space full. handle_max = %d next_handle = %d", + GATT_TRACE_DEBUG("handle space full. handle_max = %d next_handle = %d\n", p_db->end_handle, p_db->next_handle); return NULL; } if (p_db->mem_free < len) { if (!allocate_svc_db_buf(p_db)) { - GATT_TRACE_ERROR("allocate_attr_in_db failed, no resources"); + GATT_TRACE_ERROR("allocate_attr_in_db failed, no resources\n"); return NULL; } } @@ -896,19 +1172,21 @@ static void *allocate_attr_in_db(tGATT_SVC_DB *p_db, tBT_UUID *p_uuid, tGATT_PER } if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16) { - GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x ", + GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid16 = [0x%04x] perm=0x%02x\n", p_attr16->handle, p_attr16->uuid, p_attr16->permission); } else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32) { - GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x ", + GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid32 = [0x%08x] perm=0x%02x\n", p_attr32->handle, p_attr32->uuid, p_attr32->permission); } else { - GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x ", + GATT_TRACE_DEBUG("=====> handle = [0x%04x] uuid128 = [0x%02x:0x%02x] perm=0x%02x\n", p_attr128->handle, p_attr128->uuid[0], p_attr128->uuid[1], p_attr128->permission); } return (void *)p_attr16; } + + /******************************************************************************* ** ** Function deallocate_attr_in_db @@ -974,7 +1252,7 @@ static BOOLEAN copy_extra_byte_in_db(tGATT_SVC_DB *p_db, void **p_dst, UINT16 le if (p_db->mem_free < len) { if (!allocate_svc_db_buf(p_db)) { - GATT_TRACE_ERROR("copy_extra_byte_in_db failed, no resources"); + GATT_TRACE_ERROR("copy_extra_byte_in_db failed, no resources\n"); return FALSE; } } @@ -1028,7 +1306,7 @@ static BOOLEAN allocate_svc_db_buf(tGATT_SVC_DB *p_db) ** *******************************************************************************/ static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code, - UINT16 handle, UINT16 offset, UINT32 trans_id) + UINT16 handle, UINT16 offset, UINT32 trans_id, BOOLEAN need_rsp) { tGATTS_DATA sr_data; UINT8 i_rcb; @@ -1050,6 +1328,7 @@ static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code, sr_data.read_req.handle = handle; sr_data.read_req.is_long = (BOOLEAN)(op_code == GATT_REQ_READ_BLOB); sr_data.read_req.offset = offset; + sr_data.read_req.need_rsp = need_rsp; gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_READ, &sr_data); diff --git a/components/bt/bluedroid/stack/gatt/gatt_main.c b/components/bt/bluedroid/stack/gatt/gatt_main.c index 8b40ed0e5..d7997a847 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_main.c +++ b/components/bt/bluedroid/stack/gatt/gatt_main.c @@ -508,7 +508,7 @@ static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf) GKI_freebuf (p_buf); if (p_tcb != NULL) { - GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d", + GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d\n", gatt_get_ch_state(p_tcb)); } } @@ -906,10 +906,10 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf) } } } else { - GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code); + GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x\n", op_code); } } else { - GATT_TRACE_ERROR ("invalid data length, ignore"); + GATT_TRACE_ERROR ("invalid data length, ignore\n"); } GKI_freebuf (p_buf); diff --git a/components/bt/bluedroid/stack/gatt/gatt_sr.c b/components/bt/bluedroid/stack/gatt/gatt_sr.c index 4846d4ad3..a817ad147 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/bluedroid/stack/gatt/gatt_sr.c @@ -239,7 +239,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, tGATT_STATUS ret_code = GATT_SUCCESS; UNUSED(trans_id); - GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if); + GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d\n", gatt_if); gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE); @@ -264,7 +264,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, if (p_tcb->sr_cmd.p_rsp_msg == NULL) { p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (UINT8)(op_code + 1), (tGATT_SR_MSG *)p_msg); } else { - GATT_TRACE_ERROR("Exception!!! already has respond message"); + GATT_TRACE_ERROR("Exception!!! already has respond message\n"); } } } @@ -279,7 +279,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, gatt_dequeue_sr_cmd(p_tcb); } - GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code); + GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d\n", ret_code); return ret_code; } @@ -371,7 +371,7 @@ void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U #if GATT_CONFORMANCE_TESTING == TRUE if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) { - GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status); + GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d\n", gatt_cb.err_status); STREAM_TO_UINT16(handle, p); @@ -871,7 +871,7 @@ static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data) ** - discover characteristic by UUID ** - relationship discovery ** -** Returns void +** Returns void ** *******************************************************************************/ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) @@ -889,10 +889,10 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, tGATT_SRV_LIST_ELEM *p_srv = NULL; reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl); - + GATT_TRACE_DEBUG("%s, op_code =%x, len = %x\n", __func__, op_code, len); #if GATT_CONFORMANCE_TESTING == TRUE if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) { - GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status); + GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d\n", gatt_cb.err_status); gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE); @@ -902,7 +902,7 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, if (reason == GATT_SUCCESS) { if ((p_msg = (BT_HDR *)GKI_getbuf(msg_len)) == NULL) { - GATT_TRACE_ERROR("gatts_process_find_info failed. no resources."); + GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n"); reason = GATT_NO_RESOURCES; } else { @@ -959,7 +959,7 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, p_msg->offset = L2CAP_MIN_OFFSET; } } - if (reason != GATT_SUCCESS) { + if (reason != GATT_SUCCESS && reason != GATT_STACK_RSP) { if (p_msg) { GKI_freebuf(p_msg); } @@ -987,21 +987,34 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, UINT8 op_code, UINT16 len, UINT8 *p_data) { + UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET); tGATTS_DATA sr_data; UINT32 trans_id; tGATT_STATUS status; - UINT8 sec_flag, key_size, *p = p_data; + UINT8 sec_flag, key_size, *p = p_data, *p_m; tGATT_SR_REG *p_sreg; - UINT16 conn_id; - + UINT16 conn_id, offset = 0; + BT_HDR *p_msg = NULL; memset(&sr_data, 0, sizeof(tGATTS_DATA)); + if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) { + GATT_TRACE_ERROR("gatts_process_write_req failed. no resources.\n"); + } + + memset(p_msg, 0, buf_len); + p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; + *p_m ++ = op_code + 1; + p_msg->len = 1; + buf_len = p_tcb->payload_size - 1; + switch (op_code) { case GATT_REQ_PREPARE_WRITE: sr_data.write_req.is_prep = TRUE; STREAM_TO_UINT16(sr_data.write_req.offset, p); + UINT16_TO_STREAM(p_m, sr_data.write_req.is_prep); + offset = sr_data.write_req.offset; len -= 2; - /* fall through */ + /* fall through */ case GATT_SIGN_CMD_WRITE: if (op_code == GATT_SIGN_CMD_WRITE) { GATT_TRACE_DEBUG("Write CMD with data sigining" ); @@ -1012,11 +1025,16 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, case GATT_REQ_WRITE: if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE) { sr_data.write_req.need_rsp = TRUE; + if(op_code == GATT_REQ_PREPARE_WRITE){ + memcpy(p_m, p, len); + p_msg->len += len; + } } sr_data.write_req.handle = handle; sr_data.write_req.len = len; if (len != 0 && p != NULL) { memcpy (sr_data.write_req.value, p, len); + } break; } @@ -1039,48 +1057,64 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) { p_sreg = &gatt_cb.sr_reg[i_rcb]; conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if); - gatt_sr_send_req_callback(conn_id, - trans_id, - GATTS_REQ_TYPE_WRITE, - &sr_data); + status = gatts_write_attr_value_by_handle(gatt_cb.sr_reg[i_rcb].p_db, + handle, offset, p, len); + if((sr_data.write_req.need_rsp == TRUE) && (status == GATT_APP_RSP)){ + sr_data.write_req.need_rsp = TRUE; + status = GATT_PENDING; + } + + else{ + sr_data.write_req.need_rsp = FALSE; + } + + gatt_sr_send_req_callback(conn_id, + trans_id, + GATTS_REQ_TYPE_WRITE, + &sr_data); + + if(status == GATT_SUCCESS){ + attp_send_sr_msg(p_tcb, p_msg); + gatt_dequeue_sr_cmd(p_tcb); + } - status = GATT_PENDING; } else { - GATT_TRACE_ERROR("max pending command, send error"); + GATT_TRACE_ERROR("max pending command, send error\n"); status = GATT_BUSY; /* max pending command, application error */ } } /* in theroy BUSY is not possible(should already been checked), protected check */ - if (status != GATT_PENDING && status != GATT_BUSY && + if (status != GATT_PENDING && status != GATT_BUSY && status != GATT_SUCCESS && (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) { gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE); + gatt_dequeue_sr_cmd(p_tcb); } return; } /******************************************************************************* -** -** Function gatts_process_read_req -** -** Description This function is called to process the read request -** from client. -** -** Returns void -** -*******************************************************************************/ + ** + ** Function gatts_process_read_req + ** + ** Description This function is called to process the read request + ** from client. + ** + ** Returns void + ** + *******************************************************************************/ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code, UINT16 handle, UINT16 len, UINT8 *p_data) { - UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET); - tGATT_STATUS reason; - BT_HDR *p_msg = NULL; - UINT8 sec_flag, key_size, *p; - UINT16 offset = 0, value_len = 0; + UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET); + tGATT_STATUS reason; + BT_HDR *p_msg = NULL; + UINT8 sec_flag, key_size, *p; + UINT16 offset = 0, value_len = 0; UNUSED (len); if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) { - GATT_TRACE_ERROR("gatts_process_find_info failed. no resources."); + GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n"); reason = GATT_NO_RESOURCES; } else { @@ -1114,17 +1148,20 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 p_msg->len += value_len; } - if (reason != GATT_SUCCESS) { + + if (reason != GATT_SUCCESS && reason != GATT_PENDING && reason != GATT_STACK_RSP) { if (p_msg) { GKI_freebuf(p_msg); } /* in theroy BUSY is not possible(should already been checked), protected check */ - if (reason != GATT_PENDING && reason != GATT_BUSY) { + if (reason != GATT_BUSY) { gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE); + gatt_dequeue_sr_cmd(p_tcb); } } else { attp_send_sr_msg(p_tcb, p_msg); + gatt_dequeue_sr_cmd(p_tcb); } } @@ -1149,7 +1186,7 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code, tGATT_ATTR16 *p_attr; if (len < 2) { - GATT_TRACE_ERROR("Illegal PDU length, discard request"); + GATT_TRACE_ERROR("Illegal PDU length, discard request\n"); status = GATT_INVALID_PDU; } else { STREAM_TO_UINT16(handle, p); @@ -1159,7 +1196,7 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code, #if GATT_CONFORMANCE_TESTING == TRUE gatt_cb.handle = handle; if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) { - GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status); + GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d\n", gatt_cb.err_status); gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE); @@ -1350,24 +1387,24 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, /* otherwise, ignore the pkt */ } else { switch (op_code) { - case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */ - case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */ + case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */ + case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */ gatts_process_primary_service_req (p_tcb, op_code, len, p_data); break; - case GATT_REQ_FIND_INFO:/* discover char descrptor */ + case GATT_REQ_FIND_INFO: /* discover char descrptor */ gatts_process_find_info(p_tcb, op_code, len, p_data); break; - case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */ + case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */ /* discover characteristic, discover char by UUID */ gatts_process_read_by_type_req(p_tcb, op_code, len, p_data); break; - case GATT_REQ_READ: /* read char/char descriptor value */ + case GATT_REQ_READ: /* read char/char descriptor value */ case GATT_REQ_READ_BLOB: - case GATT_REQ_WRITE: /* write char/char descriptor value */ + case GATT_REQ_WRITE: /* write char/char descriptor value */ case GATT_CMD_WRITE: case GATT_SIGN_CMD_WRITE: case GATT_REQ_PREPARE_WRITE: diff --git a/components/bt/bluedroid/stack/gatt/gatt_utils.c b/components/bt/bluedroid/stack/gatt/gatt_utils.c index 7b55a097c..09f4e8df2 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/bluedroid/stack/gatt/gatt_utils.c @@ -318,6 +318,34 @@ tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle) } return NULL; } + +/******************************************************************************* +** +** Function gatt_find_hdl_buffer_by_attr_handle +** +** Description Find handle range buffer by attribute handle. +** +** Returns Pointer to the buffer, NULL no buffer available +** +*******************************************************************************/ +tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle) +{ + tGATT_HDL_LIST_INFO *p_list_info = &gatt_cb.hdl_list_info; + tGATT_HDL_LIST_ELEM *p_list = NULL; + + p_list = p_list_info->p_first; + + while (p_list != NULL) { + if (p_list->in_use && (p_list->asgn_range.s_handle <= attr_handle) + && (p_list->asgn_range.e_handle >= attr_handle)) { + return (p_list); + } + p_list = p_list->p_next; + } + return NULL; +} + + /******************************************************************************* ** ** Function gatt_find_hdl_buffer_by_app_id @@ -1476,7 +1504,7 @@ tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if) p_reg = &gatt_cb.cl_rcb[ii - 1]; if (!p_reg->in_use) { - GATT_TRACE_WARNING("gatt_if found but not in use."); + GATT_TRACE_WARNING("gatt_if found but not in use.\n"); return NULL; } diff --git a/components/bt/bluedroid/stack/gatt/include/gatt_int.h b/components/bt/bluedroid/stack/gatt/include/gatt_int.h index 1ac8431b3..c9622a24c 100644 --- a/components/bt/bluedroid/stack/gatt/include/gatt_int.h +++ b/components/bt/bluedroid/stack/gatt/include/gatt_int.h @@ -35,7 +35,10 @@ #define GATT_GET_GATT_IF(conn_id) ((tGATT_IF)((UINT8) (conn_id))) #define GATT_GET_SR_REG_PTR(index) (&gatt_cb.sr_reg[(UINT8) (index)]); -#define GATT_TRANS_ID_MAX 0x0fffffff /* 4 MSB is reserved */ +#define GATT_TRANS_ID_MAX 0x0fffffff /* 4 MSB is reserved */ +#define GATT_RSP_BY_APP 0x00 +#define GATT_RSP_BY_STACK 0x01 +#define GATT_RSP_DEFAULT GATT_RSP_BY_APP //need to rsp by the app. /* security action for GATT write and read request */ #define GATT_SEC_NONE 0 @@ -61,16 +64,16 @@ typedef UINT8 tGATT_SEC_ACTION; #define GATT_ATTR_OP_SPT_PREP_WRITE (0x00000001 << 10) #define GATT_ATTR_OP_SPT_EXE_WRITE (0x00000001 << 11) #define GATT_ATTR_OP_SPT_HDL_VALUE_CONF (0x00000001 << 12) -#define GATT_ATTR_OP_SP_SIGN_WRITE (0x00000001 << 13) +#define GATT_ATTR_OP_SP_SIGN_WRITE (0x00000001 << 13) -#define GATT_INDEX_INVALID 0xff +#define GATT_INDEX_INVALID 0xff -#define GATT_PENDING_REQ_NONE 0 +#define GATT_PENDING_REQ_NONE 0 -#define GATT_WRITE_CMD_MASK 0xc0 /*0x1100-0000*/ -#define GATT_AUTH_SIGN_MASK 0x80 /*0x1000-0000*/ -#define GATT_AUTH_SIGN_LEN 12 +#define GATT_WRITE_CMD_MASK 0xc0 /*0x1100-0000*/ +#define GATT_AUTH_SIGN_MASK 0x80 /*0x1000-0000*/ +#define GATT_AUTH_SIGN_LEN 12 #define GATT_HDR_SIZE 3 /* 1B opcode + 2B handle */ @@ -154,7 +157,7 @@ typedef union { tBT_UUID uuid; /* service declaration */ tGATT_CHAR_DECL char_decl; /* characteristic declaration */ tGATT_INCL_SRVC incl_handle; /* included service */ - + tGATT_ATTR_VAL attr_val; } tGATT_ATTR_VALUE; /* Attribute UUID type @@ -167,50 +170,49 @@ typedef UINT8 tGATT_ATTR_UUID_TYPE; /* 16 bits UUID Attribute in server database */ typedef struct { - void *p_next; /* pointer to the next attribute, - either tGATT_ATTR16 or tGATT_ATTR128 */ - tGATT_ATTR_VALUE *p_value; - tGATT_ATTR_UUID_TYPE uuid_type; - tGATT_PERM permission; - UINT16 handle; - UINT16 uuid; + void *p_next; /* pointer to the next attribute, either tGATT_ATTR16 or tGATT_ATTR128 */ + tGATT_ATTR_VALUE *p_value; + tGATT_ATTR_UUID_TYPE uuid_type; + tGATT_PERM permission; + tGATTS_ATTR_CONTROL control; + UINT16 handle; + UINT16 uuid; } tGATT_ATTR16; /* 32 bits UUID Attribute in server database */ typedef struct { - void *p_next; /* pointer to the next attribute, - either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */ - tGATT_ATTR_VALUE *p_value; - tGATT_ATTR_UUID_TYPE uuid_type; - tGATT_PERM permission; - UINT16 handle; - UINT32 uuid; + void *p_next; /* pointer to the next attribute, either tGATT_ATTR16, tGATT_ATTR32 or tGATT_ATTR128 */ + tGATT_ATTR_VALUE *p_value; + tGATT_ATTR_UUID_TYPE uuid_type; + tGATT_PERM permission; + tGATTS_ATTR_CONTROL control; + UINT16 handle; + UINT32 uuid; } tGATT_ATTR32; /* 128 bits UUID Attribute in server database */ typedef struct { - void *p_next; /* pointer to the next attribute, - either tGATT_ATTR16 or tGATT_ATTR128 */ - tGATT_ATTR_VALUE *p_value; - tGATT_ATTR_UUID_TYPE uuid_type; - tGATT_PERM permission; - UINT16 handle; - UINT8 uuid[LEN_UUID_128]; + void *p_next; /* pointer to the next attribute, either tGATT_ATTR16 or tGATT_ATTR128 */ + tGATT_ATTR_VALUE *p_value; + tGATT_ATTR_UUID_TYPE uuid_type; + tGATT_PERM permission; + tGATTS_ATTR_CONTROL control; + UINT16 handle; + UINT8 uuid[LEN_UUID_128]; } tGATT_ATTR128; /* Service Database definition */ typedef struct { - void *p_attr_list; /* pointer to the first attribute, - either tGATT_ATTR16 or tGATT_ATTR128 */ - UINT8 *p_free_mem; /* Pointer to free memory */ - BUFFER_Q svc_buffer; /* buffer queue used for service database */ - UINT32 mem_free; /* Memory still available */ - UINT16 end_handle; /* Last handle number */ - UINT16 next_handle; /* Next usable handle value */ + void *p_attr_list; /* pointer to the first attribute, either tGATT_ATTR16 or tGATT_ATTR128 */ + UINT8 *p_free_mem; /* Pointer to free memory */ + BUFFER_Q svc_buffer; /* buffer queue used for service database */ + UINT32 mem_free; /* Memory still available */ + UINT16 end_handle; /* Last handle number */ + UINT16 next_handle; /* Next usable handle value */ } tGATT_SVC_DB; /* Data Structure used for GATT server */ @@ -218,14 +220,14 @@ typedef struct { /* A service registration information record consists of beginning and ending */ /* attribute handle, service UUID and a set of GATT server callback. */ typedef struct { - tGATT_SVC_DB *p_db; /* pointer to the service database */ + tGATT_SVC_DB *p_db; /* pointer to the service database */ tBT_UUID app_uuid; /* applicatino UUID */ - UINT32 sdp_handle; /* primamry service SDP handle */ + UINT32 sdp_handle; /* primamry service SDP handle */ UINT16 service_instance; /* service instance number */ - UINT16 type; /* service type UUID, primary or secondary */ - UINT16 s_hdl; /* service starting handle */ - UINT16 e_hdl; /* service ending handle */ - tGATT_IF gatt_if; /* this service is belong to which application */ + UINT16 type; /* service type UUID, primary or secondary */ + UINT16 s_hdl; /* service starting handle */ + UINT16 e_hdl; /* service ending handle */ + tGATT_IF gatt_if; /* this service is belong to which application */ BOOLEAN in_use; } tGATT_SR_REG; @@ -340,7 +342,7 @@ typedef struct { tGATT_CH_STATE ch_state; UINT8 ch_flags; - tGATT_IF app_hold_link[GATT_MAX_APPS]; + tGATT_IF app_hold_link[GATT_MAX_APPS]; /* server needs */ /* server response data */ @@ -350,13 +352,13 @@ typedef struct { TIMER_LIST_ENT conf_timer_ent; /* peer confirm to indication timer */ - UINT8 prep_cnt[GATT_MAX_APPS]; - UINT8 ind_count; + UINT8 prep_cnt[GATT_MAX_APPS]; + UINT8 ind_count; - tGATT_CMD_Q cl_cmd_q[GATT_CL_MAX_LCB]; - TIMER_LIST_ENT ind_ack_timer_ent; /* local app confirm to indication timer */ - UINT8 pending_cl_req; - UINT8 next_slot_inq; /* index of next available slot in queue */ + tGATT_CMD_Q cl_cmd_q[GATT_CL_MAX_LCB]; + TIMER_LIST_ENT ind_ack_timer_ent; /* local app confirm to indication timer */ + UINT8 pending_cl_req; + UINT8 next_slot_inq; /* index of next available slot in queue */ BOOLEAN in_use; UINT8 tcb_idx; @@ -579,6 +581,7 @@ extern BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb); /* reserved handle list */ extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst); extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle); +extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle); extern tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void); extern void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p); extern BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value); @@ -664,12 +667,27 @@ extern void gatt_set_sec_act(tGATT_TCB *p_tcb, tGATT_SEC_ACTION sec_act); /* gatt_db.c */ extern BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri, UINT16 s_hdl, UINT16 num_handle); extern UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e_handle, tBT_UUID service); -extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, tGATT_CHAR_PROP property, tBT_UUID *p_char_uuid); -extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, tBT_UUID *p_dscp_uuid); +extern UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, + tGATT_CHAR_PROP property, + tBT_UUID *p_char_uuid, tGATT_ATTR_VAL *attr_val, + tGATTS_ATTR_CONTROL *control); +extern UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, + tBT_UUID *p_dscp_uuid, tGATT_ATTR_VAL *attr_val, + tGATTS_ATTR_CONTROL *control); + +extern tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle, + UINT16 length, UINT8 *value); + +extern tGATT_STATUS gatts_get_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle, + UINT16 *length, UINT8 **value); +extern BOOLEAN gatts_is_auto_response(UINT16 attr_handle); extern tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, tGATT_SVC_DB *p_db, UINT8 op_code, BT_HDR *p_rsp, UINT16 s_handle, UINT16 e_handle, tBT_UUID type, UINT16 *p_len, tGATT_SEC_FLAG sec_flag, UINT8 key_size, UINT32 trans_id, UINT16 *p_cur_handle); extern tGATT_STATUS gatts_read_attr_value_by_handle(tGATT_TCB *p_tcb, tGATT_SVC_DB *p_db, UINT8 op_code, UINT16 handle, UINT16 offset, UINT8 *p_value, UINT16 *p_len, UINT16 mtu, tGATT_SEC_FLAG sec_flag, UINT8 key_size, UINT32 trans_id); +extern tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db, + UINT16 handle, UINT16 offset, + UINT8 *p_value, UINT16 len); extern tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, UINT16 handle, UINT16 offset, UINT8 *p_data, UINT16 len, tGATT_SEC_FLAG sec_flag, UINT8 key_size); extern tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB *p_db, BOOLEAN is_long, UINT16 handle, tGATT_SEC_FLAG sec_flag, UINT8 key_size); diff --git a/components/bt/bluedroid/stack/include/gatt_api.h b/components/bt/bluedroid/stack/include/gatt_api.h index a365ca9de..9360d4fbf 100644 --- a/components/bt/bluedroid/stack/include/gatt_api.h +++ b/components/bt/bluedroid/stack/include/gatt_api.h @@ -63,6 +63,8 @@ #define GATT_ENCRYPED_NO_MITM 0x8d #define GATT_NOT_ENCRYPTED 0x8e #define GATT_CONGESTED 0x8f +#define GATT_STACK_RSP 0x90 +#define GATT_APP_RSP 0x91 /* 0xE0 ~ 0xFC reserved for future use */ #define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */ @@ -117,36 +119,36 @@ typedef UINT16 tGATT_DISCONN_REASON; /* MAX GATT MTU size */ #ifndef GATT_MAX_MTU_SIZE -#define GATT_MAX_MTU_SIZE 517 +#define GATT_MAX_MTU_SIZE 517 #endif /* max legth of an attribute value */ #ifndef GATT_MAX_ATTR_LEN -#define GATT_MAX_ATTR_LEN 600 +#define GATT_MAX_ATTR_LEN 600 #endif /* default GATT MTU size over LE link */ -#define GATT_DEF_BLE_MTU_SIZE 23 +#define GATT_DEF_BLE_MTU_SIZE 23 /* invalid connection ID */ -#define GATT_INVALID_CONN_ID 0xFFFF +#define GATT_INVALID_CONN_ID 0xFFFF #ifndef GATT_CL_MAX_LCB -#define GATT_CL_MAX_LCB 12 // 22 +#define GATT_CL_MAX_LCB 12 // 22 #endif #ifndef GATT_MAX_SCCB -#define GATT_MAX_SCCB 10 +#define GATT_MAX_SCCB 10 #endif /* GATT notification caching timer, default to be three seconds */ #ifndef GATTC_NOTIF_TIMEOUT -#define GATTC_NOTIF_TIMEOUT 3 +#define GATTC_NOTIF_TIMEOUT 3 #endif /***************************************************************************** @@ -155,22 +157,22 @@ typedef UINT16 tGATT_DISCONN_REASON; /* Attribute permissions */ -#define GATT_PERM_READ (1 << 0) /* bit 0 */ -#define GATT_PERM_READ_ENCRYPTED (1 << 1) /* bit 1 */ -#define GATT_PERM_READ_ENC_MITM (1 << 2) /* bit 2 */ -#define GATT_PERM_WRITE (1 << 4) /* bit 4 */ -#define GATT_PERM_WRITE_ENCRYPTED (1 << 5) /* bit 5 */ -#define GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 */ -#define GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 */ -#define GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 */ +#define GATT_PERM_READ (1 << 0) /* bit 0 */ +#define GATT_PERM_READ_ENCRYPTED (1 << 1) /* bit 1 */ +#define GATT_PERM_READ_ENC_MITM (1 << 2) /* bit 2 */ +#define GATT_PERM_WRITE (1 << 4) /* bit 4 */ +#define GATT_PERM_WRITE_ENCRYPTED (1 << 5) /* bit 5 */ +#define GATT_PERM_WRITE_ENC_MITM (1 << 6) /* bit 6 */ +#define GATT_PERM_WRITE_SIGNED (1 << 7) /* bit 7 */ +#define GATT_PERM_WRITE_SIGNED_MITM (1 << 8) /* bit 8 */ typedef UINT16 tGATT_PERM; #define GATT_ENCRYPT_KEY_SIZE_MASK (0xF000) /* the MS nibble of tGATT_PERM; key size 7=0; size 16=9 */ -#define GATT_READ_ALLOWED (GATT_PERM_READ | GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM) -#define GATT_READ_AUTH_REQUIRED (GATT_PERM_READ_ENCRYPTED) -#define GATT_READ_MITM_REQUIRED (GATT_PERM_READ_ENC_MITM) -#define GATT_READ_ENCRYPTED_REQUIRED (GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM) +#define GATT_READ_ALLOWED (GATT_PERM_READ | GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM) +#define GATT_READ_AUTH_REQUIRED (GATT_PERM_READ_ENCRYPTED) +#define GATT_READ_MITM_REQUIRED (GATT_PERM_READ_ENC_MITM) +#define GATT_READ_ENCRYPTED_REQUIRED (GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM) #define GATT_WRITE_ALLOWED (GATT_PERM_WRITE | GATT_PERM_WRITE_ENCRYPTED | GATT_PERM_WRITE_ENC_MITM | \ @@ -312,6 +314,16 @@ typedef struct { UINT8 value[GATT_MAX_ATTR_LEN]; /* the actual attribute value */ } tGATT_VALUE; +typedef struct{ + UINT16 attr_max_len; + UINT16 attr_len; + UINT8 *attr_val; +}tGATT_ATTR_VAL; + +typedef struct{ + uint8_t auto_rsp; +}tGATTS_ATTR_CONTROL; + /* Union of the event data which is used in the server respond API to carry the server response information */ typedef union { @@ -337,6 +349,7 @@ typedef struct { UINT16 handle; UINT16 offset; BOOLEAN is_long; + BOOLEAN need_rsp; } tGATT_READ_REQ; /* write request data */ @@ -740,8 +753,9 @@ extern UINT16 GATTS_AddIncludeService (UINT16 service_handle, ** characteristic failed. ** *******************************************************************************/ -extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uuid, - tGATT_PERM perm, tGATT_CHAR_PROP property); +extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid, + tGATT_PERM perm, tGATT_CHAR_PROP property, + tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control); /******************************************************************************* ** @@ -763,7 +777,8 @@ extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uui ** *******************************************************************************/ extern UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, tGATT_PERM perm, - tBT_UUID *p_descr_uuid); + tBT_UUID *p_descr_uuid, tGATT_ATTR_VAL *attr_val, + tGATTS_ATTR_CONTROL *control); /******************************************************************************* ** @@ -866,6 +881,39 @@ extern tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id, tGATT_STATUS status, tGATTS_RSP *p_msg); +/******************************************************************************* +** +** Function GATTS_SetAttributeValue +** +** Description This function sends to set the attribute value . +** +** Parameter attr_handle:the attribute handle +** length: the attribute length +** value: the value to be set to the attribute in the database +** +** Returns GATT_SUCCESS if sucessfully sent; otherwise error code. +** +*******************************************************************************/ +tGATT_STATUS GATTS_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value); + + +/******************************************************************************* +** +** Function GATTS_GetAttributeValue +** +** Description This function sends to set the attribute value . +** +** Parameter attr_handle: the attribute handle +** length:the attribute value length in the database +** value: the attribute value out put +** +** Returns GATT_SUCCESS if sucessfully sent; otherwise error code. +** +*******************************************************************************/ +tGATT_STATUS GATTS_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value); + + + /*******************************************************************************/ /* GATT Profile Client Functions */ /*******************************************************************************/ diff --git a/components/bt/bluedroid/stack/smp/smp_main.c b/components/bt/bluedroid/stack/smp/smp_main.c index 85b232aea..cad642746 100644 --- a/components/bt/bluedroid/stack/smp/smp_main.c +++ b/components/bt/bluedroid/stack/smp/smp_main.c @@ -419,7 +419,7 @@ static const UINT8 smp_master_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] static const UINT8 smp_slave_entry_map[][SMP_STATE_MAX] = { /* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */ - /* PAIR_REQ */{ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* PAIR_REQ */{ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PAIR_RSP */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* CONFIRM */{ 0, 4, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* RAND */{ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, diff --git a/docs/api/esp_blufi.rst b/docs/api/esp_blufi.rst index 9dd808516..13432dc15 100644 --- a/docs/api/esp_blufi.rst +++ b/docs/api/esp_blufi.rst @@ -6,8 +6,7 @@ Overview BLUFI is a profile based GATT to config ESP32 WIFI to connect/disconnect AP or setup a softap and etc. Use should concern these things: 1. The event sent from profile. Then you need to do something as the event indicate. -2. Security reference. You can write your own Security functions such as symmetrical encryption/decryption and checksum functions. -Even you can define the "Key Exchange/Negotiation" procedure. +2. Security reference. You can write your own Security functions such as symmetrical encryption/decryption and checksum functions. Even you can define the "Key Exchange/Negotiation" procedure. Application Example ------------------- diff --git a/docs/api/esp_gatt_defs.rst b/docs/api/esp_gatt_defs.rst index 637acaab9..70e808a5d 100644 --- a/docs/api/esp_gatt_defs.rst +++ b/docs/api/esp_gatt_defs.rst @@ -25,6 +25,29 @@ Header Files Macros ^^^^^^ + +.. doxygendefine:: ESP_GATT_UUID_IMMEDIATE_ALERT_SVC +.. doxygendefine:: ESP_GATT_UUID_LINK_LOSS_SVC +.. doxygendefine:: ESP_GATT_UUID_TX_POWER_SVC +.. doxygendefine:: ESP_GATT_UUID_CURRENT_TIME_SVC +.. doxygendefine:: ESP_GATT_UUID_REF_TIME_UPDATE_SVC +.. doxygendefine:: ESP_GATT_UUID_NEXT_DST_CHANGE_SVC +.. doxygendefine:: ESP_GATT_UUID_GLUCOSE_SVC +.. doxygendefine:: ESP_GATT_UUID_HEALTH_THERMOM_SVC +.. doxygendefine:: ESP_GATT_UUID_DEVICE_INFO_SVC +.. doxygendefine:: ESP_GATT_UUID_HEART_RATE_SVC +.. doxygendefine:: ESP_GATT_UUID_PHONE_ALERT_STATUS_SVC +.. doxygendefine:: ESP_GATT_UUID_BATTERY_SERVICE_SVC +.. doxygendefine:: ESP_GATT_UUID_BLOOD_PRESSURE_SVC +.. doxygendefine:: ESP_GATT_UUID_ALERT_NTF_SVC +.. doxygendefine:: ESP_GATT_UUID_HID_SVC +.. doxygendefine:: ESP_GATT_UUID_SCAN_PARAMETERS_SVC +.. doxygendefine:: ESP_GATT_UUID_RUNNING_SPEED_CADENCE_SVC +.. doxygendefine:: ESP_GATT_UUID_CYCLING_SPEED_CADENCE_SVC +.. doxygendefine:: ESP_GATT_UUID_CYCLING_POWER_SVC +.. doxygendefine:: ESP_GATT_UUID_LOCATION_AND_NAVIGATION_SVC +.. doxygendefine:: ESP_GATT_UUID_USER_DATA_SVC +.. doxygendefine:: ESP_GATT_UUID_WEIGHT_SCALE_SVC .. doxygendefine:: ESP_GATT_UUID_PRI_SERVICE .. doxygendefine:: ESP_GATT_UUID_SEC_SERVICE .. doxygendefine:: ESP_GATT_UUID_INCLUDE_SERVICE @@ -74,6 +97,9 @@ Macros .. doxygendefine:: ESP_GATT_UUID_HID_BT_KB_INPUT .. doxygendefine:: ESP_GATT_UUID_HID_BT_KB_OUTPUT .. doxygendefine:: ESP_GATT_UUID_HID_BT_MOUSE_INPUT +.. doxygendefine:: ESP_GATT_HEART_RATE_MEAS +.. doxygendefine:: ESP_GATT_BODY_SENSOR_LOCATION +.. doxygendefine:: ESP_GATT_HEART_RATE_CNTL_POINT .. doxygendefine:: ESP_GATT_UUID_BATTERY_LEVEL .. doxygendefine:: ESP_GATT_UUID_SC_CONTROL_POINT .. doxygendefine:: ESP_GATT_UUID_SENSOR_LOCATION @@ -84,7 +110,11 @@ Macros .. doxygendefine:: ESP_GATT_UUID_SCAN_INT_WINDOW .. doxygendefine:: ESP_GATT_UUID_SCAN_REFRESH .. doxygendefine:: ESP_GATT_ILLEGAL_UUID +.. doxygendefine:: ESP_GATT_ILLEGAL_HANDLE +.. doxygendefine:: ESP_GATT_ATTR_HANDLE_MAX .. doxygendefine:: ESP_GATT_MAX_ATTR_LEN +.. doxygendefine:: ESP_GATT_RSP_BY_APP +.. doxygendefine:: ESP_GATT_AUTO_RSP .. doxygendefine:: ESP_GATT_IF_NONE Type Definitions @@ -106,6 +136,24 @@ Enumerations Structures ^^^^^^^^^^ +.. doxygenstruct:: esp_attr_desc_t + :members: + +.. doxygenstruct:: esp_attr_control_t + :members: + +.. doxygenstruct:: esp_gatts_attr_db_t + :members: + +.. doxygenstruct:: esp_attr_value_t + :members: + +.. doxygenstruct:: esp_gatts_incl_svc_desc_t + :members: + +.. doxygenstruct:: esp_gatts_incl128_svc_desc_t + :members: + .. doxygenstruct:: esp_gatt_value_t :members: diff --git a/docs/api/esp_gatts.rst b/docs/api/esp_gatts.rst index fbaa1c236..4278e6b33 100644 --- a/docs/api/esp_gatts.rst +++ b/docs/api/esp_gatts.rst @@ -101,6 +101,12 @@ Structures .. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_rsp_evt_param :members: +.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_add_attr_tab_evt_param + :members: + +.. doxygenstruct:: esp_ble_gatts_cb_param_t::gatts_set_attr_val_evt_param + :members: + Functions ^^^^^^^^^ @@ -109,6 +115,7 @@ Functions .. doxygenfunction:: esp_ble_gatts_app_register .. doxygenfunction:: esp_ble_gatts_app_unregister .. doxygenfunction:: esp_ble_gatts_create_service +.. doxygenfunction:: esp_ble_gatts_create_attr_tab .. doxygenfunction:: esp_ble_gatts_add_included_service .. doxygenfunction:: esp_ble_gatts_add_char .. doxygenfunction:: esp_ble_gatts_add_char_descr @@ -117,6 +124,8 @@ Functions .. doxygenfunction:: esp_ble_gatts_stop_service .. doxygenfunction:: esp_ble_gatts_send_indicate .. doxygenfunction:: esp_ble_gatts_send_response +.. doxygenfunction:: esp_ble_gatts_set_attr_value +.. doxygenfunction:: esp_ble_gatts_get_attr_value .. doxygenfunction:: esp_ble_gatts_open .. doxygenfunction:: esp_ble_gatts_close diff --git a/examples/14_gatt_server/main/gatts_demo.c b/examples/14_gatt_server/main/gatts_demo.c index 9b3b6cc80..98feaa224 100644 --- a/examples/14_gatt_server/main/gatts_demo.c +++ b/examples/14_gatt_server/main/gatts_demo.c @@ -48,6 +48,19 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i #define TEST_DEVICE_NAME "ESP_GATTS_DEMO" #define TEST_MANUFACTURER_DATA_LEN 17 + +#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 + +uint8_t char1_str[] ={0x11,0x22,0x33}; + +esp_attr_value_t gatts_demo_char1_val = +{ + .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX, + .attr_len = sizeof(char1_str), + .attr_value = char1_str, +}; + + static uint8_t test_service_uuid128[32] = { /* LSB <--------------------------------------------------------------------------------> MSB */ //first uuid, 16bit, [12],[13] is the value @@ -175,20 +188,30 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, - ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY); + ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY, + &gatts_demo_char1_val, NULL); break; case ESP_GATTS_ADD_INCL_SRVC_EVT: break; - case ESP_GATTS_ADD_CHAR_EVT: - ESP_LOGI(GATTS_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d\n", - param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); + case ESP_GATTS_ADD_CHAR_EVT: { + uint16_t length = 0; + const uint8_t *prf_char; + ESP_LOGI(GATTS_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d\n", + param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); gl_profile_tab[PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle; gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16; gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; + esp_ble_gatts_get_attr_value(param->add_char.attr_handle, &length, &prf_char); + + ESP_LOGI(GATTS_TAG, "the gatts demo char length = %x\n", length); + for(int i = 0; i < length; i++){ + ESP_LOGI(GATTS_TAG, "prf_char[%x] =%x\n",i,prf_char[i]); + } esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid, - ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE); + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); break; + } case ESP_GATTS_ADD_CHAR_DESCR_EVT: ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n", param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); @@ -269,7 +292,8 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, - ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY); + ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY, + NULL, NULL); break; case ESP_GATTS_ADD_INCL_SRVC_EVT: break; @@ -281,7 +305,8 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16; gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid, - ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE); + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + NULL, NULL); break; case ESP_GATTS_ADD_CHAR_DESCR_EVT: ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n", diff --git a/examples/33_gatt_server_service_table/Makefile b/examples/33_gatt_server_service_table/Makefile new file mode 100644 index 000000000..2ff9c6eae --- /dev/null +++ b/examples/33_gatt_server_service_table/Makefile @@ -0,0 +1,11 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := gatt_server_service_table_demo + +COMPONENT_ADD_INCLUDEDIRS := components/include + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/33_gatt_server_service_table/README.rst b/examples/33_gatt_server_service_table/README.rst new file mode 100644 index 000000000..7a763998d --- /dev/null +++ b/examples/33_gatt_server_service_table/README.rst @@ -0,0 +1,10 @@ +ESP-IDF GATT SERVER create attribute table demo +=============================================== + +This is the demo for user to use ESP_APIs to create a GATT Server attribute table. +The table is easy to use to create GATT server service database without use each "attribute create" functions. +Actually, there are two way to create server service and characteristics. +One is use the esp_gatts_create_service or esp_ble_gatts_add_char and etc. +The other way is use esp_ble_gatts_create_attr_tab. +The important things: the two ways cannot use in the same service, but can use in different service. + diff --git a/examples/33_gatt_server_service_table/main/component.mk b/examples/33_gatt_server_service_table/main/component.mk new file mode 100644 index 000000000..79edf031d --- /dev/null +++ b/examples/33_gatt_server_service_table/main/component.mk @@ -0,0 +1,8 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# This Makefile should, at the very least, just include $(SDK_PATH)/make/component_common.mk. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/examples/33_gatt_server_service_table/main/gatts_table_creat_demo.c b/examples/33_gatt_server_service_table/main/gatts_table_creat_demo.c new file mode 100644 index 000000000..024362c5b --- /dev/null +++ b/examples/33_gatt_server_service_table/main/gatts_table_creat_demo.c @@ -0,0 +1,326 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "bt.h" +#include "bta_api.h" + +#include "esp_gap_ble_api.h" +#include "esp_gatts_api.h" +#include "esp_bt_defs.h" +#include "esp_bt_main.h" +#include "esp_bt_main.h" +#include "gatts_table_creat_demo.h" + + +#define HEART_PROFILE_NUM 1 +#define HEART_PROFILE_APP_IDX 0 +#define ESP_HEART_RATE_APP_ID 0x55 +#define SAMPLE_DEVICE_NAME "ESP_HEART_RATE" +#define SAMPLE_MANUFACTURER_DATA_LEN 17 +#define HEART_RATE_SVC_INST_ID 0 + +#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 + +uint8_t char1_str[] ={0x11,0x22,0x33}; + +uint16_t heart_rate_handle_table[HRS_IDX_NB]; + +esp_attr_value_t gatts_demo_char1_val = +{ + .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX, + .attr_len = sizeof(char1_str), + .attr_value = char1_str, +}; + + +static uint8_t heart_rate_service_uuid[16] = { + /* LSB <--------------------------------------------------------------------------------> MSB */ + //first uuid, 16bit, [12],[13] is the value + 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x18, 0x0D, 0x00, 0x00, +}; + + +static esp_ble_adv_data_t heart_rate_adv_config = { + .set_scan_rsp = false, + .include_name = true, + .include_txpower = true, + .min_interval = 0x20, + .max_interval = 0x40, + .appearance = 0x00, + .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, + .p_manufacturer_data = NULL, //&test_manufacturer[0], + .service_data_len = 0, + .p_service_data = NULL, + .service_uuid_len = 32, + .p_service_uuid = heart_rate_service_uuid, + .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), +}; + +static esp_ble_adv_params_t heart_rate_adv_params = { + .adv_int_min = 0x20, + .adv_int_max = 0x40, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + //.peer_addr = + //.peer_addr_type = + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +struct gatts_profile_inst { + esp_gatts_cb_t gatts_cb; + uint16_t gatts_if; + uint16_t app_id; + uint16_t conn_id; + uint16_t service_handle; + esp_gatt_srvc_id_t service_id; + uint16_t char_handle; + esp_bt_uuid_t char_uuid; + esp_gatt_perm_t perm; + esp_gatt_char_prop_t property; + uint16_t descr_handle; + esp_bt_uuid_t descr_uuid; +}; + +static void gatts_profile_event_handler(esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); + +/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */ +static struct gatts_profile_inst heart_rate_profile_tab[HEART_PROFILE_NUM] = { + [HEART_PROFILE_APP_IDX] = { + .gatts_cb = gatts_profile_event_handler, + .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ + }, + +}; + +/* + * HTPT PROFILE ATTRIBUTES + **************************************************************************************** + */ + + +/* + * Heart Rate PROFILE ATTRIBUTES + **************************************************************************************** + */ + +/// Heart Rate Sensor Service +static const uint16_t heart_rate_svc = ESP_GATT_UUID_HEART_RATE_SVC; + +#define CHAR_DECLARATION_SIZE (sizeof(uint8_t)) +static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE; +static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE; +static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; +static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY; +static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ; +static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ; + +/// Heart Rate Sensor Service - Heart Rate Measurement Characteristic, notify +static const uint16_t heart_rate_meas_uuid = ESP_GATT_HEART_RATE_MEAS; +static const uint8_t heart_measurement_ccc[2] ={ 0x00, 0x00}; + + +/// Heart Rate Sensor Service -Body Sensor Location characteristic, read +static const uint16_t body_sensor_location_uuid = ESP_GATT_BODY_SENSOR_LOCATION; +static const uint8_t body_sensor_loc_val[1] = {0x00}; + + +/// Heart Rate Sensor Service - Heart Rate Control Point characteristic, write&read +static const uint16_t heart_rate_ctrl_point = ESP_GATT_HEART_RATE_CNTL_POINT; +static const uint8_t heart_ctrl_point[1] = {0x00}; + +/// Full HRS Database Description - Used to add attributes into the database +static const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB] = +{ + // Heart Rate Service Declaration + [HRS_IDX_SVC] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, + sizeof(uint16_t), sizeof(heart_rate_svc), (uint8_t *)&heart_rate_svc}}, + + // Heart Rate Measurement Characteristic Declaration + [HRS_IDX_HR_MEAS_CHAR] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, + CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_notify}}, + + // Heart Rate Measurement Characteristic Value + [HRS_IDX_HR_MEAS_VAL] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_meas_uuid, ESP_GATT_PERM_READ, + HRPS_HT_MEAS_MAX_LEN,0, NULL}}, + + // Heart Rate Measurement Characteristic - Client Characteristic Configuration Descriptor + [HRS_IDX_HR_MEAS_NTF_CFG] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, + sizeof(uint16_t),sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}}, + + // Body Sensor Location Characteristic Declaration + [HRS_IDX_BOBY_SENSOR_LOC_CHAR] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, + CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}}, + + // Body Sensor Location Characteristic Value + [HRS_IDX_BOBY_SENSOR_LOC_VAL] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&body_sensor_location_uuid, ESP_GATT_PERM_READ, + sizeof(uint8_t), sizeof(body_sensor_loc_val), (uint8_t *)body_sensor_loc_val}}, + + // Heart Rate Control Point Characteristic Declaration + [HRS_IDX_HR_CTNL_PT_CHAR] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, + CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}}, + + // Heart Rate Control Point Characteristic Value + [HRS_IDX_HR_CTNL_PT_VAL] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_ctrl_point, ESP_GATT_PERM_WRITE|ESP_GATT_PERM_READ, + sizeof(uint8_t), sizeof(heart_ctrl_point), (uint8_t *)heart_ctrl_point}}, +}; + + + +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + LOG_ERROR("GAP_EVT, event %d\n", event); + + switch (event) { + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + esp_ble_gap_start_advertising(&heart_rate_adv_params); + break; + default: + break; + } +} + +static void gatts_profile_event_handler(esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ + LOG_ERROR("event = %x\n",event); + switch (event) { + case ESP_GATTS_REG_EVT: + LOG_INFO("%s %d\n", __func__, __LINE__); + esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME); + LOG_INFO("%s %d\n", __func__, __LINE__); + esp_ble_gap_config_adv_data(&heart_rate_adv_config); + + LOG_INFO("%s %d\n", __func__, __LINE__); + esp_ble_gatts_create_attr_tab(heart_rate_gatt_db, gatts_if, + HRS_IDX_NB, HEART_RATE_SVC_INST_ID); + break; + case ESP_GATTS_READ_EVT: + + break; + case ESP_GATTS_WRITE_EVT: + break; + case ESP_GATTS_EXEC_WRITE_EVT: + break; + case ESP_GATTS_MTU_EVT: + break; + case ESP_GATTS_CONF_EVT: + break; + case ESP_GATTS_UNREG_EVT: + break; + case ESP_GATTS_DELETE_EVT: + break; + case ESP_GATTS_START_EVT: + break; + case ESP_GATTS_STOP_EVT: + break; + case ESP_GATTS_CONNECT_EVT: + break; + case ESP_GATTS_DISCONNECT_EVT: + break; + case ESP_GATTS_OPEN_EVT: + break; + case ESP_GATTS_CANCEL_OPEN_EVT: + break; + case ESP_GATTS_CLOSE_EVT: + break; + case ESP_GATTS_LISTEN_EVT: + break; + case ESP_GATTS_CONGEST_EVT: + break; + case ESP_GATTS_CREAT_ATTR_TAB_EVT:{ + LOG_ERROR("The number handle =%x\n",param->add_attr_tab.num_handle); + if(param->add_attr_tab.num_handle == HRS_IDX_NB){ + memcpy(heart_rate_handle_table, param->add_attr_tab.handles, + sizeof(heart_rate_handle_table)); + esp_ble_gatts_start_service(heart_rate_handle_table[HRS_IDX_SVC]); + } + + break; + } + + default: + break; + } +} + + +static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) +{ + LOG_INFO("EVT %d, gatts if %d\n", event, gatts_if); + + /* If event is register event, store the gatts_if for each profile */ + if (event == ESP_GATTS_REG_EVT) { + if (param->reg.status == ESP_GATT_OK) { + heart_rate_profile_tab[HEART_PROFILE_APP_IDX].gatts_if = gatts_if; + } else { + LOG_INFO("Reg app failed, app_id %04x, status %d\n", + param->reg.app_id, + param->reg.status); + return; + } + } + + do { + int idx; + for (idx = 0; idx < HEART_PROFILE_NUM; idx++) { + if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */ + gatts_if == heart_rate_profile_tab[idx].gatts_if) { + if (heart_rate_profile_tab[idx].gatts_cb) { + heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param); + } + } + } + } while (0); +} + +void app_main() +{ + esp_err_t ret; + + esp_bt_controller_init(); + LOG_INFO("%s init bluetooth\n", __func__); + ret = esp_bluedroid_init(); + if (ret) { + LOG_ERROR("%s init bluetooth failed\n", __func__); + return; + } + ret = esp_bluedroid_enable(); + if (ret) { + LOG_ERROR("%s enable bluetooth failed\n", __func__); + return; + } + + esp_ble_gatts_register_callback(gatts_event_handler); + esp_ble_gap_register_callback(gap_event_handler); + esp_ble_gatts_app_register(ESP_HEART_RATE_APP_ID); + return; +} diff --git a/examples/33_gatt_server_service_table/main/gatts_table_creat_demo.h b/examples/33_gatt_server_service_table/main/gatts_table_creat_demo.h new file mode 100644 index 000000000..c12d1aa59 --- /dev/null +++ b/examples/33_gatt_server_service_table/main/gatts_table_creat_demo.h @@ -0,0 +1,48 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include + +/* + * DEFINES + **************************************************************************************** + */ + +#define HRPS_HT_MEAS_MAX_LEN (13) + +#define HRPS_MANDATORY_MASK (0x0F) +#define HRPS_BODY_SENSOR_LOC_MASK (0x30) +#define HRPS_HR_CTNL_PT_MASK (0xC0) + + +///Attributes State Machine +enum +{ + HRS_IDX_SVC, + + HRS_IDX_HR_MEAS_CHAR, + HRS_IDX_HR_MEAS_VAL, + HRS_IDX_HR_MEAS_NTF_CFG, + + HRS_IDX_BOBY_SENSOR_LOC_CHAR, + HRS_IDX_BOBY_SENSOR_LOC_VAL, + + HRS_IDX_HR_CTNL_PT_CHAR, + HRS_IDX_HR_CTNL_PT_VAL, + + HRS_IDX_NB, +}; diff --git a/examples/33_gatt_server_service_table/sdkconfig.defaults b/examples/33_gatt_server_service_table/sdkconfig.defaults new file mode 100644 index 000000000..e435f383c --- /dev/null +++ b/examples/33_gatt_server_service_table/sdkconfig.defaults @@ -0,0 +1,14 @@ +# Override some defaults so BT stack is enabled +# in this example + +# +# BT config +# +CONFIG_BT_ENABLED=y + +# +# ESP32-specific config +# +CONFIG_ESP32_ENABLE_STACK_BT=y +# CONFIG_ESP32_ENABLE_STACK_NONE is not set +CONFIG_MEMMAP_BT=y