main.c 15 KB

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