main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include "esp_log.h"
  7. #include "nvs_flash.h"
  8. /* BLE */
  9. #include "esp_nimble_hci.h"
  10. #include "nimble/nimble_port.h"
  11. #include "nimble/nimble_port_freertos.h"
  12. #include "host/ble_hs.h"
  13. #include "host/util/util.h"
  14. #include "console/console.h"
  15. #include "services/gap/ble_svc_gap.h"
  16. #include "ble_spp_server.h"
  17. #include "driver/uart.h"
  18. static const char *tag = "NimBLE_SPP_BLE_PRPH";
  19. static int ble_spp_server_gap_event(struct ble_gap_event *event, void *arg);
  20. static uint8_t own_addr_type;
  21. int gatt_svr_register(void);
  22. QueueHandle_t spp_common_uart_queue = NULL;
  23. static bool is_connect = false;
  24. uint16_t connection_handle;
  25. static uint16_t ble_svc_gatt_read_val_handle,ble_spp_svc_gatt_read_val_handle;
  26. /* 16 Bit Alert Notification Service UUID */
  27. #define BLE_SVC_ANS_UUID16 0x1811
  28. /* 16 Bit Alert Notification Service Characteristic UUIDs */
  29. #define BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT 0x2a47
  30. /* 16 Bit SPP Service UUID */
  31. #define BLE_SVC_SPP_UUID16 0xABF0
  32. /* 16 Bit SPP Service Characteristic UUID */
  33. #define BLE_SVC_SPP_CHR_UUID16 0xABF1
  34. void ble_store_config_init(void);
  35. /**
  36. * Logs information about a connection to the console.
  37. */
  38. static void
  39. ble_spp_server_print_conn_desc(struct ble_gap_conn_desc *desc)
  40. {
  41. MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=",
  42. desc->conn_handle, desc->our_ota_addr.type);
  43. print_addr(desc->our_ota_addr.val);
  44. MODLOG_DFLT(INFO, " our_id_addr_type=%d our_id_addr=",
  45. desc->our_id_addr.type);
  46. print_addr(desc->our_id_addr.val);
  47. MODLOG_DFLT(INFO, " peer_ota_addr_type=%d peer_ota_addr=",
  48. desc->peer_ota_addr.type);
  49. print_addr(desc->peer_ota_addr.val);
  50. MODLOG_DFLT(INFO, " peer_id_addr_type=%d peer_id_addr=",
  51. desc->peer_id_addr.type);
  52. print_addr(desc->peer_id_addr.val);
  53. MODLOG_DFLT(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d "
  54. "encrypted=%d authenticated=%d bonded=%d\n",
  55. desc->conn_itvl, desc->conn_latency,
  56. desc->supervision_timeout,
  57. desc->sec_state.encrypted,
  58. desc->sec_state.authenticated,
  59. desc->sec_state.bonded);
  60. }
  61. /**
  62. * Enables advertising with the following parameters:
  63. * o General discoverable mode.
  64. * o Undirected connectable mode.
  65. */
  66. static void
  67. ble_spp_server_advertise(void)
  68. {
  69. struct ble_gap_adv_params adv_params;
  70. struct ble_hs_adv_fields fields;
  71. const char *name;
  72. int rc;
  73. /**
  74. * Set the advertisement data included in our advertisements:
  75. * o Flags (indicates advertisement type and other general info).
  76. * o Advertising tx power.
  77. * o Device name.
  78. * o 16-bit service UUIDs (alert notifications).
  79. */
  80. memset(&fields, 0, sizeof fields);
  81. /* Advertise two flags:
  82. * o Discoverability in forthcoming advertisement (general)
  83. * o BLE-only (BR/EDR unsupported).
  84. */
  85. fields.flags = BLE_HS_ADV_F_DISC_GEN |
  86. BLE_HS_ADV_F_BREDR_UNSUP;
  87. /* Indicate that the TX power level field should be included; have the
  88. * stack fill this value automatically. This is done by assigning the
  89. * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
  90. */
  91. fields.tx_pwr_lvl_is_present = 1;
  92. fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
  93. name = ble_svc_gap_device_name();
  94. fields.name = (uint8_t *)name;
  95. fields.name_len = strlen(name);
  96. fields.name_is_complete = 1;
  97. fields.uuids16 = (ble_uuid16_t[]) {
  98. BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
  99. };
  100. fields.num_uuids16 = 1;
  101. fields.uuids16_is_complete = 1;
  102. rc = ble_gap_adv_set_fields(&fields);
  103. if (rc != 0) {
  104. MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
  105. return;
  106. }
  107. /* Begin advertising. */
  108. memset(&adv_params, 0, sizeof adv_params);
  109. adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
  110. adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
  111. rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
  112. &adv_params, ble_spp_server_gap_event, NULL);
  113. if (rc != 0) {
  114. MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
  115. return;
  116. }
  117. }
  118. /**
  119. * The nimble host executes this callback when a GAP event occurs. The
  120. * application associates a GAP event callback with each connection that forms.
  121. * ble_spp_server uses the same callback for all connections.
  122. *
  123. * @param event The type of event being signalled.
  124. * @param ctxt Various information pertaining to the event.
  125. * @param arg Application-specified argument; unused by
  126. * ble_spp_server.
  127. *
  128. * @return 0 if the application successfully handled the
  129. * event; nonzero on failure. The semantics
  130. * of the return code is specific to the
  131. * particular GAP event being signalled.
  132. */
  133. static int
  134. ble_spp_server_gap_event(struct ble_gap_event *event, void *arg)
  135. {
  136. struct ble_gap_conn_desc desc;
  137. int rc;
  138. switch (event->type) {
  139. case BLE_GAP_EVENT_CONNECT:
  140. /* A new connection was established or a connection attempt failed. */
  141. MODLOG_DFLT(INFO, "connection %s; status=%d ",
  142. event->connect.status == 0 ? "established" : "failed",
  143. event->connect.status);
  144. if (event->connect.status == 0) {
  145. rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
  146. assert(rc == 0);
  147. ble_spp_server_print_conn_desc(&desc);
  148. is_connect=true;
  149. connection_handle = event->connect.conn_handle;
  150. }
  151. MODLOG_DFLT(INFO, "\n");
  152. if (event->connect.status != 0) {
  153. /* Connection failed; resume advertising. */
  154. ble_spp_server_advertise();
  155. }
  156. return 0;
  157. case BLE_GAP_EVENT_DISCONNECT:
  158. MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
  159. ble_spp_server_print_conn_desc(&event->disconnect.conn);
  160. MODLOG_DFLT(INFO, "\n");
  161. /* Connection terminated; resume advertising. */
  162. ble_spp_server_advertise();
  163. return 0;
  164. case BLE_GAP_EVENT_CONN_UPDATE:
  165. /* The central has updated the connection parameters. */
  166. MODLOG_DFLT(INFO, "connection updated; status=%d ",
  167. event->conn_update.status);
  168. rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
  169. assert(rc == 0);
  170. ble_spp_server_print_conn_desc(&desc);
  171. MODLOG_DFLT(INFO, "\n");
  172. return 0;
  173. case BLE_GAP_EVENT_ADV_COMPLETE:
  174. MODLOG_DFLT(INFO, "advertise complete; reason=%d",
  175. event->adv_complete.reason);
  176. ble_spp_server_advertise();
  177. return 0;
  178. case BLE_GAP_EVENT_MTU:
  179. MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d cid=%d mtu=%d\n",
  180. event->mtu.conn_handle,
  181. event->mtu.channel_id,
  182. event->mtu.value);
  183. return 0;
  184. default:
  185. return 0;
  186. }
  187. }
  188. static void
  189. ble_spp_server_on_reset(int reason)
  190. {
  191. MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
  192. }
  193. static void
  194. ble_spp_server_on_sync(void)
  195. {
  196. int rc;
  197. rc = ble_hs_util_ensure_addr(0);
  198. assert(rc == 0);
  199. /* Figure out address to use while advertising (no privacy for now) */
  200. rc = ble_hs_id_infer_auto(0, &own_addr_type);
  201. if (rc != 0) {
  202. MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
  203. return;
  204. }
  205. /* Printing ADDR */
  206. uint8_t addr_val[6] = {0};
  207. rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
  208. MODLOG_DFLT(INFO, "Device Address: ");
  209. print_addr(addr_val);
  210. MODLOG_DFLT(INFO, "\n");
  211. /* Begin advertising. */
  212. ble_spp_server_advertise();
  213. }
  214. void ble_spp_server_host_task(void *param)
  215. {
  216. ESP_LOGI(tag, "BLE Host Task Started");
  217. /* This function will return only when nimble_port_stop() is executed */
  218. nimble_port_run();
  219. nimble_port_freertos_deinit();
  220. }
  221. /* Callback function for custom service */
  222. static int ble_svc_gatt_handler(uint16_t conn_handle, uint16_t attr_handle,struct ble_gatt_access_ctxt *ctxt, void *arg)
  223. {
  224. switch(ctxt->op){
  225. case BLE_GATT_ACCESS_OP_READ_CHR:
  226. ESP_LOGI(tag, "Callback for read");
  227. break;
  228. case BLE_GATT_ACCESS_OP_WRITE_CHR:
  229. ESP_LOGI(tag,"Data received in write event,conn_handle = %x,attr_handle = %x",conn_handle,attr_handle);
  230. break;
  231. default:
  232. ESP_LOGI(tag, "\nDefault Callback");
  233. break;
  234. }
  235. return 0;
  236. }
  237. /* Define new custom service */
  238. static const struct ble_gatt_svc_def new_ble_svc_gatt_defs[] = {
  239. {
  240. /*** Service: GATT */
  241. .type = BLE_GATT_SVC_TYPE_PRIMARY,
  242. .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_UUID16),
  243. .characteristics = (struct ble_gatt_chr_def[]) { {
  244. /* Support new alert category */
  245. .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT),
  246. .access_cb = ble_svc_gatt_handler,
  247. .val_handle = &ble_svc_gatt_read_val_handle,
  248. .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE,
  249. },
  250. {
  251. 0, /* No more characteristics */
  252. }
  253. },
  254. },
  255. {
  256. /*** Service: SPP */
  257. .type = BLE_GATT_SVC_TYPE_PRIMARY,
  258. .uuid = BLE_UUID16_DECLARE(BLE_SVC_SPP_UUID16),
  259. .characteristics = (struct ble_gatt_chr_def[]) { {
  260. /* Support SPP service */
  261. .uuid = BLE_UUID16_DECLARE(BLE_SVC_SPP_CHR_UUID16),
  262. .access_cb = ble_svc_gatt_handler,
  263. .val_handle = &ble_spp_svc_gatt_read_val_handle,
  264. .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE,
  265. },
  266. {
  267. 0, /* No more characteristics */
  268. }
  269. },
  270. },
  271. {
  272. 0, /* No more services. */
  273. },
  274. };
  275. int gatt_svr_register(void)
  276. {
  277. int rc=0;
  278. rc = ble_gatts_count_cfg(new_ble_svc_gatt_defs);
  279. if (rc != 0) {
  280. return rc;
  281. }
  282. rc = ble_gatts_add_svcs(new_ble_svc_gatt_defs);
  283. if (rc != 0) {
  284. return rc;
  285. }
  286. return 0;
  287. }
  288. void ble_server_uart_task(void *pvParameters){
  289. ESP_LOGI(tag,"BLE server UART_task started\n");
  290. uart_event_t event;
  291. int rc=0;
  292. for (;;) {
  293. //Waiting for UART event.
  294. if (xQueueReceive(spp_common_uart_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
  295. switch (event.type) {
  296. //Event of UART receving data
  297. case UART_DATA:
  298. if (event.size && (is_connect == true)) {
  299. static uint8_t ntf[1];
  300. ntf[0] = 90;
  301. struct os_mbuf *txom;
  302. txom = ble_hs_mbuf_from_flat(ntf, sizeof(ntf));
  303. rc = ble_gattc_notify_custom(connection_handle,ble_spp_svc_gatt_read_val_handle,txom);
  304. if( rc == 0){
  305. ESP_LOGI(tag,"Notification sent successfully");
  306. }
  307. else {
  308. ESP_LOGI(tag,"Error in sending notification");
  309. }
  310. }
  311. break;
  312. default:
  313. break;
  314. }
  315. }
  316. }
  317. vTaskDelete(NULL);
  318. }
  319. static void ble_spp_uart_init(void)
  320. {
  321. uart_config_t uart_config = {
  322. .baud_rate = 115200,
  323. .data_bits = UART_DATA_8_BITS,
  324. .parity = UART_PARITY_DISABLE,
  325. .stop_bits = UART_STOP_BITS_1,
  326. .flow_ctrl = UART_HW_FLOWCTRL_RTS,
  327. .rx_flow_ctrl_thresh = 122,
  328. .source_clk = UART_SCLK_APB,
  329. };
  330. //Install UART driver, and get the queue.
  331. uart_driver_install(UART_NUM_0, 4096, 8192, 10,&spp_common_uart_queue,0);
  332. //Set UART parameters
  333. uart_param_config(UART_NUM_0, &uart_config);
  334. //Set UART pins
  335. uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  336. xTaskCreate(ble_server_uart_task, "uTask", 2048, (void*)UART_NUM_0, 8, NULL);
  337. }
  338. void
  339. app_main(void)
  340. {
  341. int rc;
  342. /* Initialize NVS — it is used to store PHY calibration data */
  343. esp_err_t ret = nvs_flash_init();
  344. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  345. ESP_ERROR_CHECK(nvs_flash_erase());
  346. ret = nvs_flash_init();
  347. }
  348. ESP_ERROR_CHECK(ret);
  349. ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
  350. nimble_port_init();
  351. /* Initialize uart driver and start uart task */
  352. ble_spp_uart_init();
  353. /* Initialize the NimBLE host configuration. */
  354. ble_hs_cfg.reset_cb = ble_spp_server_on_reset;
  355. ble_hs_cfg.sync_cb = ble_spp_server_on_sync;
  356. ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
  357. ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
  358. ble_hs_cfg.sm_io_cap = CONFIG_EXAMPLE_IO_TYPE;
  359. #ifdef CONFIG_EXAMPLE_BONDING
  360. ble_hs_cfg.sm_bonding = 1;
  361. #endif
  362. #ifdef CONFIG_EXAMPLE_MITM
  363. ble_hs_cfg.sm_mitm = 1;
  364. #endif
  365. #ifdef CONFIG_EXAMPLE_USE_SC
  366. ble_hs_cfg.sm_sc = 1;
  367. #else
  368. ble_hs_cfg.sm_sc = 0;
  369. #endif
  370. #ifdef CONFIG_EXAMPLE_BONDING
  371. ble_hs_cfg.sm_our_key_dist = 1;
  372. ble_hs_cfg.sm_their_key_dist = 1;
  373. #endif
  374. rc = new_gatt_svr_init();
  375. assert(rc == 0);
  376. /* Register custom service */
  377. rc = gatt_svr_register();
  378. assert(rc == 0);
  379. /* Set the default device name. */
  380. rc = ble_svc_gap_device_name_set("nimble-ble-spp-svr");
  381. assert(rc == 0);
  382. /* XXX Need to have template for store */
  383. ble_store_config_init();
  384. nimble_port_freertos_init(ble_spp_server_host_task);
  385. }