2
0

bt_app_source.c 42 KB

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