bt_app_source.c 42 KB

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