]> granicus.if.org Git - esp-idf/blob - examples/bluetooth/ble_spp_client/main/spp_client_demo.c
Update spp_client_demo.c
[esp-idf] / examples / bluetooth / ble_spp_client / main / spp_client_demo.c
1 // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16
17 /****************************************************************************
18 *
19 * This file is for ble spp client demo.
20 *
21 ****************************************************************************/
22
23 #include <stdint.h>
24 #include <string.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include "controller.h"
28 #include "driver/uart.h"
29
30 #include "bt.h"
31 #include "nvs_flash.h"
32 #include "esp_bt_device.h"
33 #include "esp_gap_ble_api.h"
34 #include "esp_gattc_api.h"
35 #include "esp_gatt_defs.h"
36 #include "esp_bt_main.h"
37 #include "esp_system.h"
38 #include "btc_main.h"
39 #include "esp_gatt_common_api.h"
40
41 #define GATTC_TAG                   "GATTC_SPP_DEMO"
42 #ifdef SUPPORT_NEW_GATTC_API
43 #define PROFILE_NUM                 1
44 #define PROFILE_APP_ID              0
45 #define BT_BD_ADDR_STR              "%02x:%02x:%02x:%02x:%02x:%02x"
46 #define BT_BD_ADDR_HEX(addr)        addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]
47
48 #define SPP_SRV_INDEX               1
49 #define SPP_DATA_RECV_CHAR_INDEX    1
50 #define SPP_DATA_NTFY_CHAR_INDEX    2
51 #define SPP_CMD_CHAR_INDEX          3
52 #define SPP_STATUS_CHAR_INDEX       4
53 #define SPP_HEARTBEAT_CHAR_INDEX    5
54 #define SPP_NO_DESC                 0
55 #define SPP_IS_DESC                 1
56
57 //#define SUPPORT_HEARTBEAT
58 //#define DEBUG_MODE
59
60 typedef struct spp_ble_gattc_char_descr {
61     int char_descr_index;
62     uint16_t conn_id;
63     esp_gatt_id_t descr_id;
64     struct spp_ble_gattc_char_descr *next;
65 } spp_ble_gattc_char_descr_t;
66
67 typedef struct spp_ble_gattc_char {
68     int srv_index;
69     int index;
70     uint16_t conn_id;
71     esp_gatt_srvc_id_t srvc_id;
72     esp_gatt_id_t char_id;
73     esp_gatt_char_prop_t char_prop;
74     spp_ble_gattc_char_descr_t * char_descr;
75     struct spp_ble_gattc_char *next;
76 } spp_ble_gattc_char_t;
77
78 typedef struct {
79     int32_t len;
80     spp_ble_gattc_char_t * pfirst;
81     spp_ble_gattc_char_t * plast;
82 } spp_ble_gattc_char_head;
83
84 typedef struct at_ble_gattc_srv {
85     int index;
86     uint16_t conn_id;
87     esp_gatt_srvc_id_t srvc_id;
88     spp_ble_gattc_char_head * gattc_srv_char_head;
89     struct at_ble_gattc_srv *next;
90 } spp_ble_gattc_srv_t;
91
92 typedef struct {
93     int32_t len;
94     spp_ble_gattc_srv_t * pfirst;
95     spp_ble_gattc_srv_t * plast;
96 } spp_ble_gattc_srv_head;
97
98 static spp_ble_gattc_srv_head pAtGattcSrvHead = {
99     .len    = 0,
100     .pfirst = NULL,
101     .plast  = NULL
102 };
103
104 struct gattc_profile_inst {
105     esp_gattc_cb_t gattc_cb;
106     uint16_t gattc_if;
107     uint16_t app_id;
108     uint16_t conn_id;
109     esp_bd_addr_t remote_bda;
110 };
111
112 ///Declare static functions
113 static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
114 static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
115 static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
116
117 /* One gatt-based profile one app_id and one gattc_if, this array will store the gattc_if returned by ESP_GATTS_REG_EVT */
118 static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = {
119     [PROFILE_APP_ID] = {
120         .gattc_cb = gattc_profile_event_handler,
121         .gattc_if = ESP_GATT_IF_NONE,       /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
122     },
123 };
124
125 static esp_ble_scan_params_t ble_scan_params = {
126     .scan_type              = BLE_SCAN_TYPE_ACTIVE,
127     .own_addr_type          = BLE_ADDR_TYPE_PUBLIC,
128     .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,
129     .scan_interval          = 0x50,
130     .scan_window            = 0x30
131 };
132
133
134 static const char device_name[] = "ESP_SPP_SERVER";
135 static bool is_connect = false;
136 static uint16_t spp_conn_id = 0;
137 static uint16_t spp_mtu_size = 23;
138 static uint16_t cmd = 0;
139 static uint16_t wr_descr_ccc_num = 0;
140 static uint16_t spp_gattc_if = 0xff;
141 static int need_notify_number  = 0;
142 static int char_descr_index_count = 0;
143 static char * notify_value_p = NULL;
144 static int notify_value_offset = 0;
145 static int notify_value_count = 0;
146 static spp_ble_gattc_srv_t * temp_srv_p = NULL;
147 static spp_ble_gattc_char_t * notify_char_pp = NULL;
148 static spp_ble_gattc_char_t notify_char_p[3] ;
149 static spp_ble_gattc_char_t * temp_gattc_char_p1 = NULL;
150 static spp_ble_gattc_char_descr_t * notify_char_descr_p[2] = {NULL,NULL};
151 static spp_ble_gattc_char_descr_t * temp_char_descr_p = NULL;
152 static spp_ble_gattc_char_head * pGattcCharHead = NULL;
153 static esp_ble_gap_cb_param_t scan_rst;
154 static xQueueHandle cmd_reg_queue = NULL;
155 static xQueueHandle cmd_read_queue = NULL;
156 QueueHandle_t spp_uart_queue = NULL;
157 #ifdef SUPPORT_HEARTBEAT
158 static uint8_t  heartbeat_s[9] = {'E','s','p','r','e','s','s','i','f'};
159 static xQueueHandle cmd_heartbeat_queue = NULL;
160 #endif
161
162 static void print_srv_node(void)
163 {
164     temp_srv_p = pAtGattcSrvHead.pfirst;
165
166     if(temp_srv_p == NULL){
167         ESP_LOGE(GATTC_TAG, "temp_srv_p == NULL,%s L#%d\n",__func__,__LINE__);
168     }
169     temp_srv_p = pAtGattcSrvHead.pfirst;
170     while(temp_srv_p != NULL){
171         ESP_LOGI(GATTC_TAG,"+SRV:No.%d,UUID:0x%04x\n", temp_srv_p->index,temp_srv_p->srvc_id.id.uuid.uuid.uuid16);
172         temp_srv_p = temp_srv_p->next;
173     }
174 }
175
176 static void get_char_and_descr(void)
177 {
178     pGattcCharHead = (spp_ble_gattc_char_head *)malloc(sizeof(spp_ble_gattc_char_head));
179     if(pGattcCharHead == NULL){
180         ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
181         return;
182     }
183
184     pGattcCharHead->len = 0;
185     pGattcCharHead->pfirst = NULL;
186     pGattcCharHead->plast = NULL;
187     pAtGattcSrvHead.pfirst->gattc_srv_char_head = pGattcCharHead;
188     temp_srv_p = pAtGattcSrvHead.pfirst;
189
190     esp_ble_gattc_get_characteristic(spp_gattc_if, temp_srv_p->conn_id, &temp_srv_p->srvc_id, NULL);
191 }
192
193 static void Characteristic_Rd(int32_t srv_index,int32_t char_index)
194 {
195     spp_ble_gattc_char_t * pGattc_char_node = NULL;
196
197     temp_srv_p = pAtGattcSrvHead.pfirst;
198     if(temp_srv_p == NULL) {
199         ESP_LOGE(GATTC_TAG, "temp_srv_p == NULL,%s L#%d\n",__func__,__LINE__);
200         return ;
201     }
202     while(--srv_index) {
203         temp_srv_p = temp_srv_p->next;
204         if (temp_srv_p == NULL) {
205             ESP_LOGE(GATTC_TAG, "temp_srv_p == NULL,%s L#%d\n",__func__,__LINE__);
206             return ;
207         }
208     }
209     pGattcCharHead = temp_srv_p->gattc_srv_char_head;
210     if(pGattcCharHead == NULL){
211         ESP_LOGE(GATTC_TAG, "pGattcCharHead == NULL,%s L#%d\n",__func__,__LINE__);
212         return;
213     }
214
215     pGattc_char_node = pGattcCharHead->pfirst;
216     if(pGattc_char_node == NULL) {
217         ESP_LOGE(GATTC_TAG, "pGattc_char_node == NULL,%s L#%d\n",__func__,__LINE__);
218         return ;
219     }
220     while(--char_index){
221         pGattc_char_node = pGattc_char_node->next;
222         if(pGattc_char_node == NULL){
223             ESP_LOGE(GATTC_TAG, "pGattc_char_node == NULL,%s L#%d\n",__func__,__LINE__);
224             return ;
225         }
226     }
227
228     esp_ble_gattc_read_char(spp_gattc_if, pGattc_char_node->conn_id, &pGattc_char_node->srvc_id, &pGattc_char_node->char_id, ESP_GATT_AUTH_REQ_NONE);
229 }
230
231 static void  Characteristic_Wr(int32_t srv_index,int32_t char_index,char * s ,size_t length)
232 {
233     future_t **future_p = NULL;
234     int32_t len = 0;
235     spp_ble_gattc_char_t * pGattc_char_node;
236     uint8_t * spp_gattc_wr_buffer = NULL;
237
238     if(length == 0) {
239         return ;
240     }
241     len = length;
242
243     temp_srv_p = pAtGattcSrvHead.pfirst;
244     if(temp_srv_p == NULL) {
245         ESP_LOGE(GATTC_TAG, "temp_srv_p == NULL,%s L#%d\n",__func__,__LINE__);
246         return ;
247     }
248     while(--srv_index) {
249         temp_srv_p = temp_srv_p->next;
250         if (temp_srv_p == NULL) {
251             ESP_LOGE(GATTC_TAG, "temp_srv_p == NULL,%s L#%d\n",__func__,__LINE__);
252             return ;
253         }
254     }
255
256     pGattcCharHead = temp_srv_p->gattc_srv_char_head;
257     if(pGattcCharHead == NULL){
258         ESP_LOGE(GATTC_TAG, "pGattcCharHead == NULL,%s L#%d\n",__func__,__LINE__);
259         return ;
260     }
261     pGattc_char_node = pGattcCharHead->pfirst;
262     if (pGattc_char_node == NULL) {
263         ESP_LOGE(GATTC_TAG, "pGattc_char_node == NULL,%s L#%d\n",__func__,__LINE__);
264         return ;
265     }
266     while(--char_index){
267         pGattc_char_node = pGattc_char_node->next;
268         if(pGattc_char_node == NULL){
269             ESP_LOGE(GATTC_TAG, "pGattc_char_node == NULL,%s L#%d\n",__func__,__LINE__);
270             return ;
271         }
272     }
273
274     spp_gattc_wr_buffer = (uint8_t *)malloc(sizeof(uint8_t)*(len));
275     if(spp_gattc_wr_buffer == NULL){
276         ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
277         return;
278     }
279     memcpy(spp_gattc_wr_buffer,s,len);
280
281     if((pGattc_char_node->char_prop & (ESP_GATT_CHAR_PROP_BIT_WRITE_NR|ESP_GATT_CHAR_PROP_BIT_WRITE)) == 0){
282         ESP_LOGE(GATTC_TAG,"char_prop do not allow write\n");
283         free(spp_gattc_wr_buffer);
284         return ;
285     }
286
287     future_p = btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE);
288     *future_p = future_new();
289     if (*future_p == NULL) {
290         ESP_LOGE(GATTC_TAG,"%s failed\n", __func__);
291         return;
292     }
293     esp_ble_gattc_write_char(spp_gattc_if, pGattc_char_node->conn_id, &pGattc_char_node->srvc_id, &pGattc_char_node->char_id, len,spp_gattc_wr_buffer, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
294     free(spp_gattc_wr_buffer);
295     if(future_await(*future_p) == FUTURE_FAIL) {
296         ESP_LOGE(GATTC_TAG,"%s failed\n", __func__);
297         return;
298     }
299
300     return ;
301 }
302
303 static void store_srv_info(esp_ble_gattc_cb_param_t * p_data)
304 {
305     spp_ble_gattc_srv_t * pGattc_srv_node = NULL;
306
307     pGattc_srv_node = (spp_ble_gattc_srv_t *)malloc(sizeof(spp_ble_gattc_srv_t));
308     if (pGattc_srv_node == NULL) {
309         ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
310         return;
311     }
312     pGattc_srv_node->conn_id = p_data->search_res.conn_id;
313     pGattc_srv_node->next = NULL;
314     pGattc_srv_node->gattc_srv_char_head = NULL;
315     pGattc_srv_node->index = pAtGattcSrvHead.len + 1;
316     pGattc_srv_node->srvc_id.is_primary = p_data->search_res.srvc_id.is_primary;
317     pGattc_srv_node->srvc_id.id.inst_id = p_data->search_res.srvc_id.id.inst_id;
318     pGattc_srv_node->srvc_id.id.uuid.len = p_data->search_res.srvc_id.id.uuid.len;
319     pGattc_srv_node->srvc_id.id.uuid.uuid.uuid16 = p_data->search_res.srvc_id.id.uuid.uuid.uuid16;
320
321     if (pAtGattcSrvHead.len == 0) {
322         pAtGattcSrvHead.len++;
323         pAtGattcSrvHead.pfirst = pGattc_srv_node;
324         pAtGattcSrvHead.plast = pGattc_srv_node;
325     } else {
326         pAtGattcSrvHead.len++;
327         pAtGattcSrvHead.plast->next = pGattc_srv_node;
328         pAtGattcSrvHead.plast = pGattc_srv_node;
329     }
330 }
331
332 static void store_char_info(esp_ble_gattc_cb_param_t * p_data)
333 {
334     spp_ble_gattc_char_t * pGattc_char_node = NULL;
335
336     pGattc_char_node = (spp_ble_gattc_char_t *)malloc(sizeof(spp_ble_gattc_char_t));
337     if(pGattc_char_node == NULL){
338         ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
339         return;
340     }
341     pGattc_char_node->srv_index = temp_srv_p->index;
342     pGattc_char_node->char_descr = NULL;
343     pGattc_char_node->conn_id = p_data->get_char.conn_id;
344     pGattc_char_node->next = NULL;
345     pGattc_char_node->index = pGattcCharHead->len + 1;
346     pGattc_char_node->srvc_id.is_primary = p_data->get_char.srvc_id.is_primary;
347     pGattc_char_node->srvc_id.id.inst_id = p_data->get_char.srvc_id.id.inst_id;
348     pGattc_char_node->srvc_id.id.uuid.len = p_data->get_char.srvc_id.id.uuid.len;
349     pGattc_char_node->srvc_id.id.uuid.uuid.uuid16 = p_data->get_char.srvc_id.id.uuid.uuid.uuid16;
350
351     pGattc_char_node->char_id.inst_id = p_data->get_char.char_id.inst_id;
352     pGattc_char_node->char_id.uuid.len = p_data->get_char.char_id.uuid.len;
353     pGattc_char_node->char_prop = p_data->get_char.char_prop;
354     pGattc_char_node->char_id.uuid.uuid.uuid16 = p_data->get_char.char_id.uuid.uuid.uuid16;
355
356     temp_gattc_char_p1 = pGattc_char_node;
357
358     if (pGattcCharHead->len == 0) {
359         pGattcCharHead->len++;
360         pGattcCharHead->pfirst = pGattc_char_node;
361         pGattcCharHead->plast = pGattc_char_node;
362     } else {
363         pGattcCharHead->len++;
364         pGattcCharHead->plast->next = pGattc_char_node;
365         pGattcCharHead->plast = pGattc_char_node;
366     }
367     esp_ble_gattc_get_descriptor(spp_gattc_if, pGattc_char_node->conn_id, &pGattc_char_node->srvc_id, &pGattc_char_node->char_id, NULL);
368 }
369
370 static void store_desc_info(esp_ble_gattc_cb_param_t * p_data)
371 {
372     spp_ble_gattc_char_descr_t * pGattc_char_node_descr = NULL;
373
374     temp_char_descr_p = temp_gattc_char_p1->char_descr;
375     pGattc_char_node_descr = (spp_ble_gattc_char_descr_t *)malloc(sizeof(spp_ble_gattc_char_descr_t));
376     if(pGattc_char_node_descr == NULL){
377         ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
378         return;
379     }
380     pGattc_char_node_descr->conn_id = p_data->get_descr.conn_id;
381     pGattc_char_node_descr->char_descr_index = ++char_descr_index_count;
382     if (temp_char_descr_p == NULL)
383         temp_gattc_char_p1->char_descr = pGattc_char_node_descr;
384     else {
385         while (temp_char_descr_p->next != NULL) {
386             temp_char_descr_p = temp_char_descr_p->next;
387         }
388         temp_char_descr_p->next = pGattc_char_node_descr;
389     }
390     pGattc_char_node_descr->next = NULL;
391     pGattc_char_node_descr->descr_id.inst_id = p_data->get_descr.descr_id.inst_id;
392     pGattc_char_node_descr->descr_id.uuid.len = p_data->get_descr.descr_id.uuid.len;
393
394     pGattc_char_node_descr->descr_id.uuid.uuid.uuid16 = p_data->get_descr.descr_id.uuid.uuid.uuid16;
395     if((p_data->get_descr.descr_id.uuid.uuid.uuid16 == 0x2902)&&(need_notify_number<3)){
396         memset(&(notify_char_p[need_notify_number]),0x0,sizeof(spp_ble_gattc_char_t));
397         memcpy(&(notify_char_p[need_notify_number]),temp_gattc_char_p1,sizeof(spp_ble_gattc_char_t));
398         notify_char_descr_p[need_notify_number] = pGattc_char_node_descr;
399         ESP_LOGI(GATTC_TAG,"need_notify_number=%d\n",need_notify_number);
400         ESP_LOGI(GATTC_TAG,"- srvc_id = 0x%04x, char_id = 0x%04x \n", notify_char_p[need_notify_number].srvc_id.id.uuid.uuid.uuid16, notify_char_p[need_notify_number].char_id.uuid.uuid.uuid16);
401         need_notify_number++;
402     }
403     esp_ble_gattc_get_descriptor(spp_gattc_if, temp_gattc_char_p1->conn_id, &temp_gattc_char_p1->srvc_id, &temp_gattc_char_p1->char_id, &pGattc_char_node_descr->descr_id);
404 }
405
406 static void notify_event_handler(esp_ble_gattc_cb_param_t * p_data)
407 {
408     uint8_t gattc_srv_index_for_port = 0;
409     uint8_t gattc_char_index_for_port = 0;
410
411     temp_srv_p = pAtGattcSrvHead.pfirst;
412     while(temp_srv_p != NULL){
413         if(temp_srv_p->srvc_id.id.uuid.uuid.uuid16 ==  p_data->notify.srvc_id.id.uuid.uuid.uuid16){
414             gattc_srv_index_for_port = temp_srv_p->index;
415             pGattcCharHead = temp_srv_p->gattc_srv_char_head;
416             if(pGattcCharHead != NULL){
417                 notify_char_pp = pGattcCharHead->pfirst;
418                 while(notify_char_pp != NULL){
419                     if(notify_char_pp->char_id.uuid.uuid.uuid16== p_data->notify.char_id.uuid.uuid.uuid16){
420                         gattc_char_index_for_port = notify_char_pp->index;
421                     }
422                     notify_char_pp = notify_char_pp->next;
423                 }
424             }
425         }
426         temp_srv_p = temp_srv_p->next;
427     }
428     if(p_data->notify.is_notify == true){
429         ESP_LOGI(GATTC_TAG,"+NOTIFY:%d,%d,%d,",gattc_srv_index_for_port,gattc_char_index_for_port,p_data->notify.value_len);
430     }else{
431         ESP_LOGI(GATTC_TAG,"+INDICATE:%d,%d,%d,",gattc_srv_index_for_port,gattc_char_index_for_port,p_data->notify.value_len);
432     }
433     if((gattc_srv_index_for_port == SPP_SRV_INDEX)&&(gattc_char_index_for_port == SPP_DATA_NTFY_CHAR_INDEX)){
434 #ifdef SPP_DEBUG_MODE
435         esp_log_buffer_char(GATTC_TAG, (char *)p_data->notify.value, p_data->notify.value_len);
436 #else
437         if((p_data->notify.value[0] == '#')&&(p_data->notify.value[1] == '#')){
438             if((++notify_value_count) != p_data->notify.value[3]){
439                 if(notify_value_p != NULL){
440                     free(notify_value_p);
441                 }
442                 notify_value_count = 0;
443                 notify_value_p = NULL;
444                 notify_value_offset = 0;
445                 ESP_LOGE(GATTC_TAG,"notify value count is not continuous,%s\n",__func__);
446                 return;
447             }
448             if(p_data->notify.value[3] == 1){
449                 notify_value_p = (char *)malloc(((spp_mtu_size-7)*(p_data->notify.value[2]))*sizeof(char));
450                 if(notify_value_p == NULL){
451                     ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
452                     notify_value_count = 0;
453                     return;
454                 }
455                 memcpy((notify_value_p + notify_value_offset),(p_data->notify.value + 4),(p_data->notify.value_len - 4));
456                 if(p_data->notify.value[2] == p_data->notify.value[3]){
457                     uart_write_bytes(UART_NUM_0, (char *)(notify_value_p), (p_data->notify.value_len - 4 + notify_value_offset));
458                     free(notify_value_p);
459                     notify_value_p = NULL;
460                     notify_value_offset = 0;
461                     return;
462                 }
463                 notify_value_offset += (p_data->notify.value_len - 4);
464             }else if(p_data->notify.value[3] <= p_data->notify.value[2]){
465                 memcpy((notify_value_p + notify_value_offset),(p_data->notify.value + 4),(p_data->notify.value_len - 4));
466                 if(p_data->notify.value[3] == p_data->notify.value[2]){
467                     uart_write_bytes(UART_NUM_0, (char *)(notify_value_p), (p_data->notify.value_len - 4 + notify_value_offset));
468                     free(notify_value_p);
469                     notify_value_count = 0;
470                     notify_value_p = NULL;
471                     notify_value_offset = 0;
472                     return;
473                 }
474                 notify_value_offset += (p_data->notify.value_len - 4);
475             }
476         }else{
477             uart_write_bytes(UART_NUM_0, (char *)(p_data->notify.value), p_data->notify.value_len);
478         }
479 #endif
480     }else if((gattc_srv_index_for_port == SPP_SRV_INDEX)&&(gattc_char_index_for_port == SPP_STATUS_CHAR_INDEX)){
481         esp_log_buffer_char(GATTC_TAG, (char *)p_data->notify.value, p_data->notify.value_len);
482         //TODO:server notify status characteristic
483     }else{
484         esp_log_buffer_char(GATTC_TAG, (char *)p_data->notify.value, p_data->notify.value_len);
485     }
486 }
487
488 static void read_event_handler(esp_ble_gattc_cb_param_t * p_data)
489 {
490     uint8_t gattc_srv_index_for_port = 0;
491     uint8_t gattc_char_index_for_port = 0;
492
493     temp_srv_p = pAtGattcSrvHead.pfirst;
494     while(temp_srv_p != NULL){
495         if(temp_srv_p->srvc_id.id.uuid.uuid.uuid16 ==  p_data->notify.srvc_id.id.uuid.uuid.uuid16){
496             gattc_srv_index_for_port = temp_srv_p->index;
497             pGattcCharHead = temp_srv_p->gattc_srv_char_head;
498             if(pGattcCharHead != NULL){
499                 notify_char_pp = pGattcCharHead->pfirst;
500                 while(notify_char_pp != NULL){
501                     if(notify_char_pp->char_id.uuid.uuid.uuid16== p_data->notify.char_id.uuid.uuid.uuid16){
502                         gattc_char_index_for_port = notify_char_pp->index;
503                     }
504                     notify_char_pp = notify_char_pp->next;
505                 }
506             }
507         }
508         temp_srv_p = temp_srv_p->next;
509     }
510
511     if((gattc_srv_index_for_port == SPP_SRV_INDEX)&&(gattc_char_index_for_port == SPP_STATUS_CHAR_INDEX)){
512         //TODO: read status characteristic
513     }
514 }
515
516 static void printf_char_and_descr(uint8_t srv_index)
517 {
518     spp_ble_gattc_char_t * temp_gattc_char_p = NULL;
519     spp_ble_gattc_char_descr_t * temp_gattc_char_descr_p = NULL;
520
521     temp_srv_p = pAtGattcSrvHead.pfirst;
522
523     if(temp_srv_p == NULL){
524         ESP_LOGE(GATTC_TAG, "srv = NULL\n");
525     }
526     while(--srv_index){
527         temp_srv_p = temp_srv_p->next;
528         if(temp_srv_p == NULL){
529             ESP_LOGE(GATTC_TAG, "srv = NULL\n");
530         }
531     }
532
533     temp_gattc_char_p = temp_srv_p->gattc_srv_char_head->pfirst;
534     while(temp_gattc_char_p != NULL){
535         ESP_LOGI(GATTC_TAG,"+CHAR:%d,%d,UUID:0x%04x",temp_srv_p->index, temp_gattc_char_p->index,temp_gattc_char_p->char_id.uuid.uuid.uuid16);
536
537         temp_gattc_char_descr_p = temp_gattc_char_p->char_descr;
538         while(temp_gattc_char_descr_p != NULL){
539             ESP_LOGI(GATTC_TAG,"+DESC:%d,%d,%d,UUID:0x%04x",temp_srv_p->index, temp_gattc_char_p->index,temp_gattc_char_descr_p->char_descr_index,temp_gattc_char_descr_p->descr_id.uuid.uuid.uuid16);
540             temp_gattc_char_descr_p = temp_gattc_char_descr_p->next;
541         }
542         temp_gattc_char_p = temp_gattc_char_p->next;
543     }
544     return ;
545 }
546
547 static void free_gattc_srv_db(void)
548 {
549     spp_ble_gattc_srv_t * temp_service_p = NULL , * temp_service_pp = NULL;
550     spp_ble_gattc_char_head * temp_srv_char_head_p = NULL;
551     spp_ble_gattc_char_t * temp_gattc_char_node_p = NULL , *temp_gattc_char_node_pp =NULL;
552     spp_ble_gattc_char_descr_t * temp_gattc_char_descr_node_p = NULL,* temp_gattc_char_descr_node_pp = NULL;
553
554     temp_service_p = pAtGattcSrvHead.pfirst;
555     while(temp_service_p != NULL){
556         temp_srv_char_head_p = temp_service_p->gattc_srv_char_head;
557         temp_gattc_char_node_p = temp_srv_char_head_p->pfirst;
558         while(temp_gattc_char_node_p != NULL){
559             temp_gattc_char_node_pp = temp_gattc_char_node_p;
560             temp_gattc_char_descr_node_p = temp_gattc_char_node_pp->char_descr;
561             while(temp_gattc_char_descr_node_p != NULL){
562                 temp_gattc_char_descr_node_pp = temp_gattc_char_descr_node_p;
563                 temp_gattc_char_descr_node_p = temp_gattc_char_descr_node_p->next;
564                 free(temp_gattc_char_descr_node_pp);
565             }
566             temp_gattc_char_node_p = temp_gattc_char_node_p->next;
567             free(temp_gattc_char_node_pp);
568         }
569         free(temp_srv_char_head_p);
570
571         temp_service_pp = temp_service_p;
572         temp_service_p = temp_service_p->next;
573         free(temp_service_pp);
574     }
575     pAtGattcSrvHead.len = 0;
576     pAtGattcSrvHead.pfirst = NULL;
577     pAtGattcSrvHead.plast = NULL;
578     is_connect = false;
579     spp_conn_id = 0;
580     spp_mtu_size = 23;
581     cmd = 0;
582     wr_descr_ccc_num = 0;
583     spp_gattc_if = 0xff;
584     need_notify_number  = 0;
585     char_descr_index_count = 0;
586     notify_value_p = NULL;
587     notify_value_offset = 0;
588     notify_value_count = 0;
589 }
590
591 static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
592 {
593     uint8_t *adv_name = NULL;
594     uint8_t adv_name_len = 0;
595
596     switch(event){
597     case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
598         if(param->scan_param_cmpl.status != ESP_BT_STATUS_SUCCESS){
599             ESP_LOGE(GATTC_TAG, "Scan param set failed");
600             break;
601         }
602         //the unit of the duration is second
603         uint32_t duration = 0xFFFF;
604         ESP_LOGI(GATTC_TAG, "Enable Ble Scan:during time 0x%04X minutes.",duration);
605         esp_ble_gap_start_scanning(duration);
606         break;
607     }
608     case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
609         //scan start complete event to indicate scan start successfully or failed
610         if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
611             ESP_LOGE(GATTC_TAG, "Scan start failed");
612             break;
613         }
614         ESP_LOGI(GATTC_TAG, "Scan start successed");
615         break;
616     case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
617         if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
618             ESP_LOGE(GATTC_TAG, "Scan stop failed");
619             break;
620         }
621         ESP_LOGI(GATTC_TAG, "Scan stop successed");
622         if (is_connect == false) {
623             ESP_LOGI(GATTC_TAG, "Connect to the remote device.");
624             esp_ble_gattc_open(gl_profile_tab[PROFILE_APP_ID].gattc_if, scan_rst.scan_rst.bda, true);
625         }
626         break;
627     case ESP_GAP_BLE_SCAN_RESULT_EVT: {
628         esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
629         switch (scan_result->scan_rst.search_evt) {
630         case ESP_GAP_SEARCH_INQ_RES_EVT:
631             esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6);
632             ESP_LOGI(GATTC_TAG, "Searched Adv Data Len %d, Scan Response Len %d", scan_result->scan_rst.adv_data_len, scan_result->scan_rst.scan_rsp_len);
633             adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv,ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
634             ESP_LOGI(GATTC_TAG, "Searched Device Name Len %d", adv_name_len);
635             esp_log_buffer_char(GATTC_TAG, adv_name, adv_name_len);
636             ESP_LOGI(GATTC_TAG, "\n");
637             if (adv_name != NULL) {
638                 if ( strncmp((char *)adv_name, device_name, adv_name_len) == 0) {
639                     memcpy(&(scan_rst), scan_result, sizeof(esp_ble_gap_cb_param_t));
640                     esp_ble_gap_stop_scanning();
641                 }
642             }
643             break;
644         case ESP_GAP_SEARCH_INQ_CMPL_EVT:
645             break;
646         default:
647             break;
648         }
649         break;
650     }
651     case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
652         if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
653             ESP_LOGE(GATTC_TAG, "Adv stop failed");
654         }else {
655             ESP_LOGI(GATTC_TAG, "Stop adv successfully");
656         }
657         break;
658     default:
659         break;
660     }
661 }
662
663 static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
664 {
665     ESP_LOGI(GATTC_TAG, "EVT %d, gattc if %d", event, gattc_if);
666
667     /* If event is register event, store the gattc_if for each profile */
668     if (event == ESP_GATTC_REG_EVT) {
669         if (param->reg.status == ESP_GATT_OK) {
670             gl_profile_tab[param->reg.app_id].gattc_if = gattc_if;
671         } else {
672             ESP_LOGI(GATTC_TAG, "Reg app failed, app_id %04x, status %d",param->reg.app_id,param->reg.status);
673             return;
674         }
675     }
676     /* If the gattc_if equal to profile A, call profile A cb handler,
677      * so here call each profile's callback */
678     do {
679         int idx;
680         for (idx = 0; idx < PROFILE_NUM; idx++) {
681             if (gattc_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
682                     gattc_if == gl_profile_tab[idx].gattc_if) {
683                 if (gl_profile_tab[idx].gattc_cb) {
684                     gl_profile_tab[idx].gattc_cb(event, gattc_if, param);
685                 }
686             }
687         }
688     } while (0);
689 }
690
691 static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
692 {
693     esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
694
695     switch (event) {
696     case ESP_GATTC_REG_EVT:
697         ESP_LOGE(GATTC_TAG, "REG EVT, set scan params");
698         esp_ble_gap_set_scan_params(&ble_scan_params);
699         break;
700     case ESP_GATTC_CONNECT_EVT:
701         spp_gattc_if = gattc_if;
702         is_connect = true;
703         spp_conn_id = p_data->connect.conn_id;
704         memcpy(gl_profile_tab[PROFILE_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t));
705         ESP_LOGI(GATTC_TAG, "ESP_GATTC_CONNECT_EVT: conn_id=%d, gatt_if = %d", spp_conn_id, gattc_if);
706         ESP_LOGI(GATTC_TAG, "REMOTE BDA:");
707         esp_log_buffer_hex(GATTC_TAG, gl_profile_tab[PROFILE_APP_ID].remote_bda, sizeof(esp_bd_addr_t));
708         esp_ble_gattc_search_service(gattc_if, spp_conn_id, NULL);
709         break;
710     case ESP_GATTC_DISCONNECT_EVT:
711         ESP_LOGI(GATTC_TAG, "disconnect");
712         free_gattc_srv_db();
713         esp_ble_gap_start_scanning(0xffff);
714         break;
715     case ESP_GATTC_SEARCH_RES_EVT:
716         if((p_data->search_res.srvc_id.id.uuid.len == ESP_UUID_LEN_16)&&(p_data->search_res.srvc_id.id.uuid.uuid.uuid16 == 0x1800)){
717             ESP_LOGI(GATTC_TAG, "uuid == 0x1800\n");
718             break;
719         }
720         if((p_data->search_res.srvc_id.id.uuid.len == ESP_UUID_LEN_16)&&(p_data->search_res.srvc_id.id.uuid.uuid.uuid16 == 0x1801)){
721             ESP_LOGI(GATTC_TAG, "uuid == 0x1801\n");
722             break;
723         }
724         store_srv_info(p_data);
725         break;
726     case ESP_GATTC_SEARCH_CMPL_EVT:
727         ESP_LOGI(GATTC_TAG, "SEARCH_CMPL: conn_id = %x, status %d", spp_conn_id, p_data->search_cmpl.status);
728         esp_ble_gattc_send_mtu_req(gattc_if,spp_conn_id);
729         break;
730     case ESP_GATTC_GET_CHAR_EVT:
731         if (p_data->get_char.status != ESP_GATT_OK) {
732             printf_char_and_descr(SPP_SRV_INDEX);
733             xQueueSend(cmd_reg_queue,&cmd,10/portTICK_PERIOD_MS);
734             cmd++;
735             break;
736         }
737         store_char_info(p_data);
738         break;
739     case ESP_GATTC_GET_DESCR_EVT:
740         if (p_data->get_descr.status != ESP_GATT_OK) {
741             char_descr_index_count = 0;
742             esp_ble_gattc_get_characteristic(spp_gattc_if, temp_srv_p->conn_id, &temp_srv_p->srvc_id, &temp_gattc_char_p1->char_id);
743             break;
744         }
745         store_desc_info(p_data);
746         break;
747     case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
748         ESP_LOGI(GATTC_TAG,"\nwr_descr_cmd = %d-- srvc_id = 0x%04x, char_id = 0x%04x, descr_id = 0x%04x \n",wr_descr_ccc_num , notify_char_p[wr_descr_ccc_num].srvc_id.id.uuid.uuid.uuid16, notify_char_p[wr_descr_ccc_num].char_id.uuid.uuid.uuid16,notify_char_descr_p[wr_descr_ccc_num]->descr_id.uuid.uuid.uuid16);
749
750         uint16_t notify_en = 1;
751         esp_ble_gattc_write_char_descr(
752                 spp_gattc_if,
753                 notify_char_p[wr_descr_ccc_num].conn_id,
754                 &(notify_char_p[wr_descr_ccc_num].srvc_id),
755                 &(notify_char_p[wr_descr_ccc_num].char_id),
756                 &notify_char_descr_p[wr_descr_ccc_num]->descr_id,
757                 sizeof(notify_en),
758                 (uint8_t *)&notify_en,
759                 ESP_GATT_WRITE_TYPE_RSP,
760                 ESP_GATT_AUTH_REQ_NONE);
761
762         wr_descr_ccc_num++;
763         break;
764     }
765     case ESP_GATTC_NOTIFY_EVT:
766         ESP_LOGI(GATTC_TAG,"ESP_GATTC_NOTIFY_EVT\n");
767         notify_event_handler(p_data);
768         break;
769     case ESP_GATTC_READ_CHAR_EVT:
770         ESP_LOGI(GATTC_TAG,"ESP_GATTC_READ_CHAR_EVT\n");
771         read_event_handler(p_data);
772         break;
773     case ESP_GATTC_WRITE_CHAR_EVT:
774         ESP_LOGI(GATTC_TAG,"ESP_GATTC_WRITE_CHAR_EVT:status=%d,srvc_uuid = 0x%04x, char_uuid = 0x%04x, descr_uuid=0x%04x \n",p_data->write.status , p_data->write.srvc_id.id.uuid.uuid.uuid16, p_data->write.char_id.uuid.uuid.uuid16, p_data->write.descr_id.uuid.uuid.uuid16);
775         if(param->write.status == ESP_GATT_OK){
776             if(param->write.char_id.uuid.uuid.uuid16 == 0xABF1){
777                 future_ready(*btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE), FUTURE_SUCCESS);
778             }
779         }
780         break;
781     case ESP_GATTC_PREP_WRITE_EVT:
782         break;
783     case ESP_GATTC_EXEC_EVT:
784         break;
785     case ESP_GATTC_WRITE_DESCR_EVT:
786         ESP_LOGI(GATTC_TAG,"ESP_GATTC_WRITE_DESCR_EVT: status =%d,srvc_uuid = 0x%04x, char_uuid = 0x%04x, descr_uuid=0x%04x \n",p_data->write.status,p_data->write.srvc_id.id.uuid.uuid.uuid16, p_data->write.char_id.uuid.uuid.uuid16, p_data->write.descr_id.uuid.uuid.uuid16);
787         xQueueSend(cmd_reg_queue,&cmd,10/portTICK_PERIOD_MS);
788         cmd++;
789         break;
790     case ESP_GATTC_CFG_MTU_EVT:
791         if(p_data->cfg_mtu.status != ESP_OK){
792             break;
793         }
794         ESP_LOGI(GATTC_TAG,"+MTU:%d\n", p_data->cfg_mtu.mtu);
795         spp_mtu_size = p_data->cfg_mtu.mtu;
796         print_srv_node();
797         get_char_and_descr();
798         break;
799     case ESP_GATTC_SRVC_CHG_EVT:
800         break;
801     default:
802         break;
803     }
804 }
805
806 void spp_client_reg_task(void* arg)
807 {
808     uint16_t cmd_id;
809     for(;;) {
810         vTaskDelay(100 / portTICK_PERIOD_MS);
811         if(xQueueReceive(cmd_reg_queue, &cmd_id, portMAX_DELAY)) {
812             if(0 == cmd_id){
813                 esp_ble_gattc_register_for_notify(spp_gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda ,&(notify_char_p[cmd_id].srvc_id), &(notify_char_p[cmd_id].char_id));
814                 ESP_LOGI(GATTC_TAG,"No.%d-- srvc_id = 0x%04x, char_id = 0x%04x \n",cmd_id, notify_char_p[cmd_id].srvc_id.id.uuid.uuid.uuid16, notify_char_p[cmd_id].char_id.uuid.uuid.uuid16);
815             }else if(1 == cmd_id){
816                 esp_ble_gattc_register_for_notify(spp_gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda ,&(notify_char_p[cmd_id].srvc_id), &(notify_char_p[cmd_id].char_id));
817                 ESP_LOGI(GATTC_TAG,"No.%d-- srvc_id = 0x%04x, char_id = 0x%04x \n",cmd_id, notify_char_p[cmd_id].srvc_id.id.uuid.uuid.uuid16, notify_char_p[cmd_id].char_id.uuid.uuid.uuid16);
818             }else if(2 == cmd_id){
819                 esp_ble_gattc_register_for_notify(spp_gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda ,&(notify_char_p[cmd_id].srvc_id), &(notify_char_p[cmd_id].char_id));
820                 ESP_LOGI(GATTC_TAG,"No.%d-- srvc_id = 0x%04x, char_id = 0x%04x \n",cmd_id, notify_char_p[cmd_id].srvc_id.id.uuid.uuid.uuid16, notify_char_p[cmd_id].char_id.uuid.uuid.uuid16);
821             }
822 #ifdef SUPPORT_HEARTBEAT
823             else if(3 == cmd_id){
824                 xQueueSend(cmd_heartbeat_queue,&cmd,10/portTICK_PERIOD_MS);
825             }
826 #endif
827         }
828     }
829 }
830
831 #ifdef SUPPORT_HEARTBEAT
832 void spp_heart_beat_task(void * arg)
833 {
834     uint16_t cmd_id;
835
836     for(;;) {
837         vTaskDelay(50 / portTICK_PERIOD_MS);
838         if(xQueueReceive(cmd_heartbeat_queue, &cmd_id, portMAX_DELAY)) {
839             while(1){
840                 if(is_connect == true){
841                     Characteristic_Wr(SPP_SRV_INDEX,SPP_HEARTBEAT_CHAR_INDEX,(char *)heartbeat_s,sizeof(heartbeat_s));
842                     vTaskDelay(5000 / portTICK_PERIOD_MS);
843                 }else{
844                     ESP_LOGI(GATTC_TAG,"disconnect\n");
845                     break;
846                 }
847             }
848         }
849     }
850 }
851 #endif
852
853 void spp_client_read_task(void * arg)
854 {
855     uint16_t cmd_id;
856     int32_t srv_index = SPP_SRV_INDEX, char_index = SPP_STATUS_CHAR_INDEX;
857
858     for(;;) {
859         vTaskDelay(50 / portTICK_PERIOD_MS);
860         if(xQueueReceive(cmd_read_queue, &cmd_id, portMAX_DELAY)) {
861             if(is_connect == true){
862                 Characteristic_Rd(srv_index,char_index);
863             }else{
864                 ESP_LOGI(GATTC_TAG,"disconnect\n");
865             }
866         }
867     }
868 }
869
870 void ble_client_appRegister(void)
871 {
872     esp_err_t status;
873
874     ESP_LOGI(GATTC_TAG, "register callback");
875
876     //register the scan callback function to the gap module
877     if ((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK) {
878         ESP_LOGE(GATTC_TAG, "gap register error, error code = %x", status);
879         return;
880     }
881     //register the callback function to the gattc module
882     if ((status = esp_ble_gattc_register_callback(esp_gattc_cb)) != ESP_OK) {
883         ESP_LOGE(GATTC_TAG, "gattc register error, error code = %x", status);
884         return;
885     }
886     esp_ble_gattc_app_register(PROFILE_APP_ID);
887
888     esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(200);
889     if (local_mtu_ret){
890         ESP_LOGE(GATTC_TAG, "set local  MTU failed, error code = %x", local_mtu_ret);
891     }
892
893     cmd_reg_queue = xQueueCreate(10, sizeof(uint32_t));
894     xTaskCreate(spp_client_reg_task, "spp_client_reg_task", 2048, NULL, 10, NULL);
895
896 #ifdef SUPPORT_HEARTBEAT
897     cmd_heartbeat_queue = xQueueCreate(10, sizeof(uint32_t));
898     xTaskCreate(spp_heart_beat_task, "spp_heart_beat_task", 2048, NULL, 10, NULL);
899 #endif
900
901     cmd_read_queue = xQueueCreate(10, sizeof(uint32_t));
902     xTaskCreate(spp_client_read_task, "spp_client_read_task", 2048, NULL, 10, NULL);
903 }
904
905 void uart_task(void *pvParameters)
906 {
907     uart_event_t event;
908     for (;;) {
909         //Waiting for UART event.
910         if (xQueueReceive(spp_uart_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
911             switch (event.type) {
912             //Event of UART receving data
913             case UART_DATA:
914                 if (event.size) {
915                     uint8_t * temp = NULL;
916                     temp = (uint8_t *)malloc(sizeof(uint8_t)*event.size);
917                     if(temp == NULL){
918                         ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n",__func__,__LINE__);
919                         break;
920                     }
921                     memset(temp,0x0,event.size);
922                     uart_read_bytes(UART_NUM_0,temp,event.size,portMAX_DELAY);
923                     Characteristic_Wr(SPP_SRV_INDEX,SPP_DATA_RECV_CHAR_INDEX,(char *)temp,event.size);
924                     free(temp);
925                 }
926                 break;
927             default:
928                 break;
929             }
930         }
931     }
932     vTaskDelete(NULL);
933 }
934
935 static void spp_uart_init(void)
936 {
937     uart_config_t uart_config = {
938         .baud_rate = 115200,
939         .data_bits = UART_DATA_8_BITS,
940         .parity = UART_PARITY_DISABLE,
941         .stop_bits = UART_STOP_BITS_1,
942         .flow_ctrl = UART_HW_FLOWCTRL_RTS,
943         .rx_flow_ctrl_thresh = 122,
944     };
945
946     //Set UART parameters
947     uart_param_config(UART_NUM_0, &uart_config);
948     //Set UART pins
949     uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
950     //Install UART driver, and get the queue.
951     uart_driver_install(UART_NUM_0, 4096, 8192, 10,&spp_uart_queue,0);
952     xTaskCreate(uart_task, "uTask", 2048, (void*)UART_NUM_0, 8, NULL);
953 }
954 #endif
955
956 void app_main()
957 {
958     esp_err_t ret;
959     esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
960
961     nvs_flash_init();
962     ret = esp_bt_controller_init(&bt_cfg);
963     if (ret) {
964         ESP_LOGE(GATTC_TAG, "%s enable controller failed\n", __func__);
965         return;
966     }
967
968     ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
969     if (ret) {
970         ESP_LOGE(GATTC_TAG, "%s enable controller failed\n", __func__);
971         return;
972     }
973
974     ESP_LOGI(GATTC_TAG, "%s init bluetooth\n", __func__);
975     ret = esp_bluedroid_init();
976     if (ret) {
977         ESP_LOGE(GATTC_TAG, "%s init bluetooth failed\n", __func__);
978         return;
979     }
980     ret = esp_bluedroid_enable();
981     if (ret) {
982         ESP_LOGE(GATTC_TAG, "%s enable bluetooth failed\n", __func__);
983         return;
984     }
985
986 #ifdef SUPPORT_NEW_GATTC_API
987     ble_client_appRegister();
988     spp_uart_init();
989 #endif
990 }
991