--- a/main/ble_gatts.c Mon Apr 17 16:20:58 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,337 +0,0 @@ -/** - * @file ble_gatts.c - * @brief BLE GATTS services. - */ - -#include "config.h" - -static const char *TAG = "ble_gatts"; - -#define PROFILE_NUM 1 -#define PROFILE_RGB_APP_ID 0 -#define PROFILE_RGB_NUM_HANDLE 3 - -#ifdef USE_BATTERY -/// characteristic presentation information -struct char_pres_fmt -{ - uint16_t unit; ///< Unit (The Unit is a UUID) - uint16_t description; ///< Description - uint8_t format; - uint8_t exponent; - uint8_t name_space; ///< Name space -}; - - -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_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY; -#endif - -uint8_t rgb_service_uuid[ESP_UUID_LEN_128] = {0x00, 0x56, 0xa5, 0x97, 0xd2, 0xb7, 0x2e, 0x81, 0x57, 0x49, 0x00, 0x47, 0x6c, 0x55, 0x02, 0x3b}; -uint8_t rgb_characteristic_uuid[ESP_UUID_LEN_128] = {0x00, 0x56, 0xa5, 0x97, 0xd2, 0xb7, 0x2e, 0x81, 0x57, 0x49, 0x00, 0x47, 0x6c, 0x55, 0x02, 0x3c}; - -static void gatts_profile_rgb_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); - -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; -}; - - -/********************/ - -#ifdef USE_BATTERY -/// battery Service -static const uint16_t battary_svc = ESP_GATT_UUID_BATTERY_SERVICE_SVC; - -static const uint16_t bat_lev_uuid = ESP_GATT_UUID_BATTERY_LEVEL; -static const uint8_t bat_lev_ccc[2] ={ 0x00, 0x00}; -static const uint16_t char_format_uuid = ESP_GATT_UUID_CHAR_PRESENT_FORMAT; - -static uint8_t battary_lev = 50; - -/// Full HRS Database Description - Used to add attributes into the database -static const esp_gatts_attr_db_t bas_att_db[BAS_IDX_NB] = -{ - // Battary Service Declaration - [BAS_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, - sizeof(uint16_t), sizeof(battary_svc), (uint8_t *)&battary_svc}}, - - // Battary level Characteristic Declaration - [BAS_IDX_BATT_LVL_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, - sizeof(uint8_t),sizeof(uint8_t), (uint8_t *)&char_prop_read_notify}}, - - // Battary level Characteristic Value - [BAS_IDX_BATT_LVL_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&bat_lev_uuid, ESP_GATT_PERM_READ, - sizeof(uint8_t),sizeof(uint8_t), &battary_lev}}, - - // Battary level Characteristic - Client Characteristic Configuration Descriptor - [BAS_IDX_BATT_LVL_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(bat_lev_ccc), (uint8_t *)bat_lev_ccc}}, - - // Battary level report Characteristic Declaration - [BAS_IDX_BATT_LVL_PRES_FMT] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&char_format_uuid, ESP_GATT_PERM_READ, - sizeof(struct char_pres_fmt), 0, NULL}}, -}; -#endif - - - -/*******************/ - - -/* 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 gl_profile_tab[PROFILE_NUM] = { - [PROFILE_RGB_APP_ID] = { - .gatts_cb = gatts_profile_rgb_event_handler, - .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ - } -}; - -static void create_rgb_service(esp_gatt_if_t gatts_if) -{ - gl_profile_tab[PROFILE_RGB_APP_ID].service_id.is_primary = true; - gl_profile_tab[PROFILE_RGB_APP_ID].service_id.id.inst_id = 0x00; - gl_profile_tab[PROFILE_RGB_APP_ID].service_id.id.uuid.len = ESP_UUID_LEN_128; - memcpy(gl_profile_tab[PROFILE_RGB_APP_ID].service_id.id.uuid.uuid.uuid128, rgb_service_uuid, ESP_UUID_LEN_128); - - esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_RGB_APP_ID].service_id, PROFILE_RGB_NUM_HANDLE); -} - -static void start_rgb_service(esp_ble_gatts_cb_param_t *param) -{ - gl_profile_tab[PROFILE_RGB_APP_ID].service_handle = param->create.service_handle; - esp_ble_gatts_start_service(gl_profile_tab[PROFILE_RGB_APP_ID].service_handle); -} - -static void add_rgb_characteristic(void) -{ - uint8_t char_value[] = {0x00}; - - esp_attr_value_t rgb_char_val = - { - .attr_max_len = sizeof(char_value), - .attr_len = sizeof(char_value), - .attr_value = char_value, - }; - - gl_profile_tab[PROFILE_RGB_APP_ID].char_uuid.len = ESP_UUID_LEN_128; - memcpy(gl_profile_tab[PROFILE_RGB_APP_ID].char_uuid.uuid.uuid128, rgb_characteristic_uuid, ESP_UUID_LEN_128); - - esp_err_t add_char_ret = esp_ble_gatts_add_char(gl_profile_tab[PROFILE_RGB_APP_ID].service_handle, &gl_profile_tab[PROFILE_RGB_APP_ID].char_uuid, - ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, - ESP_GATT_CHAR_PROP_BIT_WRITE, - &rgb_char_val, NULL); - if (add_char_ret){ - ESP_LOGE(TAG, "add char failed, error code =%x",add_char_ret); - } -} - -static void handle_write_event(uint8_t * p_data, uint16_t len) -{ - uint8_t opcode = p_data[0]; - ESP_LOGI(TAG, "opcode = 0x%x", opcode); - switch (opcode) - { - case 1: -// rgb_ctrl(RGB_RED, RGB_ON); -// rgb_ctrl(RGB_GREEN, RGB_OFF); -// rgb_ctrl(RGB_BLUE, RGB_OFF); - break; - case 2: -// rgb_ctrl(RGB_RED, RGB_OFF); -// rgb_ctrl(RGB_GREEN, RGB_ON); -// rgb_ctrl(RGB_BLUE, RGB_OFF); - break; - case 3: -// rgb_ctrl(RGB_RED, RGB_OFF); -// rgb_ctrl(RGB_GREEN, RGB_OFF); -// rgb_ctrl(RGB_BLUE, RGB_ON); - break; - case 4: -// rgb_ctrl(RGB_RED, RGB_OFF); -// rgb_ctrl(RGB_GREEN, RGB_OFF); -// rgb_ctrl(RGB_BLUE, RGB_OFF); - break; - default: - break; - } -} - - -static void gatts_profile_rgb_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) -{ - ESP_LOGI(TAG, "gatts_profile_rgb_event_handler()"); - - switch (event) { - case ESP_GATTS_REG_EVT: - ESP_LOGI(TAG, "REGISTER_APP_EVT, status %d, app_id %d", param->reg.status, param->reg.app_id); - ble_balkon_adv_config(); - create_rgb_service(gatts_if); - break; - case ESP_GATTS_READ_EVT: { - ESP_LOGI(TAG, "GATT_READ_EVT, conn_id %d, trans_id %lu, handle %d\n", param->read.conn_id, param->read.trans_id, param->read.handle); - break; - } - case ESP_GATTS_WRITE_EVT: { - ESP_LOGI(TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %lu, handle %d", param->write.conn_id, param->write.trans_id, param->write.handle); - if (!param->write.is_prep){ - ESP_LOGI(TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); - esp_log_buffer_hex(TAG, param->write.value, param->write.len); - handle_write_event(param->write.value, param->write.len); - } - esp_gatt_status_t status = ESP_GATT_OK; - if (param->write.need_rsp){ - if (!param->write.is_prep){ - esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, NULL); - } - } - break; - } - case ESP_GATTS_EXEC_WRITE_EVT: - ESP_LOGI(TAG,"ESP_GATTS_EXEC_WRITE_EVT"); - break; - case ESP_GATTS_MTU_EVT: - ESP_LOGI(TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu); - break; - case ESP_GATTS_UNREG_EVT: - break; - case ESP_GATTS_CREATE_EVT: - ESP_LOGI(TAG, "CREATE_SERVICE_EVT, status %d, service_handle %d", param->create.status, param->create.service_handle); - start_rgb_service(param); - add_rgb_characteristic(); - break; - case ESP_GATTS_ADD_INCL_SRVC_EVT: - break; - case ESP_GATTS_ADD_CHAR_EVT: { - ESP_LOGI(TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d", - param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); - break; - } - case ESP_GATTS_ADD_CHAR_DESCR_EVT: - ESP_LOGI(TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d", - param->add_char_descr.status, param->add_char_descr.attr_handle, param->add_char_descr.service_handle); - break; - case ESP_GATTS_DELETE_EVT: - break; - case ESP_GATTS_START_EVT: - ESP_LOGI(TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle); - break; - case ESP_GATTS_STOP_EVT: - break; - case ESP_GATTS_CONNECT_EVT: { - esp_ble_conn_update_params_t conn_params = {0}; - memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); - /* For the IOS system, please reference the apple official documents about the ble connection parameters restrictions. */ - conn_params.latency = 0; - conn_params.max_int = 0x20; // max_int = 0x20*1.25ms = 40ms - conn_params.min_int = 0x10; // min_int = 0x10*1.25ms = 20ms - conn_params.timeout = 400; // timeout = 400*10ms = 4000ms - ESP_LOGI(TAG, "ESP_GATTS_CONNECT_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x:", - param->connect.conn_id, - param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2], - param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5]); - gl_profile_tab[PROFILE_RGB_APP_ID].conn_id = param->connect.conn_id; - //start sent the update connection parameters to the peer device. - esp_ble_gap_update_conn_params(&conn_params); - break; - } - case ESP_GATTS_DISCONNECT_EVT: - ESP_LOGI(TAG, "ESP_GATTS_DISCONNECT_EVT, disconnect reason 0x%x", param->disconnect.reason); - ble_balkon_adv_start(); - break; - case ESP_GATTS_CONF_EVT: - ESP_LOGI(TAG, "ESP_GATTS_CONF_EVT, status %d attr_handle %d", param->conf.status, param->conf.handle); - if (param->conf.status != ESP_GATT_OK){ - esp_log_buffer_hex(TAG, param->conf.value, param->conf.len); - } - break; - case ESP_GATTS_OPEN_EVT: - case ESP_GATTS_CANCEL_OPEN_EVT: - case ESP_GATTS_CLOSE_EVT: - case ESP_GATTS_LISTEN_EVT: - case ESP_GATTS_CONGEST_EVT: - 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) -{ - ESP_LOGI(TAG, "gatts_event_handler(%x)", event); - - /* 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) { - gl_profile_tab[param->reg.app_id].gatts_if = gatts_if; - } else { - ESP_LOGI(TAG, "Reg app failed, app_id %04x, status %d", param->reg.app_id, param->reg.status); - return; - } - } - - /* If the gatts_if equal to profile A, call profile A cb handler, - * so here call each profile's callback */ - do { - int idx; - for (idx = 0; idx < 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 == gl_profile_tab[idx].gatts_if) { - if (gl_profile_tab[idx].gatts_cb) { - gl_profile_tab[idx].gatts_cb(event, gatts_if, param); - } - } - } - } while (0); -} - - -/***************************************************************************************************************************/ - -esp_err_t ble_balkon_gatts_register(void) -{ - esp_err_t ret = esp_ble_gatts_register_callback(gatts_event_handler); - if (ret){ - ESP_LOGE(TAG, "gatts register error, error code = %x", ret); - } - - return ret; -} - - -esp_err_t ble_balkon_gatts_app_register(void) -{ - esp_err_t ret = esp_ble_gatts_app_register(PROFILE_RGB_APP_ID); - if (ret){ - ESP_LOGE(TAG, "gatts app register error, error code = %x", ret); - } - - return ret; -} - - -esp_err_t ble_balkon_gatts_set_mtu(void) -{ - esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500); - if (local_mtu_ret){ - ESP_LOGE(TAG, "set local MTU failed, error code = %x", local_mtu_ret); - } - - return local_mtu_ret; -} - -