bt_app_source.c 38 KB

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