// 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 #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" #include "esp_event_loop.h" #include "esp_log.h" #include "nvs_flash.h" #include "bt.h" #include "esp_blufi_api.h" #include "esp_bt_defs.h" #include "esp_gap_ble_api.h" #include "esp_bt_main.h" #include "esp_bt_device.h" #include "blufi_example.h" static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param); #define BLUFI_DEVICE_NAME "BLUFI_DEVICE" static uint8_t example_service_uuid128[32] = { /* LSB <--------------------------------------------------------------------------------> MSB */ //first uuid, 16bit, [12],[13] is the value 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, }; //static uint8_t test_manufacturer[TEST_MANUFACTURER_DATA_LEN] = {0x12, 0x23, 0x45, 0x56}; static esp_ble_adv_data_t example_adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, .min_interval = 0x100, .max_interval = 0x100, .appearance = 0x00, .manufacturer_len = 0, .p_manufacturer_data = NULL, .service_data_len = 0, .p_service_data = NULL, .service_uuid_len = 16, .p_service_uuid = example_service_uuid128, .flag = 0x6, }; static esp_ble_adv_params_t example_adv_params = { .adv_int_min = 0x100, .adv_int_max = 0x100, .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, }; #define WIFI_LIST_NUM 10 static wifi_config_t sta_config; static wifi_config_t ap_config; /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; /* The event group allows multiple bits for each event, but we only care about one event - are we connected to the AP with an IP? */ const int CONNECTED_BIT = BIT0; /* store the station info for send back to phone */ static bool gl_sta_connected = false; static uint8_t gl_sta_bssid[6]; static uint8_t gl_sta_ssid[32]; static int gl_sta_ssid_len; /* connect infor*/ static uint8_t server_if; static uint16_t conn_id; static esp_err_t example_net_event_handler(void *ctx, system_event_t *event) { wifi_mode_t mode; switch (event->event_id) { case SYSTEM_EVENT_STA_START: esp_wifi_connect(); break; case SYSTEM_EVENT_STA_GOT_IP: { esp_blufi_extra_info_t info; xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); esp_wifi_get_mode(&mode); memset(&info, 0, sizeof(esp_blufi_extra_info_t)); memcpy(info.sta_bssid, gl_sta_bssid, 6); info.sta_bssid_set = true; info.sta_ssid = gl_sta_ssid; info.sta_ssid_len = gl_sta_ssid_len; esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, 0, &info); break; } case SYSTEM_EVENT_STA_CONNECTED: gl_sta_connected = true; memcpy(gl_sta_bssid, event->event_info.connected.bssid, 6); memcpy(gl_sta_ssid, event->event_info.connected.ssid, event->event_info.connected.ssid_len); gl_sta_ssid_len = event->event_info.connected.ssid_len; break; case SYSTEM_EVENT_STA_DISCONNECTED: /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ gl_sta_connected = false; memset(gl_sta_ssid, 0, 32); memset(gl_sta_bssid, 0, 6); gl_sta_ssid_len = 0; esp_wifi_connect(); xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); break; case SYSTEM_EVENT_AP_START: esp_wifi_get_mode(&mode); /* TODO: get config or information of softap, then set to report extra_info */ if (gl_sta_connected) { esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, 0, NULL); } else { esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, 0, NULL); } break; default: break; } return ESP_OK; } static void initialise_wifi(void) { tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK( esp_event_loop_init(example_net_event_handler, NULL) ); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_start() ); } static esp_blufi_callbacks_t example_callbacks = { .event_cb = example_event_callback, .negotiate_data_handler = blufi_dh_negotiate_data_handler, .encrypt_func = blufi_aes_encrypt, .decrypt_func = blufi_aes_decrypt, .checksum_func = blufi_crc_checksum, }; static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param) { /* actually, should post to blufi_task handle the procedure, * now, as a example, we do it more simply */ switch (event) { case ESP_BLUFI_EVENT_INIT_FINISH: BLUFI_INFO("BLUFI init finish\n"); esp_ble_gap_set_device_name(BLUFI_DEVICE_NAME); esp_ble_gap_config_adv_data(&example_adv_data); break; case ESP_BLUFI_EVENT_DEINIT_FINISH: BLUFI_INFO("BLUFI deinit finish\n"); break; case ESP_BLUFI_EVENT_BLE_CONNECT: BLUFI_INFO("BLUFI ble connect\n"); server_if=param->connect.server_if; conn_id=param->connect.conn_id; esp_ble_gap_stop_advertising(); blufi_security_init(); break; case ESP_BLUFI_EVENT_BLE_DISCONNECT: BLUFI_INFO("BLUFI ble disconnect\n"); blufi_security_deinit(); esp_ble_gap_start_advertising(&example_adv_params); break; case ESP_BLUFI_EVENT_SET_WIFI_OPMODE: BLUFI_INFO("BLUFI Set WIFI opmode %d\n", param->wifi_mode.op_mode); ESP_ERROR_CHECK( esp_wifi_set_mode(param->wifi_mode.op_mode) ); break; case ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP: BLUFI_INFO("BLUFI requset wifi connect to AP\n"); esp_wifi_connect(); break; case ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP: BLUFI_INFO("BLUFI requset wifi disconnect from AP\n"); esp_wifi_disconnect(); break; case ESP_BLUFI_EVENT_GET_WIFI_STATUS: { wifi_mode_t mode; esp_blufi_extra_info_t info; esp_wifi_get_mode(&mode); if (gl_sta_connected ) { memset(&info, 0, sizeof(esp_blufi_extra_info_t)); memcpy(info.sta_bssid, gl_sta_bssid, 6); info.sta_bssid_set = true; info.sta_ssid = gl_sta_ssid; info.sta_ssid_len = gl_sta_ssid_len; esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, 0, &info); } else { esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, 0, NULL); } BLUFI_INFO("BLUFI get wifi status from AP\n"); break; } case ESP_BLUFI_EVENT_RECV_SLAVE_DISCONNECT_BLE: BLUFI_INFO("blufi close a gatt connection"); esp_blufi_close(server_if,conn_id); break; case ESP_BLUFI_EVENT_DEAUTHENTICATE_STA: /* TODO */ break; case ESP_BLUFI_EVENT_RECV_STA_BSSID: memcpy(sta_config.sta.bssid, param->sta_bssid.bssid, 6); sta_config.sta.bssid_set = 1; esp_wifi_set_config(WIFI_IF_STA, &sta_config); BLUFI_INFO("Recv STA BSSID %s\n", sta_config.sta.ssid); break; case ESP_BLUFI_EVENT_RECV_STA_SSID: strncpy((char *)sta_config.sta.ssid, (char *)param->sta_ssid.ssid, param->sta_ssid.ssid_len); sta_config.sta.ssid[param->sta_ssid.ssid_len] = '\0'; esp_wifi_set_config(WIFI_IF_STA, &sta_config); BLUFI_INFO("Recv STA SSID %s\n", sta_config.sta.ssid); break; case ESP_BLUFI_EVENT_RECV_STA_PASSWD: strncpy((char *)sta_config.sta.password, (char *)param->sta_passwd.passwd, param->sta_passwd.passwd_len); sta_config.sta.password[param->sta_passwd.passwd_len] = '\0'; esp_wifi_set_config(WIFI_IF_STA, &sta_config); BLUFI_INFO("Recv STA PASSWORD %s\n", sta_config.sta.password); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_SSID: strncpy((char *)ap_config.ap.ssid, (char *)param->softap_ssid.ssid, param->softap_ssid.ssid_len); ap_config.ap.ssid_len = param->softap_ssid.ssid_len; esp_wifi_set_config(WIFI_IF_AP, &ap_config); BLUFI_INFO("Recv SOFTAP SSID %s, ssid len %d\n", ap_config.ap.ssid, ap_config.ap.ssid_len); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD: strncpy((char *)ap_config.ap.password, (char *)param->softap_passwd.passwd, param->softap_passwd.passwd_len); esp_wifi_set_config(WIFI_IF_AP, &ap_config); BLUFI_INFO("Recv SOFTAP PASSWORD %s\n", ap_config.ap.password); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM: if (param->softap_max_conn_num.max_conn_num > 4) { return; } ap_config.ap.max_connection = param->softap_max_conn_num.max_conn_num; esp_wifi_set_config(WIFI_IF_AP, &ap_config); BLUFI_INFO("Recv SOFTAP MAX CONN NUM %d\n", ap_config.ap.max_connection); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE: if (param->softap_auth_mode.auth_mode >= WIFI_AUTH_MAX) { return; } ap_config.ap.authmode = param->softap_auth_mode.auth_mode; esp_wifi_set_config(WIFI_IF_AP, &ap_config); BLUFI_INFO("Recv SOFTAP AUTH MODE %d\n", ap_config.ap.authmode); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL: if (param->softap_channel.channel > 13) { return; } ap_config.ap.channel = param->softap_channel.channel; esp_wifi_set_config(WIFI_IF_AP, &ap_config); BLUFI_INFO("Recv SOFTAP CHANNEL %d\n", ap_config.ap.channel); break; case ESP_BLUFI_EVENT_RECV_USERNAME: /* Not handle currently */ break; case ESP_BLUFI_EVENT_RECV_CA_CERT: /* Not handle currently */ break; case ESP_BLUFI_EVENT_RECV_CLIENT_CERT: /* Not handle currently */ break; case ESP_BLUFI_EVENT_RECV_SERVER_CERT: /* Not handle currently */ break; case ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY: /* Not handle currently */ break;; case ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY: /* Not handle currently */ break; default: break; } } static void example_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: esp_ble_gap_start_advertising(&example_adv_params); break; default: break; } } void app_main() { esp_err_t ret; // Initialize NVS ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK( ret ); initialise_wifi(); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); ret = esp_bt_controller_init(&bt_cfg); if (ret) { BLUFI_ERROR("%s initialize bt controller failed\n", __func__); } ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); if (ret) { BLUFI_ERROR("%s enable bt controller failed\n", __func__); return; } ret = esp_bluedroid_init(); if (ret) { BLUFI_ERROR("%s init bluedroid failed\n", __func__); return; } ret = esp_bluedroid_enable(); if (ret) { BLUFI_ERROR("%s init bluedroid failed\n", __func__); return; } BLUFI_INFO("BD ADDR: "ESP_BD_ADDR_STR"\n", ESP_BD_ADDR_HEX(esp_bt_dev_get_address())); BLUFI_INFO("BLUFI VERSION %04x\n", esp_blufi_get_version()); blufi_security_init(); esp_ble_gap_register_callback(example_gap_event_handler); esp_blufi_register_callbacks(&example_callbacks); esp_blufi_profile_init(); }