nimble_ota.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. /*
  2. * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.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 "host/ble_uuid.h"
  17. #include "ble_ota.h"
  18. #include "esp_nimble_hci.h"
  19. bool is_conn = false;
  20. #ifdef CONFIG_PRE_ENC_OTA
  21. #define SECTOR_END_ID 2
  22. #define ENC_HEADER 512
  23. esp_decrypt_handle_t decrypt_handle_cmp;
  24. #endif
  25. #define BUF_LENGTH 4096
  26. #define OTA_IDX_NB 4
  27. #define CMD_ACK_LENGTH 20
  28. #define character_declaration_uuid BLE_ATT_UUID_CHARACTERISTIC
  29. #define character_client_config_uuid BLE_ATT_UUID_CHARACTERISTIC
  30. #define GATT_SVR_SVC_ALERT_UUID 0x1811
  31. #define BLE_OTA_SERVICE_UUID 0x8018
  32. #define RECV_FW_UUID 0x8020
  33. #define OTA_BAR_UUID 0x8021
  34. #define COMMAND_UUID 0x8022
  35. #define CUSTOMER_UUID 0x8023
  36. #if CONFIG_EXAMPLE_EXTENDED_ADV
  37. static uint8_t ext_adv_pattern[] = {
  38. 0x02,
  39. 0x01,
  40. 0x06,
  41. 0x03,
  42. 0x03,
  43. 0xab,
  44. 0xcd,
  45. 0x03,
  46. 0x03,
  47. 0x18,
  48. 0x11,
  49. 0x0f,
  50. 0X09,
  51. 'n',
  52. 'i',
  53. 'm',
  54. 'b',
  55. 'l',
  56. 'e',
  57. '-',
  58. 'o',
  59. 't',
  60. 'a',
  61. '-',
  62. 'e',
  63. 'x',
  64. 't',
  65. };
  66. #endif
  67. static bool counter = false;
  68. static const char *TAG = "NimBLE_BLE_OTA";
  69. static bool start_ota = false;
  70. static uint32_t cur_sector = 0;
  71. static uint32_t cur_packet = 0;
  72. static uint8_t *fw_buf = NULL;
  73. static uint32_t fw_buf_offset = 0;
  74. static uint32_t ota_total_len = 0;
  75. static uint32_t ota_block_size = BUF_LENGTH;
  76. esp_ble_ota_callback_funs_t ota_cb_fun_t = {
  77. .recv_fw_cb = NULL};
  78. #ifndef CONFIG_OTA_WITH_PROTOCOMM
  79. esp_ble_ota_notification_check_t ota_notification = {
  80. .recv_fw_ntf_enable = false,
  81. .process_bar_ntf_enable = false,
  82. .command_ntf_enable = false,
  83. .customer_ntf_enable = false,
  84. };
  85. static uint8_t own_addr_type;
  86. static uint16_t connection_handle;
  87. static uint16_t attribute_handle;
  88. static uint16_t ota_handle_table[OTA_IDX_NB];
  89. static uint16_t receive_fw_val;
  90. static uint16_t ota_status_val;
  91. static uint16_t command_val;
  92. static uint16_t custom_val;
  93. static int
  94. esp_ble_ota_gap_event(struct ble_gap_event *event, void *arg);
  95. static esp_ble_ota_char_t
  96. find_ota_char_and_desr_by_handle(uint16_t handle);
  97. static int
  98. esp_ble_ota_notification_data(uint16_t conn_handle, uint16_t attr_handle, uint8_t cmd_ack[],
  99. esp_ble_ota_char_t ota_char);
  100. #endif
  101. /*----------------------------------------------------
  102. * Common api's
  103. *----------------------------------------------------*/
  104. void ble_store_config_init(void);
  105. static uint16_t
  106. crc16_ccitt(const unsigned char *buf, int len);
  107. static esp_err_t
  108. esp_ble_ota_recv_fw_handler(uint8_t *buf, uint32_t length);
  109. static void
  110. esp_ble_ota_write_chr(struct os_mbuf *om)
  111. {
  112. #ifndef CONFIG_OTA_WITH_PROTOCOMM
  113. esp_ble_ota_char_t ota_char = find_ota_char_and_desr_by_handle(attribute_handle);
  114. #endif
  115. #ifdef CONFIG_PRE_ENC_OTA
  116. esp_err_t err;
  117. pre_enc_decrypt_arg_t pargs = {};
  118. pargs.data_in_len = om->om_len - 3;
  119. if (SLIST_NEXT(om, om_next) != NULL)
  120. {
  121. struct os_mbuf *temp2 = SLIST_NEXT(om, om_next);
  122. pargs.data_in_len += temp2->om_len;
  123. }
  124. pargs.data_in = (const char *)malloc(pargs.data_in_len * sizeof(char *));
  125. err = os_mbuf_copydata(om, 3, pargs.data_in_len, pargs.data_in);
  126. if (om->om_data[2] == 0xff)
  127. {
  128. pargs.data_in_len -= SECTOR_END_ID;
  129. }
  130. err = esp_encrypted_img_decrypt_data(decrypt_handle_cmp, &pargs);
  131. if (err != ESP_OK && err != ESP_ERR_NOT_FINISHED)
  132. {
  133. return;
  134. }
  135. #endif
  136. uint8_t cmd_ack[CMD_ACK_LENGTH] = {0x03, 0x00, 0x00, 0x00, 0x00,
  137. 0x00, 0x00, 0x00, 0x00, 0x00,
  138. 0x00, 0x00, 0x00, 0x00, 0x00,
  139. 0x00, 0x00, 0x00, 0x00, 0x00};
  140. uint16_t crc16;
  141. if ((om->om_data[0] + (om->om_data[1] * 256)) != cur_sector)
  142. {
  143. // sector error
  144. if ((om->om_data[0] == 0xff) && (om->om_data[1] == 0xff))
  145. {
  146. // last sector
  147. ESP_LOGD(TAG, "Last sector");
  148. }
  149. else
  150. {
  151. // sector error
  152. ESP_LOGE(TAG, "%s - sector index error, cur: %" PRIu32 ", recv: %d", __func__,
  153. cur_sector, (om->om_data[0] + (om->om_data[1] * 256)));
  154. cmd_ack[0] = om->om_data[0];
  155. cmd_ack[1] = om->om_data[1];
  156. cmd_ack[2] = 0x02; // sector index error
  157. cmd_ack[3] = 0x00;
  158. cmd_ack[4] = cur_sector & 0xff;
  159. cmd_ack[5] = (cur_sector & 0xff00) >> 8;
  160. crc16 = crc16_ccitt(cmd_ack, 18);
  161. cmd_ack[18] = crc16 & 0xff;
  162. cmd_ack[19] = (crc16 & 0xff00) >> 8;
  163. #ifndef CONFIG_OTA_WITH_PROTOCOMM
  164. esp_ble_ota_notification_data(connection_handle, attribute_handle, cmd_ack, ota_char);
  165. #endif
  166. }
  167. }
  168. if (om->om_data[2] != cur_packet)
  169. { // packet seq error
  170. if (om->om_data[2] == 0xff)
  171. { // last packet
  172. ESP_LOGD(TAG, "last packet");
  173. goto write_ota_data;
  174. }
  175. else
  176. { // packet seq error
  177. ESP_LOGE(TAG, "%s - packet index error, cur: %" PRIu32 ", recv: %d", __func__,
  178. cur_packet, om->om_data[2]);
  179. }
  180. }
  181. write_ota_data:
  182. #ifdef CONFIG_PRE_ENC_OTA
  183. if (pargs.data_out_len > 0)
  184. {
  185. memcpy(fw_buf + fw_buf_offset, pargs.data_out, pargs.data_out_len);
  186. free(pargs.data_out);
  187. free(pargs.data_in);
  188. fw_buf_offset += pargs.data_out_len;
  189. }
  190. ESP_LOGD(TAG, "DEBUG: Sector:%" PRIu32 ", total length:%" PRIu32 ", length:%d", cur_sector,
  191. fw_buf_offset, pargs.data_out_len);
  192. #else
  193. memcpy(fw_buf + fw_buf_offset, om->om_data + 3, om->om_len - 3);
  194. fw_buf_offset += om->om_len - 3;
  195. if (SLIST_NEXT(om, om_next) != NULL)
  196. {
  197. struct os_mbuf *temp = SLIST_NEXT(om, om_next);
  198. memcpy(fw_buf + fw_buf_offset, temp->om_data, temp->om_len);
  199. fw_buf_offset += temp->om_len;
  200. temp = NULL;
  201. }
  202. ESP_LOGD(TAG, "DEBUG: Sector:%" PRIu32 ", total length:%" PRIu32 ", length:%d", cur_sector,
  203. fw_buf_offset, om->om_len - 3);
  204. #endif
  205. if (om->om_data[2] == 0xff)
  206. {
  207. cur_packet = 0;
  208. cur_sector++;
  209. ESP_LOGD(TAG, "DEBUG: recv %" PRIu32 " sector", cur_sector);
  210. goto sector_end;
  211. }
  212. else
  213. {
  214. ESP_LOGD(TAG, "DEBUG: wait next packet");
  215. cur_packet++;
  216. }
  217. return;
  218. sector_end:
  219. if (fw_buf_offset < ota_block_size)
  220. {
  221. esp_ble_ota_recv_fw_handler(fw_buf, fw_buf_offset);
  222. }
  223. else
  224. {
  225. esp_ble_ota_recv_fw_handler(fw_buf, ota_block_size);
  226. }
  227. fw_buf_offset = 0;
  228. memset(fw_buf, 0x0, ota_block_size);
  229. cmd_ack[0] = om->om_data[0];
  230. cmd_ack[1] = om->om_data[1];
  231. cmd_ack[2] = 0x00; // success
  232. cmd_ack[3] = 0x00;
  233. crc16 = crc16_ccitt(cmd_ack, 18);
  234. cmd_ack[18] = crc16 & 0xff;
  235. cmd_ack[19] = (crc16 & 0xff00) >> 8;
  236. counter = true;
  237. #ifndef CONFIG_OTA_WITH_PROTOCOMM
  238. esp_ble_ota_notification_data(connection_handle, attribute_handle, cmd_ack, ota_char);
  239. #endif
  240. }
  241. static uint16_t crc16_ccitt(const unsigned char *buf, int len)
  242. {
  243. uint16_t crc16 = 0;
  244. int32_t i;
  245. while (len--)
  246. {
  247. crc16 ^= *buf++ << 8;
  248. for (i = 0; i < 8; i++)
  249. {
  250. if (crc16 & 0x8000)
  251. {
  252. crc16 = (crc16 << 1) ^ 0x1021;
  253. }
  254. else
  255. {
  256. crc16 = crc16 << 1;
  257. }
  258. }
  259. }
  260. return crc16;
  261. }
  262. void esp_ble_ota_set_fw_length(uint32_t length)
  263. {
  264. ota_total_len = length;
  265. }
  266. unsigned int esp_ble_ota_get_fw_length(void)
  267. {
  268. return ota_total_len;
  269. }
  270. static esp_err_t
  271. esp_ble_ota_recv_fw_handler(uint8_t *buf, uint32_t length)
  272. {
  273. if (ota_cb_fun_t.recv_fw_cb)
  274. {
  275. ota_cb_fun_t.recv_fw_cb(buf, length);
  276. }
  277. return ESP_OK;
  278. }
  279. #ifndef CONFIG_PRE_ENC_OTA
  280. esp_err_t esp_ble_ota_recv_fw_data_callback(esp_ble_ota_recv_fw_cb_t callback)
  281. {
  282. ota_cb_fun_t.recv_fw_cb = callback;
  283. return ESP_OK;
  284. }
  285. #else
  286. esp_err_t esp_ble_ota_recv_fw_data_callback(esp_ble_ota_recv_fw_cb_t callback,
  287. esp_decrypt_handle_t esp_decrypt_handle)
  288. {
  289. decrypt_handle_cmp = esp_decrypt_handle;
  290. ota_cb_fun_t.recv_fw_cb = callback;
  291. return ESP_OK;
  292. }
  293. #endif
  294. /*----------------------------------------------------
  295. * Protocomm specific api's
  296. *----------------------------------------------------*/
  297. #ifdef CONFIG_OTA_WITH_PROTOCOMM
  298. void esp_ble_ota_set_sizes(size_t file_size, size_t block_size)
  299. {
  300. ota_total_len = file_size;
  301. ota_block_size = block_size;
  302. }
  303. void esp_ble_ota_finish(void)
  304. {
  305. ESP_LOGI(TAG, "Received OTA end command");
  306. start_ota = false;
  307. ota_total_len = 0;
  308. ota_block_size = 0;
  309. free(fw_buf);
  310. fw_buf = NULL;
  311. }
  312. void esp_ble_ota_write(uint8_t *file, size_t length)
  313. {
  314. struct os_mbuf *om = ble_hs_mbuf_from_flat(file, length);
  315. esp_ble_ota_write_chr(om);
  316. }
  317. #else
  318. /*----------------------------------------------------
  319. * OTA without protocomm api's
  320. *----------------------------------------------------*/
  321. static void
  322. ble_ota_start_write_chr(struct os_mbuf *om)
  323. {
  324. uint8_t cmd_ack[CMD_ACK_LENGTH] = {0x03, 0x00, 0x00, 0x00, 0x00,
  325. 0x00, 0x00, 0x00, 0x00, 0x00,
  326. 0x00, 0x00, 0x00, 0x00, 0x00,
  327. 0x00, 0x00, 0x00, 0x00, 0x00};
  328. uint16_t crc16;
  329. esp_ble_ota_char_t ota_char = find_ota_char_and_desr_by_handle(attribute_handle);
  330. if ((om->om_data[0] == 0x01) && (om->om_data[1] == 0x00))
  331. {
  332. start_ota = true;
  333. ota_total_len = (om->om_data[2]) + (om->om_data[3] * 256) +
  334. (om->om_data[4] * 256 * 256) + (om->om_data[5] * 256 * 256 * 256);
  335. #ifdef CONFIG_PRE_ENC_OTA
  336. ota_total_len -= ENC_HEADER;
  337. #endif
  338. ESP_LOGI(TAG, "recv ota start cmd, fw_length = %" PRIu32 "", ota_total_len);
  339. #if 0
  340. fw_buf = (uint8_t *)malloc(ota_block_size * sizeof(uint8_t));
  341. #else
  342. fw_buf = (uint8_t *)heap_caps_malloc(ota_block_size * sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
  343. #endif
  344. if (fw_buf == NULL)
  345. {
  346. ESP_LOGE(TAG, "%s - malloc fail", __func__);
  347. }
  348. else
  349. {
  350. memset(fw_buf, 0x0, ota_block_size);
  351. }
  352. cmd_ack[2] = 0x01;
  353. cmd_ack[3] = 0x00;
  354. crc16 = crc16_ccitt(cmd_ack, 18);
  355. cmd_ack[18] = crc16 & 0xff;
  356. cmd_ack[19] = (crc16 & 0xff00) >> 8;
  357. esp_ble_ota_notification_data(connection_handle, attribute_handle, cmd_ack, ota_char);
  358. }
  359. else if ((om->om_data[0] == 0x02) && (om->om_data[1] == 0x00))
  360. {
  361. printf("\nCMD_CHAR -> 0 : %d, 1 : %d", om->om_data[0],
  362. om->om_data[1]);
  363. #ifdef CONFIG_PRE_ENC_OTA
  364. if (esp_encrypted_img_decrypt_end(decrypt_handle_cmp) != ESP_OK)
  365. {
  366. ESP_LOGI(TAG, "Decryption end failed");
  367. }
  368. #endif
  369. start_ota = false;
  370. ota_total_len = 0;
  371. ESP_LOGD(TAG, "recv ota stop cmd");
  372. cmd_ack[2] = 0x02;
  373. cmd_ack[3] = 0x00;
  374. crc16 = crc16_ccitt(cmd_ack, 18);
  375. cmd_ack[18] = crc16 & 0xff;
  376. cmd_ack[19] = (crc16 & 0xff00) >> 8;
  377. esp_ble_ota_notification_data(connection_handle, attribute_handle, cmd_ack, ota_char);
  378. free(fw_buf);
  379. fw_buf = NULL;
  380. }
  381. }
  382. static void
  383. gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
  384. {
  385. char buf[BLE_UUID_STR_LEN];
  386. switch (ctxt->op)
  387. {
  388. case BLE_GATT_REGISTER_OP_SVC:
  389. ESP_LOGD(TAG, "registered service %s with handle=%d\n",
  390. ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
  391. ctxt->svc.handle);
  392. break;
  393. case BLE_GATT_REGISTER_OP_CHR:
  394. ESP_LOGD(TAG, "registering characteristic %s with "
  395. "def_handle=%d val_handle=%d\n",
  396. ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
  397. ctxt->chr.def_handle,
  398. ctxt->chr.val_handle);
  399. break;
  400. case BLE_GATT_REGISTER_OP_DSC:
  401. ESP_LOGD(TAG, "registering descriptor %s with handle=%d\n",
  402. ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
  403. ctxt->dsc.handle);
  404. break;
  405. default:
  406. assert(0);
  407. break;
  408. }
  409. }
  410. static int
  411. ble_ota_gatt_handler(uint16_t conn_handle, uint16_t attr_handle,
  412. struct ble_gatt_access_ctxt *ctxt,
  413. void *arg)
  414. {
  415. esp_ble_ota_char_t ota_char;
  416. attribute_handle = attr_handle;
  417. switch (ctxt->op)
  418. {
  419. case BLE_GATT_ACCESS_OP_READ_CHR:
  420. ota_char = find_ota_char_and_desr_by_handle(attr_handle);
  421. ESP_LOGI(TAG, "client read, ota_char: %d", ota_char);
  422. break;
  423. case BLE_GATT_ACCESS_OP_WRITE_CHR:
  424. ota_char = find_ota_char_and_desr_by_handle(attr_handle);
  425. ESP_LOGD(TAG, "client write; len = %d", ctxt->om->om_len);
  426. if (ota_char == RECV_FW_CHAR)
  427. {
  428. if (start_ota)
  429. {
  430. esp_ble_ota_write_chr(ctxt->om);
  431. }
  432. else
  433. {
  434. ESP_LOGE(TAG, "%s - don't receive the start cmd", __func__);
  435. }
  436. }
  437. else if (ota_char == CMD_CHAR)
  438. {
  439. ble_ota_start_write_chr(ctxt->om);
  440. }
  441. break;
  442. default:
  443. return BLE_ATT_ERR_UNLIKELY;
  444. }
  445. return 0;
  446. }
  447. static const struct ble_gatt_svc_def ota_gatt_db[] = {
  448. {
  449. /* OTA Service Declaration */
  450. .type = BLE_GATT_SVC_TYPE_PRIMARY,
  451. .uuid = BLE_UUID16_DECLARE(BLE_OTA_SERVICE_UUID),
  452. .characteristics = (struct ble_gatt_chr_def[]){
  453. {
  454. /* Receive Firmware Characteristic */
  455. .uuid = BLE_UUID16_DECLARE(RECV_FW_UUID),
  456. .access_cb = ble_ota_gatt_handler,
  457. .val_handle = &receive_fw_val,
  458. .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE,
  459. },
  460. {
  461. /* OTA Characteristic */
  462. .uuid = BLE_UUID16_DECLARE(OTA_BAR_UUID),
  463. .access_cb = ble_ota_gatt_handler,
  464. .val_handle = &ota_status_val,
  465. .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ,
  466. },
  467. {
  468. /* Command Characteristic */
  469. .uuid = BLE_UUID16_DECLARE(COMMAND_UUID),
  470. .access_cb = ble_ota_gatt_handler,
  471. .val_handle = &command_val,
  472. .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE,
  473. },
  474. {
  475. /* Customer characteristic */
  476. .uuid = BLE_UUID16_DECLARE(CUSTOMER_UUID),
  477. .access_cb = ble_ota_gatt_handler,
  478. .val_handle = &custom_val,
  479. .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_WRITE,
  480. },
  481. {
  482. 0, /* No more characteristics in this service */
  483. }},
  484. },
  485. {
  486. 0, /* No more services */
  487. },
  488. };
  489. static esp_ble_ota_char_t
  490. find_ota_char_and_desr_by_handle(uint16_t handle)
  491. {
  492. esp_ble_ota_char_t ret = INVALID_CHAR;
  493. for (int i = 0; i < OTA_IDX_NB; i++)
  494. {
  495. if (handle == ota_handle_table[i])
  496. {
  497. switch (i)
  498. {
  499. case RECV_FW_CHAR_VAL_IDX:
  500. ret = RECV_FW_CHAR;
  501. break;
  502. case OTA_STATUS_CHAR_VAL_IDX:
  503. ret = OTA_STATUS_CHAR;
  504. break;
  505. case CMD_CHAR_VAL_IDX:
  506. ret = CMD_CHAR;
  507. break;
  508. case CUS_CHAR_VAL_IDX:
  509. ret = CUS_CHAR;
  510. break;
  511. default:
  512. ret = INVALID_CHAR;
  513. break;
  514. }
  515. }
  516. }
  517. return ret;
  518. }
  519. static int
  520. esp_ble_ota_notification_data(uint16_t conn_handle, uint16_t attr_handle, uint8_t cmd_ack[],
  521. esp_ble_ota_char_t ota_char)
  522. {
  523. struct os_mbuf *txom;
  524. bool notify_enable = false;
  525. int rc;
  526. txom = ble_hs_mbuf_from_flat(cmd_ack, CMD_ACK_LENGTH);
  527. switch (ota_char)
  528. {
  529. case RECV_FW_CHAR:
  530. if (ota_notification.recv_fw_ntf_enable)
  531. {
  532. notify_enable = true;
  533. }
  534. break;
  535. case OTA_STATUS_CHAR:
  536. if (ota_notification.process_bar_ntf_enable)
  537. {
  538. notify_enable = true;
  539. }
  540. break;
  541. case CMD_CHAR:
  542. if (ota_notification.command_ntf_enable)
  543. {
  544. notify_enable = true;
  545. }
  546. break;
  547. case CUS_CHAR:
  548. if (ota_notification.customer_ntf_enable)
  549. {
  550. notify_enable = true;
  551. }
  552. break;
  553. case INVALID_CHAR:
  554. break;
  555. }
  556. if (notify_enable)
  557. {
  558. rc = ble_gattc_notify_custom(conn_handle, attr_handle, txom);
  559. if (rc == 0)
  560. {
  561. ESP_LOGD(TAG, "Notification sent, attr_handle = %d", attr_handle);
  562. }
  563. else
  564. {
  565. ESP_LOGE(TAG, "Error in sending notification, rc = %d", rc);
  566. }
  567. return rc;
  568. }
  569. /* If notifications are disabled return ESP_FAIL */
  570. ESP_LOGI(TAG, "Notify is disabled");
  571. return ESP_FAIL;
  572. }
  573. static void
  574. esp_ble_ota_fill_handle_table(void)
  575. {
  576. ota_handle_table[RECV_FW_CHAR] = receive_fw_val;
  577. ota_handle_table[OTA_STATUS_CHAR] = ota_status_val;
  578. ota_handle_table[CMD_CHAR] = command_val;
  579. ota_handle_table[CUS_CHAR] = custom_val;
  580. }
  581. static void
  582. print_addr(const void *addr)
  583. {
  584. const uint8_t *u8p;
  585. u8p = addr;
  586. ESP_LOGI(TAG, "%02x:%02x:%02x:%02x:%02x:%02x",
  587. u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
  588. }
  589. /**
  590. * Logs information about a connection to the console.
  591. */
  592. static void
  593. esp_ble_ota_print_conn_desc(struct ble_gap_conn_desc *desc)
  594. {
  595. ESP_LOGI(TAG, "handle=%d our_ota_addr_type=%d our_ota_addr=",
  596. desc->conn_handle, desc->our_ota_addr.type);
  597. print_addr(desc->our_ota_addr.val);
  598. ESP_LOGI(TAG, " our_id_addr_type=%d our_id_addr=",
  599. desc->our_id_addr.type);
  600. print_addr(desc->our_id_addr.val);
  601. ESP_LOGI(TAG, " peer_ota_addr_type=%d peer_ota_addr=",
  602. desc->peer_ota_addr.type);
  603. print_addr(desc->peer_ota_addr.val);
  604. ESP_LOGI(TAG, " peer_id_addr_type=%d peer_id_addr=",
  605. desc->peer_id_addr.type);
  606. print_addr(desc->peer_id_addr.val);
  607. ESP_LOGI(TAG, " conn_itvl=%d conn_latency=%d supervision_timeout=%d "
  608. "encrypted=%d authenticated=%d bonded=%d\n",
  609. desc->conn_itvl, desc->conn_latency,
  610. desc->supervision_timeout,
  611. desc->sec_state.encrypted,
  612. desc->sec_state.authenticated,
  613. desc->sec_state.bonded);
  614. }
  615. /**
  616. * Enables advertising with the following parameters:
  617. * o General discoverable mode.
  618. * o Undirected connectable mode.
  619. */
  620. #if CONFIG_EXAMPLE_EXTENDED_ADV
  621. static void
  622. esp_ble_ota_ext_advertise(void)
  623. {
  624. struct ble_gap_ext_adv_params params;
  625. struct os_mbuf *data;
  626. uint8_t instance = 0;
  627. int rc;
  628. /* First check if any instance is already active */
  629. if (ble_gap_adv_active())
  630. return;
  631. /* use defaults for non-set params */
  632. memset(&params, 0, sizeof(params));
  633. /* enable connectable advertising */
  634. params.connectable = 1;
  635. /* advertise using random addr */
  636. params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
  637. params.primary_phy = BLE_HCI_LE_PHY_1M;
  638. params.secondary_phy = BLE_HCI_LE_PHY_2M;
  639. // params.tx_power = 127;
  640. params.sid = 1;
  641. params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
  642. params.itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
  643. /* configure instance 0 */
  644. rc = ble_gap_ext_adv_configure(instance, &params, NULL,
  645. esp_ble_ota_gap_event, NULL);
  646. assert(rc == 0);
  647. /* in this case only scan response is allowed */
  648. /* get mbuf for scan rsp data */
  649. data = os_msys_get_pkthdr(sizeof(ext_adv_pattern), 0);
  650. assert(data);
  651. /* fill mbuf with scan rsp data */
  652. rc = os_mbuf_append(data, ext_adv_pattern, sizeof(ext_adv_pattern));
  653. assert(rc == 0);
  654. rc = ble_gap_ext_adv_set_data(instance, data);
  655. assert(rc == 0);
  656. /* start advertising */
  657. rc = ble_gap_ext_adv_start(instance, 0, 0);
  658. assert(rc == 0);
  659. }
  660. #else
  661. static void
  662. esp_ble_ota_advertise(void)
  663. {
  664. struct ble_gap_adv_params adv_params;
  665. struct ble_hs_adv_fields fields;
  666. const char *name;
  667. int rc;
  668. /**
  669. * Set the advertisement data included in our advertisements:
  670. * o Flags (indicates advertisement type and other general info).
  671. * o Advertising tx power.
  672. * o Device name.
  673. * o 16-bit service UUIDs (alert notifications).
  674. */
  675. memset(&fields, 0, sizeof fields);
  676. /* Advertise two flags:
  677. * o Discoverability in forthcoming advertisement (general)
  678. * o BLE-only (BR/EDR unsupported).
  679. */
  680. fields.flags = BLE_HS_ADV_F_DISC_GEN |
  681. BLE_HS_ADV_F_BREDR_UNSUP;
  682. /* Indicate that the TX power level field should be included; have the
  683. * stack fill this value automatically. This is done by assigning the
  684. * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
  685. */
  686. fields.tx_pwr_lvl_is_present = 1;
  687. fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
  688. name = ble_svc_gap_device_name();
  689. fields.name = (uint8_t *)name;
  690. fields.name_len = strlen(name);
  691. fields.name_is_complete = 1;
  692. fields.uuids16 = (ble_uuid16_t[]){
  693. BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)};
  694. fields.num_uuids16 = 1;
  695. fields.uuids16_is_complete = 1;
  696. rc = ble_gap_adv_set_fields(&fields);
  697. if (rc != 0)
  698. {
  699. ESP_LOGE(TAG, "error setting advertisement data; rc=%d\n", rc);
  700. return;
  701. }
  702. /* Begin advertising. */
  703. memset(&adv_params, 0, sizeof adv_params);
  704. adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
  705. adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
  706. rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
  707. &adv_params, esp_ble_ota_gap_event, NULL);
  708. if (rc != 0)
  709. {
  710. ESP_LOGE(TAG, "error enabling advertisement; rc=%d\n", rc);
  711. return;
  712. }
  713. }
  714. #endif
  715. /**
  716. * The nimble host executes this callback when a GAP event occurs. The
  717. * application associates a GAP event callback with each connection that forms.
  718. * esp_ble_ota uses the same callback for all connections.
  719. *
  720. * @param event The type of event being signalled.
  721. * @param ctxt Various information pertaining to the event.
  722. * @param arg Application-specified argument; unused by
  723. * esp_ble_ota.
  724. *
  725. * @return 0 if the application successfully handled the
  726. * event; nonzero on failure. The semantics
  727. * of the return code is specific to the
  728. * particular GAP event being signalled.
  729. */
  730. static int
  731. esp_ble_ota_gap_event(struct ble_gap_event *event, void *arg)
  732. {
  733. struct ble_gap_conn_desc desc;
  734. int rc;
  735. esp_ble_ota_char_t ota_char;
  736. switch (event->type)
  737. {
  738. case BLE_GAP_EVENT_CONNECT:
  739. /* A new connection was established or a connection attempt failed. */
  740. ESP_LOGI(TAG, "connection %s; status=%d ",
  741. event->connect.status == 0 ? "established" : "failed",
  742. event->connect.status);
  743. if (event->connect.status == 0)
  744. {
  745. is_conn = true;
  746. rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
  747. assert(rc == 0);
  748. esp_ble_ota_print_conn_desc(&desc);
  749. connection_handle = event->connect.conn_handle;
  750. }
  751. else
  752. {
  753. /* Connection failed; resume advertising. */
  754. #if CONFIG_EXAMPLE_EXTENDED_ADV
  755. esp_ble_ota_ext_advertise();
  756. #else
  757. esp_ble_ota_advertise();
  758. #endif
  759. }
  760. esp_ble_ota_fill_handle_table();
  761. return 0;
  762. case BLE_GAP_EVENT_DISCONNECT:
  763. is_conn = false;
  764. ESP_LOGI(TAG, "disconnect; reason=%d ", event->disconnect.reason);
  765. esp_ble_ota_print_conn_desc(&event->disconnect.conn);
  766. /* Connection terminated; resume advertising. */
  767. #if CONFIG_EXAMPLE_EXTENDED_ADV
  768. esp_ble_ota_ext_advertise();
  769. #else
  770. esp_ble_ota_advertise();
  771. #endif
  772. return 0;
  773. case BLE_GAP_EVENT_CONN_UPDATE:
  774. /* The central has updated the connection parameters. */
  775. ESP_LOGI(TAG, "connection updated; status=%d ",
  776. event->conn_update.status);
  777. rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
  778. assert(rc == 0);
  779. esp_ble_ota_print_conn_desc(&desc);
  780. return 0;
  781. case BLE_GAP_EVENT_ADV_COMPLETE:
  782. ESP_LOGI(TAG, "advertise complete; reason=%d",
  783. event->adv_complete.reason);
  784. #ifdef CONFIG_EXAMPLE_EXTENDED_ADV
  785. esp_ble_ota_ext_advertise();
  786. #else
  787. esp_ble_ota_advertise();
  788. #endif
  789. return 0;
  790. case BLE_GAP_EVENT_ENC_CHANGE:
  791. /* Encryption has been enabled or disabled for this connection. */
  792. ESP_LOGI(TAG, "encryption change event; status=%d ",
  793. event->enc_change.status);
  794. rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
  795. assert(rc == 0);
  796. esp_ble_ota_print_conn_desc(&desc);
  797. return 0;
  798. case BLE_GAP_EVENT_SUBSCRIBE:
  799. ota_char = find_ota_char_and_desr_by_handle(event->subscribe.attr_handle);
  800. ESP_LOGI(TAG, "client subscribe ble_gap_event, ota_char: %d", ota_char);
  801. ESP_LOGI(TAG, "subscribe event; conn_handle=%d attr_handle=%d "
  802. "reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
  803. event->subscribe.conn_handle,
  804. event->subscribe.attr_handle,
  805. event->subscribe.reason,
  806. event->subscribe.prev_notify,
  807. event->subscribe.cur_notify,
  808. event->subscribe.prev_indicate,
  809. event->subscribe.cur_indicate);
  810. switch (ota_char)
  811. {
  812. case RECV_FW_CHAR:
  813. ota_notification.recv_fw_ntf_enable = true;
  814. break;
  815. case OTA_STATUS_CHAR:
  816. ota_notification.process_bar_ntf_enable = true;
  817. break;
  818. case CMD_CHAR:
  819. ota_notification.command_ntf_enable = true;
  820. break;
  821. case CUS_CHAR:
  822. ota_notification.customer_ntf_enable = true;
  823. break;
  824. case INVALID_CHAR:
  825. break;
  826. }
  827. return 0;
  828. case BLE_GAP_EVENT_MTU:
  829. ESP_LOGI(TAG, "mtu update event; conn_handle=%d cid=%d mtu=%d\n",
  830. event->mtu.conn_handle,
  831. event->mtu.channel_id,
  832. event->mtu.value);
  833. return 0;
  834. case BLE_GAP_EVENT_REPEAT_PAIRING:
  835. /* We already have a bond with the peer, but it is attempting to
  836. * establish a new secure link. This app sacrifices security for
  837. * convenience: just throw away the old bond and accept the new link.
  838. */
  839. /* Delete the old bond. */
  840. rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
  841. assert(rc == 0);
  842. ble_store_util_delete_peer(&desc.peer_id_addr);
  843. /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
  844. * continue with the pairing operation.
  845. */
  846. return BLE_GAP_REPEAT_PAIRING_RETRY;
  847. case BLE_GAP_EVENT_PASSKEY_ACTION:
  848. ESP_LOGI(TAG, "PASSKEY_ACTION_EVENT started \n");
  849. return 0;
  850. }
  851. return 0;
  852. }
  853. int ble_ota_gatt_svr_init(void)
  854. {
  855. int rc;
  856. ble_svc_gap_init();
  857. ble_svc_gatt_init();
  858. rc = ble_gatts_count_cfg(ota_gatt_db);
  859. if (rc != 0)
  860. {
  861. return rc;
  862. }
  863. rc = ble_gatts_add_svcs(ota_gatt_db);
  864. if (rc != 0)
  865. {
  866. return rc;
  867. }
  868. return 0;
  869. }
  870. static void
  871. esp_ble_ota_on_reset(int reason)
  872. {
  873. ESP_LOGE(TAG, "Resetting state; reason=%d\n", reason);
  874. }
  875. static void
  876. esp_ble_ota_on_sync(void)
  877. {
  878. int rc;
  879. rc = ble_hs_util_ensure_addr(0);
  880. assert(rc == 0);
  881. /* Figure out address to use while advertising (no privacy for now) */
  882. rc = ble_hs_id_infer_auto(0, &own_addr_type);
  883. if (rc != 0)
  884. {
  885. ESP_LOGE(TAG, "error determining address type; rc=%d\n", rc);
  886. return;
  887. }
  888. /* Printing ADDR */
  889. uint8_t addr_val[6] = {0};
  890. rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
  891. ESP_LOGI(TAG, "Device Address: ");
  892. print_addr(addr_val);
  893. /* Begin advertising. */
  894. #if CONFIG_EXAMPLE_EXTENDED_ADV
  895. esp_ble_ota_ext_advertise();
  896. #else
  897. esp_ble_ota_advertise();
  898. #endif
  899. }
  900. void esp_ble_ota_host_task(void *param)
  901. {
  902. ESP_LOGI(TAG, "BLE Host Task Started");
  903. /* This function will return only when nimble_port_stop() is executed */
  904. nimble_port_run();
  905. nimble_port_freertos_deinit();
  906. }
  907. esp_err_t
  908. esp_ble_ota_host_init(void)
  909. {
  910. int rc;
  911. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  912. if (esp_nimble_init() != 0)
  913. {
  914. ESP_LOGE(TAG, "nimble host init failed\n");
  915. return ESP_FAIL;
  916. }
  917. #else
  918. ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
  919. nimble_port_init();
  920. #endif
  921. /* Initialize the NimBLE host configuration. */
  922. ble_hs_cfg.reset_cb = esp_ble_ota_on_reset;
  923. ble_hs_cfg.sync_cb = esp_ble_ota_on_sync;
  924. ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
  925. ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
  926. ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
  927. ble_hs_cfg.sm_bonding = 1;
  928. ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ENC;
  929. ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC;
  930. rc = ble_ota_gatt_svr_init();
  931. assert(rc == 0);
  932. #include "esp_mac.h"
  933. char *device_name = (char *)malloc(sizeof("YC-OTA#") + 4);
  934. memcpy(device_name, "YC-OTA#", sizeof("YC-OTA#"));
  935. uint8_t macAddr[7];
  936. char mac_5[4];
  937. char mac_6[4];
  938. esp_read_mac((uint8_t *)macAddr, ESP_MAC_WIFI_STA);
  939. ESP_LOG_BUFFER_HEX(TAG, &macAddr, 6);
  940. itoa(macAddr[4], mac_5, 16);
  941. itoa(macAddr[5], mac_6, 16);
  942. strcat(device_name, mac_5);
  943. strcat(device_name, mac_6);
  944. ESP_LOGW(TAG, "ble name[%s]", device_name);
  945. /* Set the default device name. */
  946. rc = ble_svc_gap_device_name_set(device_name);
  947. free(device_name);
  948. assert(rc == 0);
  949. /* XXX Need to have template for store */
  950. ble_store_config_init();
  951. nimble_port_freertos_init(esp_ble_ota_host_task);
  952. return 0;
  953. }
  954. #endif