bt_app_source.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include "bt_app_core.h"
  6. #include "esp_log.h"
  7. #include "esp_bt.h"
  8. #include "esp_bt_device.h"
  9. #include "esp_bt_main.h"
  10. #include "esp_gap_bt_api.h"
  11. #include "esp_a2dp_api.h"
  12. #include "esp_avrc_api.h"
  13. #include "esp_console.h"
  14. #include "esp_pthread.h"
  15. #include "esp_system.h"
  16. #include "esp_wifi.h"
  17. #include "freertos/timers.h"
  18. #include "argtable3/argtable3.h"
  19. #include "platform_config.h"
  20. #include "trace.h"
  21. #include "messaging.h"
  22. #include "cJSON.h"
  23. static const char * TAG = "bt_app_source";
  24. static const char * BT_RC_CT_TAG="RCCT";
  25. extern int32_t output_bt_data(uint8_t *data, int32_t len);
  26. extern void output_bt_tick(void);
  27. extern char* output_state_str(void);
  28. extern bool output_stopped(void);
  29. static void bt_app_av_state_connecting(uint16_t event, void *param);
  30. static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param);
  31. /* event for handler "bt_av_hdl_stack_up */
  32. enum {
  33. BT_APP_EVT_STACK_UP = 0,
  34. };
  35. char * APP_AV_STATE_DESC[] = {
  36. "APP_AV_STATE_IDLE",
  37. "APP_AV_STATE_DISCOVERING",
  38. "APP_AV_STATE_DISCOVERED",
  39. "APP_AV_STATE_UNCONNECTED",
  40. "APP_AV_STATE_CONNECTING",
  41. "APP_AV_STATE_CONNECTED",
  42. "APP_AV_STATE_DISCONNECTING"
  43. };
  44. static char * ESP_AVRC_CT_DESC[]={
  45. "ESP_AVRC_CT_CONNECTION_STATE_EVT",
  46. "ESP_AVRC_CT_PASSTHROUGH_RSP_EVT",
  47. "ESP_AVRC_CT_METADATA_RSP_EVT",
  48. "ESP_AVRC_CT_PLAY_STATUS_RSP_EVT",
  49. "ESP_AVRC_CT_CHANGE_NOTIFY_EVT",
  50. "ESP_AVRC_CT_REMOTE_FEATURES_EVT",
  51. "ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT",
  52. "ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT"
  53. };
  54. #define BT_APP_HEART_BEAT_EVT (0xff00)
  55. // AVRCP used transaction label
  56. #define APP_RC_CT_TL_GET_CAPS (0)
  57. #define APP_RC_CT_TL_RN_VOLUME_CHANGE (1)
  58. #define PEERS_LIST_MAINTAIN_RESET -129
  59. #define PEERS_LIST_MAINTAIN_PURGE -129
  60. /// handler for bluetooth stack enabled events
  61. static void bt_av_hdl_stack_evt(uint16_t event, void *p_param);
  62. /// callback function for A2DP source
  63. static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
  64. /// callback function for AVRCP controller
  65. static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param);
  66. /// avrc CT event handler
  67. static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param);
  68. /// callback function for A2DP source audio data stream
  69. static void a2d_app_heart_beat(void *arg);
  70. /// A2DP application state machine
  71. static void bt_app_av_sm_hdlr(uint16_t event, void *param);
  72. /* A2DP application state machine handler for each state */
  73. static void bt_app_av_state_unconnected(uint16_t event, void *param);
  74. static void bt_app_av_state_connecting(uint16_t event, void *param);
  75. static void bt_app_av_state_connected(uint16_t event, void *param);
  76. static void bt_app_av_state_disconnecting(uint16_t event, void *param);
  77. static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param);
  78. static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *param);
  79. static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t *param);
  80. static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_t *param);
  81. static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter);
  82. static esp_bd_addr_t s_peer_bda = {0};
  83. static uint8_t s_peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
  84. int bt_app_source_a2d_state = APP_AV_STATE_IDLE;
  85. int bt_app_source_media_state = APP_AV_MEDIA_STATE_IDLE;
  86. static uint32_t s_pkt_cnt = 0;
  87. static TimerHandle_t s_tmr=NULL;
  88. static int prev_duration=10000;
  89. static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
  90. static int s_connecting_intv = 0;
  91. cJSON * peers_list=NULL;
  92. static struct {
  93. // int control_delay;
  94. // int connect_timeout_delay;
  95. char * sink_name;
  96. } squeezelite_conf;
  97. static cJSON * peers_list_get_entry(const char * s_peer_bdname){
  98. cJSON * element=NULL;
  99. cJSON_ArrayForEach(element,peers_list){
  100. cJSON * name = cJSON_GetObjectItem(element,"name");
  101. if(name && !strcmp(cJSON_GetStringValue(name),s_peer_bdname)){
  102. ESP_LOGV(TAG,"Entry name %s found in current scan list", s_peer_bdname);
  103. return element;
  104. }
  105. }
  106. ESP_LOGV(TAG,"Entry name %s NOT found in current scan list", s_peer_bdname);
  107. return NULL;
  108. }
  109. static void peers_list_reset(){
  110. cJSON * element=NULL;
  111. cJSON_ArrayForEach(element,peers_list){
  112. cJSON * rssi = cJSON_GetObjectItem(element,"rssi");
  113. if(rssi){
  114. rssi->valuedouble = -129;
  115. rssi->valueint = -129;
  116. }
  117. }
  118. }
  119. static void peers_list_purge(){
  120. cJSON * element=NULL;
  121. cJSON_ArrayForEach(element,peers_list){
  122. cJSON * rssi_val = cJSON_GetObjectItem(element,"rssi");
  123. if(rssi_val && rssi_val->valuedouble == -129){
  124. cJSON * name = cJSON_GetObjectItem(element,"name");
  125. ESP_LOGV(TAG,"Purging %s", cJSON_GetStringValue(name)?cJSON_GetStringValue(name):"Unknown");
  126. cJSON_DetachItemViaPointer(peers_list,element);
  127. cJSON_Delete(element);
  128. }
  129. }
  130. }
  131. static cJSON * peers_list_create_entry(const char * s_peer_bdname, int32_t rssi){
  132. cJSON * entry = cJSON_CreateObject();
  133. cJSON_AddStringToObject(entry,"name",s_peer_bdname);
  134. cJSON_AddNumberToObject(entry,"rssi",rssi);
  135. return entry;
  136. }
  137. static void peers_list_update_add(const char * s_peer_bdname, int32_t rssi){
  138. cJSON * element= peers_list_get_entry(s_peer_bdname);
  139. if(element){
  140. cJSON * rssi_val = cJSON_GetObjectItem(element,"rssi");
  141. if(rssi_val && rssi_val->valuedouble != rssi){
  142. ESP_LOGV(TAG,"Updating BT Sink Device: %s rssi to %i", s_peer_bdname,rssi);
  143. rssi_val->valuedouble = rssi;
  144. rssi_val->valueint = rssi;
  145. }
  146. }
  147. else {
  148. ESP_LOGI(TAG,"Found BT Sink Device: %s rssi is %i", s_peer_bdname,rssi);
  149. element = peers_list_create_entry( s_peer_bdname, rssi);
  150. cJSON_AddItemToArray(peers_list,element);
  151. }
  152. }
  153. static void peers_list_maintain(const char * s_peer_bdname, int32_t rssi){
  154. if(!peers_list){
  155. ESP_LOGV(TAG,"Initializing BT peers list");
  156. peers_list=cJSON_CreateArray();
  157. }
  158. if(rssi==PEERS_LIST_MAINTAIN_RESET){
  159. ESP_LOGV(TAG,"Resetting BT peers list");
  160. peers_list_reset();
  161. }
  162. else if(rssi==PEERS_LIST_MAINTAIN_PURGE){
  163. ESP_LOGV(TAG,"Purging BT peers list");
  164. peers_list_purge();
  165. }
  166. if(s_peer_bdname) {
  167. ESP_LOGV(TAG,"Adding/Updating peer %s rssi %i", s_peer_bdname,rssi);
  168. peers_list_update_add(s_peer_bdname, rssi);
  169. }
  170. char * list_json = cJSON_Print(peers_list);
  171. if(list_json){
  172. messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_BT, list_json);
  173. ESP_LOGV(TAG,"%s", list_json);
  174. free(list_json);
  175. }
  176. }
  177. int bt_app_source_get_a2d_state(){
  178. ESP_LOGD(TAG,"a2dp status: %u = %s", bt_app_source_a2d_state, APP_AV_STATE_DESC[bt_app_source_a2d_state]);
  179. return bt_app_source_a2d_state;
  180. }
  181. int bt_app_source_get_media_state(){
  182. ESP_LOGD(TAG,"media state : %u ", bt_app_source_media_state);
  183. return bt_app_source_media_state;
  184. }
  185. void set_app_source_state(int new_state){
  186. if(bt_app_source_a2d_state!=new_state){
  187. ESP_LOGD(TAG, "Updating state from %s to %s", APP_AV_STATE_DESC[bt_app_source_a2d_state], APP_AV_STATE_DESC[new_state]);
  188. bt_app_source_a2d_state=new_state;
  189. }
  190. }
  191. void set_a2dp_media_state(int new_state){
  192. if(bt_app_source_media_state!=new_state){
  193. bt_app_source_media_state=new_state;
  194. }
  195. }
  196. void hal_bluetooth_init(const char * options)
  197. {
  198. struct {
  199. struct arg_str *sink_name;
  200. // struct arg_int *control_delay;
  201. // struct arg_int *connect_timeout_delay;
  202. struct arg_end *end;
  203. } squeezelite_args;
  204. ESP_LOGD(TAG,"Initializing Bluetooth HAL");
  205. squeezelite_args.sink_name = arg_str0("n", "name", "<sink name>", "the name of the bluetooth to connect to");
  206. // squeezelite_args.control_delay = arg_int0("d", "delay", "<control delay>", "the delay between each pass at the A2DP control loop");
  207. // squeezelite_args.connect_timeout_delay = arg_int0("t","timeout", "<timeout>", "the timeout duration for connecting to the A2DP sink");
  208. squeezelite_args.end = arg_end(2);
  209. ESP_LOGD(TAG,"Copying parameters");
  210. char * opts = strdup(options);
  211. char **argv = malloc(sizeof(char**)*15);
  212. size_t argv_size=15;
  213. // change parms so ' appear as " for parsing the options
  214. for (char* p = opts; (p = strchr(p, '\'')); ++p) *p = '"';
  215. ESP_LOGD(TAG,"Splitting arg line: %s", opts);
  216. argv_size = esp_console_split_argv(opts, argv, argv_size);
  217. ESP_LOGD(TAG,"Parsing parameters");
  218. int nerrors = arg_parse(argv_size , argv, (void **) &squeezelite_args);
  219. if (nerrors != 0) {
  220. ESP_LOGD(TAG,"Parsing Errors");
  221. arg_print_errors(stdout, squeezelite_args.end, "BT");
  222. arg_print_glossary_gnu(stdout, (void **) &squeezelite_args);
  223. free(opts);
  224. free(argv);
  225. return;
  226. }
  227. if(squeezelite_args.sink_name->count == 0)
  228. {
  229. squeezelite_conf.sink_name = config_alloc_get_default(NVS_TYPE_STR, "a2dp_sink_name", NULL, 0);
  230. if(!squeezelite_conf.sink_name || strlen(squeezelite_conf.sink_name)==0 ){
  231. ESP_LOGW(TAG,"Unable to retrieve the a2dp sink name from nvs.");
  232. }
  233. } else {
  234. squeezelite_conf.sink_name=strdup(squeezelite_args.sink_name->sval[0]);
  235. // sync with NVS
  236. esp_err_t err=ESP_OK;
  237. if((err= config_set_value(NVS_TYPE_STR, "a2dp_sink_name", squeezelite_args.sink_name->sval[0]))!=ESP_OK){
  238. ESP_LOGE(TAG,"Error setting Bluetooth audio device name %s. %s",squeezelite_args.sink_name->sval[0], esp_err_to_name(err));
  239. }
  240. else {
  241. ESP_LOGI(TAG,"Bluetooth audio device name changed to %s",squeezelite_args.sink_name->sval[0]);
  242. }
  243. }
  244. // if(squeezelite_args.connect_timeout_delay->count == 0)
  245. // {
  246. // ESP_LOGD(TAG,"Using default connect timeout");
  247. // char * p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_ctmt", NULL, 0);
  248. // if(p){
  249. // squeezelite_conf.connect_timeout_delay=atoi(p);
  250. // free(p);
  251. // }
  252. // else {
  253. // squeezelite_conf.connect_timeout_delay=CONFIG_A2DP_CONNECT_TIMEOUT_MS;
  254. // }
  255. // } else {
  256. // squeezelite_conf.connect_timeout_delay=squeezelite_args.connect_timeout_delay->ival[0];
  257. // }
  258. // if(squeezelite_args.control_delay->count == 0)
  259. // {
  260. // ESP_LOGD(TAG,"Using default control delay");
  261. // char * p = config_alloc_get_default(NVS_TYPE_STR, "a2dp_ctrld", NULL, 0);
  262. // if(p){
  263. // squeezelite_conf.control_delay=atoi(p);
  264. // free(p);
  265. // }
  266. // else {
  267. // squeezelite_conf.control_delay=CONFIG_A2DP_CONNECT_TIMEOUT_MS;
  268. // }
  269. // } else {
  270. // squeezelite_conf.control_delay=squeezelite_args.control_delay->ival[0];
  271. // }
  272. ESP_LOGD(TAG,"Freeing options");
  273. free(argv);
  274. free(opts);
  275. /*
  276. * Bluetooth audio source init Start
  277. */
  278. //running_test = false;
  279. ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE));
  280. esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
  281. if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
  282. ESP_LOGE(TAG,"%s initialize controller failed\n", __func__);
  283. return;
  284. }
  285. if (esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT) != ESP_OK) {
  286. ESP_LOGE(TAG,"%s enable controller failed\n", __func__);
  287. return;
  288. }
  289. if (esp_bluedroid_init() != ESP_OK) {
  290. ESP_LOGE(TAG,"%s initialize bluedroid failed\n", __func__);
  291. return;
  292. }
  293. if (esp_bluedroid_enable() != ESP_OK) {
  294. ESP_LOGE(TAG,"%s enable bluedroid failed\n", __func__);
  295. return;
  296. }
  297. /* create application task */
  298. bt_app_task_start_up();
  299. /* Bluetooth device name, connection mode and profile set up */
  300. bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL);
  301. #if (CONFIG_BT_SSP_ENABLED == true)
  302. /* Set default parameters for Secure Simple Pairing */
  303. esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE;
  304. esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO;
  305. esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t));
  306. #endif
  307. /*
  308. * Set default parameters for Legacy Pairing
  309. * Use variable pin, input pin code when pairing
  310. */
  311. esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE;
  312. esp_bt_pin_code_t pin_code;
  313. esp_bt_gap_set_pin(pin_type, 0, pin_code);
  314. }
  315. void hal_bluetooth_stop(void) {
  316. /* this still does not work, can't figure out how to stop properly this BT stack */
  317. bt_app_task_shut_down();
  318. ESP_LOGI(TAG, "bt_app_task shutdown successfully");
  319. if (esp_bluedroid_disable() != ESP_OK) return;
  320. ESP_LOGI(TAG, "esp_bluedroid_disable called successfully");
  321. if (esp_bluedroid_deinit() != ESP_OK) return;
  322. ESP_LOGI(TAG, "esp_bluedroid_deinit called successfully");
  323. if (esp_bt_controller_disable() != ESP_OK) return;
  324. ESP_LOGI(TAG, "esp_bt_controller_disable called successfully");
  325. if (esp_bt_controller_deinit() != ESP_OK) return;
  326. ESP_LOGI(TAG, "bt stopped successfully");
  327. }
  328. static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
  329. {
  330. bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL);
  331. }
  332. static void handle_bt_gap_pin_req(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param){
  333. char * pin_str = config_alloc_get_default(NVS_TYPE_STR, "a2dp_spin", "0000", 0);
  334. int pinlen=pin_str?strlen(pin_str):0;
  335. if (pin_str && ((!param->pin_req.min_16_digit && pinlen==4) || (param->pin_req.min_16_digit && pinlen==16))) {
  336. ESP_LOGI(TAG,"Input pin code %s: ",pin_str);
  337. esp_bt_pin_code_t pin_code;
  338. for (size_t i = 0; i < pinlen; i++)
  339. {
  340. pin_code[i] = pin_str[i];
  341. }
  342. esp_bt_gap_pin_reply(param->pin_req.bda, true, pinlen, pin_code);
  343. }
  344. else {
  345. if(pinlen>0){
  346. ESP_LOGW(TAG,"Pin length: %u does not match the length expected by the device: %u", pinlen, ((param->pin_req.min_16_digit)?16:4));
  347. }
  348. else {
  349. ESP_LOGW(TAG, "No security Pin provided. Trying with default pins.");
  350. }
  351. if (param->pin_req.min_16_digit) {
  352. ESP_LOGI(TAG,"Input pin code: 0000 0000 0000 0000");
  353. esp_bt_pin_code_t pin_code = {0};
  354. esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code);
  355. } else {
  356. ESP_LOGI(TAG,"Input pin code: 1234");
  357. esp_bt_pin_code_t pin_code;
  358. pin_code[0] = '1';
  359. pin_code[1] = '2';
  360. pin_code[2] = '3';
  361. pin_code[3] = '4';
  362. esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code);
  363. }
  364. }
  365. FREE_AND_NULL(pin_str);
  366. }
  367. static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
  368. {
  369. switch (event) {
  370. case ESP_BT_GAP_DISC_RES_EVT: {
  371. filter_inquiry_scan_result(param);
  372. break;
  373. }
  374. case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: {
  375. if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED)
  376. {
  377. peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_PURGE);
  378. if (bt_app_source_a2d_state == APP_AV_STATE_DISCOVERED)
  379. {
  380. ESP_LOGI(TAG,"Discovery completed. Ready to start connecting to %s. ",s_peer_bdname);
  381. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  382. }
  383. else
  384. {
  385. // not discovered, continue to discover
  386. ESP_LOGI(TAG,"Device discovery failed, continue to discover...");
  387. esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
  388. }
  389. }
  390. else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
  391. ESP_LOGI(TAG,"Discovery started.");
  392. peers_list_maintain(NULL, PEERS_LIST_MAINTAIN_RESET);
  393. }
  394. else
  395. {
  396. ESP_LOGD(TAG,"This shouldn't happen. Discovery has only 2 states (for now).");
  397. }
  398. break;
  399. }
  400. case ESP_BT_GAP_RMT_SRVCS_EVT:
  401. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_BT_GAP_RMT_SRVCS_EVT));
  402. break;
  403. case ESP_BT_GAP_RMT_SRVC_REC_EVT:
  404. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_BT_GAP_RMT_SRVC_REC_EVT));
  405. break;
  406. case ESP_BT_GAP_AUTH_CMPL_EVT: {
  407. if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
  408. ESP_LOGI(TAG,"authentication success: %s", param->auth_cmpl.device_name);
  409. //esp_log_buffer_hex(param->auth_cmpl.bda, ESP_BD_ADDR_LEN);
  410. } else {
  411. ESP_LOGE(TAG,"authentication failed, status:%d", param->auth_cmpl.stat);
  412. }
  413. break;
  414. }
  415. case ESP_BT_GAP_PIN_REQ_EVT:
  416. handle_bt_gap_pin_req(event, param);
  417. break;
  418. #if (CONFIG_BT_SSP_ENABLED == true)
  419. case ESP_BT_GAP_CFM_REQ_EVT:
  420. ESP_LOGI(TAG,"ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
  421. esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
  422. break;
  423. case ESP_BT_GAP_KEY_NOTIF_EVT:
  424. ESP_LOGI(TAG,"ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey);
  425. break;
  426. ESP_LOGI(TAG,"ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
  427. break;
  428. #endif
  429. default: {
  430. ESP_LOGI(TAG,"event: %d", event);
  431. break;
  432. }
  433. }
  434. return;
  435. }
  436. int heart_beat_delay[] = {
  437. 1000,
  438. 1000,
  439. 1000,
  440. 1000,
  441. 10000,
  442. 500,
  443. 1000
  444. };
  445. static void a2d_app_heart_beat(void *arg)
  446. {
  447. bt_app_work_dispatch(bt_app_av_sm_hdlr, BT_APP_HEART_BEAT_EVT, NULL, 0, NULL);
  448. int tmrduration=heart_beat_delay[bt_app_source_a2d_state];
  449. if(prev_duration!=tmrduration){
  450. xTimerChangePeriod(s_tmr,tmrduration, portMAX_DELAY);
  451. ESP_LOGD(TAG,"New heartbeat is %u",tmrduration);
  452. prev_duration=tmrduration;
  453. }
  454. else {
  455. ESP_LOGD(TAG,"Starting Heart beat timer for %ums",tmrduration);
  456. }
  457. xTimerStart(s_tmr, portMAX_DELAY);
  458. }
  459. static const char * conn_state_str(esp_a2d_connection_state_t state){
  460. char * statestr = "Unknown";
  461. switch (state)
  462. {
  463. case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
  464. statestr=STR(ESP_A2D_CONNECTION_STATE_DISCONNECTED);
  465. break;
  466. case ESP_A2D_CONNECTION_STATE_CONNECTING:
  467. statestr=STR(ESP_A2D_CONNECTION_STATE_CONNECTING);
  468. break;
  469. case ESP_A2D_CONNECTION_STATE_CONNECTED:
  470. statestr=STR(ESP_A2D_CONNECTION_STATE_CONNECTED);
  471. break;
  472. case ESP_A2D_CONNECTION_STATE_DISCONNECTING:
  473. statestr=STR(ESP_A2D_CONNECTION_STATE_DISCONNECTING);
  474. break;
  475. default:
  476. break;
  477. }
  478. return statestr;
  479. }
  480. static void unexpected_connection_state(int from, esp_a2d_connection_state_t to)
  481. {
  482. ESP_LOGW(TAG,"Unexpected connection state change. App State: %s (%u) Connection State %s (%u)", APP_AV_STATE_DESC[from], from,conn_state_str(to), to);
  483. }
  484. static void handle_connect_state_unconnected(uint16_t event, esp_a2d_cb_param_t *param){
  485. ESP_LOGV(TAG, "A2DP Event while unconnected ");
  486. switch (param->conn_stat.state)
  487. {
  488. case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
  489. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  490. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  491. break;
  492. case ESP_A2D_CONNECTION_STATE_CONNECTING:
  493. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  494. break;
  495. case ESP_A2D_CONNECTION_STATE_CONNECTED:
  496. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  497. ESP_LOGE(TAG,"Connection state event received while status was unconnected. Routing message to connecting state handler. State : %u",param->conn_stat.state);
  498. if (param->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){
  499. handle_connect_state_connecting(event, param);
  500. }
  501. break;
  502. case ESP_A2D_CONNECTION_STATE_DISCONNECTING:
  503. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  504. break;
  505. default:
  506. break;
  507. }
  508. }
  509. static void handle_connect_state_connecting(uint16_t event, esp_a2d_cb_param_t *param){
  510. ESP_LOGV(TAG, "A2DP connection state event : %s ",conn_state_str(param->conn_stat.state));
  511. // a2d = (esp_a2d_cb_param_t *)(param);
  512. // if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED) {
  513. // ESP_LOGI(BT_AV_TAG, "a2dp connected");
  514. // s_a2d_state = APP_AV_STATE_CONNECTED;
  515. // s_media_state = APP_AV_MEDIA_STATE_IDLE;
  516. // esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
  517. // } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
  518. // s_a2d_state = APP_AV_STATE_UNCONNECTED;
  519. // }
  520. switch (param->conn_stat.state)
  521. {
  522. case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
  523. if(param->conn_stat.disc_rsn!=ESP_A2D_DISC_RSN_NORMAL){
  524. ESP_LOGE(TAG,"A2DP had an abnormal disconnect event");
  525. }
  526. else {
  527. ESP_LOGW(TAG,"A2DP connect unsuccessful");
  528. }
  529. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  530. break;
  531. case ESP_A2D_CONNECTION_STATE_CONNECTING: {
  532. break;
  533. }
  534. case ESP_A2D_CONNECTION_STATE_CONNECTED:
  535. set_app_source_state(APP_AV_STATE_CONNECTED);
  536. set_a2dp_media_state(APP_AV_MEDIA_STATE_IDLE);
  537. ESP_LOGD(TAG,"Setting scan mode to ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE");
  538. esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
  539. ESP_LOGD(TAG,"Done setting scan mode. App state is now CONNECTED and media state IDLE.");
  540. break;
  541. case ESP_A2D_CONNECTION_STATE_DISCONNECTING:
  542. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  543. set_app_source_state(APP_AV_STATE_DISCONNECTING);
  544. break;
  545. default:
  546. break;
  547. }
  548. }
  549. static void handle_connect_state_connected(uint16_t event, esp_a2d_cb_param_t *param){
  550. ESP_LOGV(TAG, "A2DP Event while connected ");
  551. switch (param->conn_stat.state)
  552. {
  553. case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
  554. ESP_LOGW(TAG,"a2dp disconnected");
  555. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  556. esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
  557. break;
  558. case ESP_A2D_CONNECTION_STATE_CONNECTING:
  559. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  560. break;
  561. case ESP_A2D_CONNECTION_STATE_CONNECTED:
  562. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  563. break;
  564. case ESP_A2D_CONNECTION_STATE_DISCONNECTING:
  565. set_app_source_state(APP_AV_STATE_DISCONNECTING);
  566. break;
  567. default:
  568. break;
  569. }
  570. }
  571. static void handle_connect_state_disconnecting(uint16_t event, esp_a2d_cb_param_t *param){
  572. ESP_LOGV(TAG, "A2DP Event while disconnecting ");
  573. switch (param->conn_stat.state)
  574. {
  575. case ESP_A2D_CONNECTION_STATE_DISCONNECTED:
  576. ESP_LOGI(TAG,"a2dp disconnected");
  577. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  578. esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
  579. break;
  580. case ESP_A2D_CONNECTION_STATE_CONNECTING:
  581. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  582. break;
  583. case ESP_A2D_CONNECTION_STATE_CONNECTED:
  584. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  585. break;
  586. case ESP_A2D_CONNECTION_STATE_DISCONNECTING:
  587. unexpected_connection_state(bt_app_source_a2d_state, param->conn_stat.state);
  588. break;
  589. default:
  590. break;
  591. }
  592. }
  593. static void bt_app_av_sm_hdlr(uint16_t event, void *param)
  594. {
  595. ESP_LOGV(TAG,"bt_app_av_sm_hdlr.%s a2d state: %s", event==BT_APP_HEART_BEAT_EVT?"Heart Beat.":"",APP_AV_STATE_DESC[bt_app_source_a2d_state]);
  596. switch (bt_app_source_a2d_state) {
  597. case APP_AV_STATE_DISCOVERING:
  598. ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", APP_AV_STATE_DESC[bt_app_source_a2d_state], event, output_state_str());
  599. break;
  600. case APP_AV_STATE_DISCOVERED:
  601. ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", APP_AV_STATE_DESC[bt_app_source_a2d_state], event, output_state_str());
  602. break;
  603. case APP_AV_STATE_UNCONNECTED:
  604. bt_app_av_state_unconnected(event, param);
  605. break;
  606. case APP_AV_STATE_CONNECTING:
  607. bt_app_av_state_connecting(event, param);
  608. break;
  609. case APP_AV_STATE_CONNECTED:
  610. bt_app_av_state_connected(event, param);
  611. break;
  612. case APP_AV_STATE_DISCONNECTING:
  613. bt_app_av_state_disconnecting(event, param);
  614. break;
  615. default:
  616. ESP_LOGE(TAG,"%s invalid state %d", __func__, bt_app_source_a2d_state);
  617. break;
  618. }
  619. }
  620. static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
  621. {
  622. if (bda == NULL || str == NULL || size < 18) {
  623. return NULL;
  624. }
  625. uint8_t *p = bda;
  626. sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
  627. p[0], p[1], p[2], p[3], p[4], p[5]);
  628. return str;
  629. }
  630. static bool get_name_from_eir(uint8_t *eir, uint8_t *bdname, uint8_t *bdname_len)
  631. {
  632. uint8_t *rmt_bdname = NULL;
  633. uint8_t rmt_bdname_len = 0;
  634. if (!eir) {
  635. return false;
  636. }
  637. rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len);
  638. if (!rmt_bdname) {
  639. rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len);
  640. }
  641. if (rmt_bdname) {
  642. if (rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) {
  643. rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN;
  644. }
  645. if (bdname) {
  646. memcpy(bdname, rmt_bdname, rmt_bdname_len);
  647. bdname[rmt_bdname_len] = '\0';
  648. }
  649. if (bdname_len) {
  650. *bdname_len = rmt_bdname_len;
  651. }
  652. return true;
  653. }
  654. return false;
  655. }
  656. static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param)
  657. {
  658. char bda_str[18];
  659. uint32_t cod = 0;
  660. int32_t rssi = -129; /* invalid value */
  661. uint8_t *eir = NULL;
  662. uint8_t nameLen = 0;
  663. esp_bt_gap_dev_prop_t *p;
  664. memset(bda_str, 0x00, sizeof(bda_str));
  665. if(bt_app_source_a2d_state != APP_AV_STATE_DISCOVERING)
  666. {
  667. // Ignore messages that might have been queued already
  668. // when we've discovered the target device.
  669. return;
  670. }
  671. memset(s_peer_bdname, 0x00,sizeof(s_peer_bdname));
  672. bda2str(param->disc_res.bda, bda_str, 18);
  673. ESP_LOGV(TAG,"\n=======================\nScanned device: %s",bda_str );
  674. for (int i = 0; i < param->disc_res.num_prop; i++) {
  675. p = param->disc_res.prop + i;
  676. switch (p->type) {
  677. case ESP_BT_GAP_DEV_PROP_COD:
  678. cod = *(uint32_t *)(p->val);
  679. ESP_LOGV(TAG,"-- Class of Device: 0x%x", cod);
  680. break;
  681. case ESP_BT_GAP_DEV_PROP_RSSI:
  682. rssi = *(int8_t *)(p->val);
  683. ESP_LOGV(TAG,"-- RSSI: %d", rssi);
  684. break;
  685. case ESP_BT_GAP_DEV_PROP_EIR:
  686. eir = (uint8_t *)(p->val);
  687. ESP_LOGV(TAG,"-- EIR: %u", *eir);
  688. break;
  689. case ESP_BT_GAP_DEV_PROP_BDNAME:
  690. nameLen = (p->len > ESP_BT_GAP_MAX_BDNAME_LEN) ? ESP_BT_GAP_MAX_BDNAME_LEN : (uint8_t)p->len;
  691. memcpy(s_peer_bdname, (uint8_t *)(p->val), nameLen);
  692. s_peer_bdname[nameLen] = '\0';
  693. ESP_LOGV(TAG,"-- Name: %s", s_peer_bdname);
  694. break;
  695. default:
  696. break;
  697. }
  698. }
  699. if (!esp_bt_gap_is_valid_cod(cod)){
  700. /* search for device with MAJOR service class as "rendering" in COD */
  701. ESP_LOGV(TAG,"--Invalid class of device. Skipping.\n");
  702. return;
  703. }
  704. else if (!(esp_bt_gap_get_cod_srvc(cod) & ESP_BT_COD_SRVC_RENDERING))
  705. {
  706. ESP_LOGV(TAG,"--Not a rendering device. Skipping.\n");
  707. return;
  708. }
  709. /* search for device named "ESP_SPEAKER" in its extended inqury response */
  710. if (eir) {
  711. ESP_LOGV(TAG,"--Getting details from eir.\n");
  712. get_name_from_eir(eir, s_peer_bdname, NULL);
  713. ESP_LOGV(TAG,"--Device name is %s\n",s_peer_bdname);
  714. }
  715. if(strlen((char *)s_peer_bdname)>0) {
  716. peers_list_maintain((const char *)s_peer_bdname, rssi);
  717. }
  718. if (squeezelite_conf.sink_name && strlen(squeezelite_conf.sink_name) >0 && strcmp((char *)s_peer_bdname, squeezelite_conf.sink_name) == 0) {
  719. ESP_LOGI(TAG,"Found our target device. address %s, name %s", bda_str, s_peer_bdname);
  720. ESP_LOGV(TAG,"=======================\n");
  721. if(esp_bt_gap_cancel_discovery()!=ESP_ERR_INVALID_STATE)
  722. {
  723. ESP_LOGD(TAG,"Cancel device discovery ...");
  724. memcpy(s_peer_bda, param->disc_res.bda, ESP_BD_ADDR_LEN);
  725. set_app_source_state(APP_AV_STATE_DISCOVERED);
  726. }
  727. else
  728. {
  729. ESP_LOGE(TAG,"Cancel device discovery failed...");
  730. }
  731. }
  732. else
  733. {
  734. ESP_LOGV(TAG,"Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name?squeezelite_conf.sink_name:"N/A");
  735. }
  736. }
  737. static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
  738. {
  739. switch (event) {
  740. case BT_APP_EVT_STACK_UP: {
  741. ESP_LOGI(TAG,"BT Stack going up.");
  742. /* set up device name */
  743. char * a2dp_dev_name = config_alloc_get_default(NVS_TYPE_STR, "a2dp_dev_name", CONFIG_A2DP_DEV_NAME, 0);
  744. if(a2dp_dev_name == NULL){
  745. ESP_LOGW(TAG,"Unable to retrieve the a2dp device name from nvs");
  746. esp_bt_dev_set_device_name(CONFIG_A2DP_DEV_NAME);
  747. }
  748. else {
  749. esp_bt_dev_set_device_name(a2dp_dev_name);
  750. free(a2dp_dev_name);
  751. }
  752. ESP_LOGI(TAG,"Preparing to connect");
  753. /* register GAP callback function */
  754. esp_bt_gap_register_callback(bt_app_gap_cb);
  755. /* initialize AVRCP controller */
  756. esp_avrc_ct_init();
  757. esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
  758. esp_avrc_rn_evt_cap_mask_t evt_set = {0};
  759. esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE);
  760. assert(esp_avrc_tg_set_rn_evt_cap(&evt_set) == ESP_OK);
  761. /* initialize A2DP source */
  762. esp_a2d_register_callback(&bt_app_a2d_cb);
  763. esp_a2d_source_register_data_callback(&output_bt_data);
  764. esp_a2d_source_init();
  765. /* set discoverable and connectable mode */
  766. esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
  767. /* start device discovery */
  768. ESP_LOGI(TAG,"Starting device discovery...");
  769. set_app_source_state(APP_AV_STATE_DISCOVERING);
  770. esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
  771. /* create and start heart beat timer */
  772. int tmr_id = 0;
  773. s_tmr = xTimerCreate("connTmr", ( prev_duration/ portTICK_RATE_MS),pdFALSE, (void *)tmr_id, a2d_app_heart_beat);
  774. xTimerStart(s_tmr, portMAX_DELAY);
  775. break;
  776. }
  777. default:
  778. ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
  779. break;
  780. }
  781. }
  782. static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)
  783. {
  784. switch (event) {
  785. case ESP_AVRC_CT_METADATA_RSP_EVT:
  786. case ESP_AVRC_CT_CONNECTION_STATE_EVT:
  787. case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT:
  788. case ESP_AVRC_CT_CHANGE_NOTIFY_EVT:
  789. case ESP_AVRC_CT_REMOTE_FEATURES_EVT:
  790. case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT:
  791. case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: {
  792. ESP_LOGD(TAG,"Received %s message", ESP_AVRC_CT_DESC[event]);
  793. bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL);
  794. break;
  795. }
  796. default:
  797. ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event);
  798. break;
  799. }
  800. }
  801. static void bt_app_av_media_proc(uint16_t event, void *param)
  802. {
  803. esp_a2d_cb_param_t *a2d = NULL;
  804. switch (bt_app_source_media_state) {
  805. case APP_AV_MEDIA_STATE_IDLE: {
  806. if (event == BT_APP_HEART_BEAT_EVT) {
  807. if(!output_stopped())
  808. {
  809. ESP_LOGI(TAG,"Output state is %s, Checking if A2DP is ready.", output_state_str());
  810. esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY);
  811. }
  812. } else if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) {
  813. a2d = (esp_a2d_cb_param_t *)(param);
  814. if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY &&
  815. a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS
  816. ) {
  817. ESP_LOGI(TAG,"a2dp media ready, starting playback!");
  818. set_a2dp_media_state(APP_AV_MEDIA_STATE_STARTING);
  819. esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_START);
  820. }
  821. }
  822. break;
  823. }
  824. case APP_AV_MEDIA_STATE_STARTING: {
  825. if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) {
  826. a2d = (esp_a2d_cb_param_t *)(param);
  827. if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_START &&
  828. a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) {
  829. ESP_LOGI(TAG,"a2dp media started successfully.");
  830. set_a2dp_media_state(APP_AV_MEDIA_STATE_STARTED);
  831. } else {
  832. // not started succesfully, transfer to idle state
  833. ESP_LOGI(TAG,"a2dp media start failed.");
  834. set_a2dp_media_state(APP_AV_MEDIA_STATE_IDLE);
  835. }
  836. }
  837. break;
  838. }
  839. case APP_AV_MEDIA_STATE_STARTED: {
  840. if (event == BT_APP_HEART_BEAT_EVT) {
  841. if(output_stopped()) {
  842. ESP_LOGI(TAG,"Output state is %s. Stopping a2dp media ...", output_state_str());
  843. set_a2dp_media_state(APP_AV_MEDIA_STATE_STOPPING);
  844. esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
  845. } else {
  846. output_bt_tick();
  847. }
  848. }
  849. break;
  850. }
  851. case APP_AV_MEDIA_STATE_STOPPING: {
  852. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(APP_AV_MEDIA_STATE_STOPPING));
  853. if (event == ESP_A2D_MEDIA_CTRL_ACK_EVT) {
  854. a2d = (esp_a2d_cb_param_t *)(param);
  855. if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_STOP &&
  856. a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) {
  857. ESP_LOGI(TAG,"a2dp media stopped successfully...");
  858. set_a2dp_media_state(APP_AV_MEDIA_STATE_IDLE);
  859. } else {
  860. ESP_LOGI(TAG,"a2dp media stopping...");
  861. esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
  862. }
  863. }
  864. break;
  865. }
  866. case APP_AV_MEDIA_STATE_WAIT_DISCONNECT:{
  867. esp_a2d_source_disconnect(s_peer_bda);
  868. set_app_source_state(APP_AV_STATE_DISCONNECTING);
  869. ESP_LOGI(TAG,"a2dp disconnecting...");
  870. }
  871. }
  872. }
  873. static void bt_app_av_state_unconnected(uint16_t event, void *param)
  874. {
  875. ESP_LOGV(TAG, "Handling state unconnected A2DP event");
  876. switch (event) {
  877. case ESP_A2D_CONNECTION_STATE_EVT:
  878. handle_connect_state_unconnected(event, (esp_a2d_cb_param_t *)param);
  879. break;
  880. case ESP_A2D_AUDIO_STATE_EVT:
  881. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT));
  882. break;
  883. case ESP_A2D_AUDIO_CFG_EVT:
  884. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT));
  885. break;
  886. case ESP_A2D_MEDIA_CTRL_ACK_EVT:
  887. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT));
  888. break;
  889. case BT_APP_HEART_BEAT_EVT: {
  890. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(BT_APP_HEART_BEAT_EVT));
  891. switch (esp_bluedroid_get_status()) {
  892. case ESP_BLUEDROID_STATUS_UNINITIALIZED:
  893. ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_UNINITIALIZED.");
  894. break;
  895. case ESP_BLUEDROID_STATUS_INITIALIZED:
  896. ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_INITIALIZED.");
  897. break;
  898. case ESP_BLUEDROID_STATUS_ENABLED:
  899. ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_ENABLED.");
  900. break;
  901. default:
  902. break;
  903. }
  904. uint8_t *p = s_peer_bda;
  905. ESP_LOGI(TAG, "a2dp connecting to %s, BT peer: %02x:%02x:%02x:%02x:%02x:%02x",s_peer_bdname,p[0], p[1], p[2], p[3], p[4], p[5]);
  906. if(esp_a2d_source_connect(s_peer_bda)==ESP_OK) {
  907. set_app_source_state(APP_AV_STATE_CONNECTING);
  908. s_connecting_intv = 0;
  909. }
  910. else {
  911. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  912. // there was an issue connecting... continue to discover
  913. ESP_LOGE(TAG,"Attempt at connecting failed, restart at discover...");
  914. esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
  915. }
  916. break;
  917. }
  918. default:
  919. ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
  920. break;
  921. }
  922. }
  923. static void bt_app_av_state_connecting(uint16_t event, void *param)
  924. {
  925. switch (event) {
  926. case ESP_A2D_CONNECTION_STATE_EVT:
  927. handle_connect_state_connecting(event, (esp_a2d_cb_param_t *)param);
  928. break;
  929. case ESP_A2D_AUDIO_STATE_EVT:
  930. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT));
  931. break;
  932. case ESP_A2D_AUDIO_CFG_EVT:
  933. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT));
  934. break;
  935. case ESP_A2D_MEDIA_CTRL_ACK_EVT:
  936. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT));
  937. break;
  938. case BT_APP_HEART_BEAT_EVT:
  939. if (++s_connecting_intv >= 2) {
  940. set_app_source_state(APP_AV_STATE_UNCONNECTED);
  941. ESP_LOGW(TAG,"A2DP Connect time out! Setting state to Unconnected. ");
  942. s_connecting_intv = 0;
  943. }
  944. break;
  945. default:
  946. ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
  947. break;
  948. }
  949. }
  950. static void bt_app_av_state_connected(uint16_t event, void *param)
  951. {
  952. esp_a2d_cb_param_t *a2d = NULL;
  953. switch (event) {
  954. case ESP_A2D_CONNECTION_STATE_EVT: {
  955. handle_connect_state_connected(event, (esp_a2d_cb_param_t *)param);
  956. break;
  957. }
  958. case ESP_A2D_AUDIO_STATE_EVT: {
  959. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT));
  960. a2d = (esp_a2d_cb_param_t *)(param);
  961. if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) {
  962. s_pkt_cnt = 0;
  963. }
  964. break;
  965. }
  966. case ESP_A2D_AUDIO_CFG_EVT:
  967. // not suppposed to occur for A2DP source
  968. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT));
  969. break;
  970. case ESP_A2D_MEDIA_CTRL_ACK_EVT:{
  971. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT));
  972. bt_app_av_media_proc(event, param);
  973. break;
  974. }
  975. case BT_APP_HEART_BEAT_EVT: {
  976. ESP_LOGV(TAG,QUOTE(BT_APP_HEART_BEAT_EVT));
  977. bt_app_av_media_proc(event, param);
  978. break;
  979. }
  980. default:
  981. ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
  982. break;
  983. }
  984. }
  985. static void bt_app_av_state_disconnecting(uint16_t event, void *param)
  986. {
  987. switch (event) {
  988. case ESP_A2D_CONNECTION_STATE_EVT:
  989. handle_connect_state_disconnecting( event, (esp_a2d_cb_param_t *)param);
  990. break;
  991. case ESP_A2D_AUDIO_STATE_EVT:
  992. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_STATE_EVT));
  993. break;
  994. case ESP_A2D_AUDIO_CFG_EVT:
  995. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_AUDIO_CFG_EVT));
  996. break;
  997. case ESP_A2D_MEDIA_CTRL_ACK_EVT:
  998. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT));
  999. break;
  1000. case BT_APP_HEART_BEAT_EVT:
  1001. ESP_LOG_DEBUG_EVENT(TAG,QUOTE(BT_APP_HEART_BEAT_EVT));
  1002. break;
  1003. default:
  1004. ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
  1005. break;
  1006. }
  1007. }
  1008. static void bt_av_volume_changed(void)
  1009. {
  1010. if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap,
  1011. ESP_AVRC_RN_VOLUME_CHANGE)) {
  1012. esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_VOLUME_CHANGE, ESP_AVRC_RN_VOLUME_CHANGE, 0);
  1013. }
  1014. }
  1015. static void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter)
  1016. {
  1017. switch (event_id) {
  1018. case ESP_AVRC_RN_VOLUME_CHANGE:
  1019. ESP_LOGI(BT_RC_CT_TAG, "Volume changed: %d", event_parameter->volume);
  1020. ESP_LOGI(BT_RC_CT_TAG, "Set absolute volume: volume %d", event_parameter->volume + 5);
  1021. esp_avrc_ct_send_set_absolute_volume_cmd(APP_RC_CT_TL_RN_VOLUME_CHANGE, event_parameter->volume + 5);
  1022. bt_av_volume_changed();
  1023. break;
  1024. }
  1025. }
  1026. static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param)
  1027. {
  1028. ESP_LOGD(BT_RC_CT_TAG, "%s evt %d", __func__, event);
  1029. esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param);
  1030. switch (event) {
  1031. case ESP_AVRC_CT_CONNECTION_STATE_EVT: {
  1032. uint8_t *bda = rc->conn_stat.remote_bda;
  1033. ESP_LOGI(BT_RC_CT_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]",
  1034. rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
  1035. if (rc->conn_stat.connected) {
  1036. // get remote supported event_ids of peer AVRCP Target
  1037. esp_avrc_ct_send_get_rn_capabilities_cmd(APP_RC_CT_TL_GET_CAPS);
  1038. } else {
  1039. // clear peer notification capability record
  1040. s_avrc_peer_rn_cap.bits = 0;
  1041. }
  1042. break;
  1043. }
  1044. case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: {
  1045. ESP_LOGI(BT_RC_CT_TAG, "AVRC passthrough rsp: key_code 0x%x, key_state %d", rc->psth_rsp.key_code, rc->psth_rsp.key_state);
  1046. break;
  1047. }
  1048. case ESP_AVRC_CT_METADATA_RSP_EVT: {
  1049. ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text);
  1050. free(rc->meta_rsp.attr_text);
  1051. break;
  1052. }
  1053. case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: {
  1054. ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id);
  1055. bt_av_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter);
  1056. break;
  1057. }
  1058. case ESP_AVRC_CT_REMOTE_FEATURES_EVT: {
  1059. ESP_LOGI(BT_RC_CT_TAG, "AVRC remote features %x, TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag);
  1060. break;
  1061. }
  1062. case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: {
  1063. ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count,
  1064. rc->get_rn_caps_rsp.evt_set.bits);
  1065. s_avrc_peer_rn_cap.bits = rc->get_rn_caps_rsp.evt_set.bits;
  1066. bt_av_volume_changed();
  1067. break;
  1068. }
  1069. case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: {
  1070. ESP_LOGI(BT_RC_CT_TAG, "Set absolute volume rsp: volume %d", rc->set_volume_rsp.volume);
  1071. break;
  1072. }
  1073. default:
  1074. ESP_LOGE(BT_RC_CT_TAG, "%s unhandled evt %d", __func__, event);
  1075. break;
  1076. }
  1077. }