bta_dm_pm.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2003-2012 Broadcom Corporation
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at:
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. ******************************************************************************/
  18. /******************************************************************************
  19. *
  20. * This file contains the action functions for device manager state
  21. * machine.
  22. *
  23. ******************************************************************************/
  24. // #include <assert.h>
  25. #include <string.h>
  26. #include "bta/bta_sys.h"
  27. #include "bta/bta_api.h"
  28. #include "bta_dm_int.h"
  29. #include "stack/btm_api.h"
  30. #include "osi/allocator.h"
  31. #if BTA_DYNAMIC_MEMORY == FALSE
  32. tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
  33. #else
  34. tBTA_DM_CONNECTED_SRVCS *bta_dm_conn_srvcs_ptr;
  35. #endif
  36. #if (BTA_DM_PM_INCLUDED == TRUE)
  37. static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
  38. static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_mode,
  39. tBTA_DM_PM_REQ pm_req);
  40. static void bta_dm_pm_timer_cback(void *p_tle);
  41. static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status);
  42. static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr);
  43. static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index);
  44. static BOOLEAN bta_dm_pm_is_sco_active (void);
  45. static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
  46. static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
  47. static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer,
  48. UINT8 timer_idx);
  49. #if (BTM_SSR_INCLUDED == TRUE)
  50. #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
  51. #include "../hh/bta_hh_int.h"
  52. /* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */
  53. #define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1
  54. #endif /* (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) */
  55. static void bta_dm_pm_ssr(BD_ADDR peer_addr);
  56. #endif /* (BTM_SSR_INCLUDED == TRUE) */
  57. /*******************************************************************************
  58. **
  59. ** Function bta_dm_init_pm
  60. **
  61. ** Description Initializes the BT low power manager
  62. **
  63. **
  64. ** Returns void
  65. **
  66. *******************************************************************************/
  67. void bta_dm_init_pm(void)
  68. {
  69. memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
  70. /* if there are no power manger entries, so not register */
  71. if (p_bta_dm_pm_cfg[0].app_id != 0) {
  72. bta_sys_pm_register((tBTA_SYS_CONN_CBACK *)bta_dm_pm_cback);
  73. BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
  74. bta_dm_pm_btm_cback);
  75. }
  76. /* Need to initialize all PM timer service IDs */
  77. for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  78. for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
  79. bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX;
  80. }
  81. }
  82. }
  83. /*******************************************************************************
  84. **
  85. ** Function bta_dm_disable_pm
  86. **
  87. ** Description Disable PM
  88. **
  89. **
  90. ** Returns void
  91. **
  92. *******************************************************************************/
  93. void bta_dm_disable_pm(void)
  94. {
  95. BTM_PmRegister( BTM_PM_DEREG, &bta_dm_cb.pm_id, NULL);
  96. /*
  97. * Deregister the PM callback from the system handling to prevent
  98. * re-enabling the PM timers after this call if the callback is invoked.
  99. */
  100. bta_sys_pm_register((tBTA_SYS_CONN_CBACK *)NULL);
  101. /* Need to stop all active timers. */
  102. for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  103. for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
  104. bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
  105. bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION;
  106. }
  107. }
  108. }
  109. /*******************************************************************************
  110. **
  111. ** Function bta_dm_pm_stop_timer
  112. **
  113. ** Description stop a PM timer
  114. **
  115. **
  116. ** Returns void
  117. **
  118. *******************************************************************************/
  119. static void bta_dm_pm_stop_timer(BD_ADDR peer_addr)
  120. {
  121. APPL_TRACE_DEBUG("%s: ", __func__);
  122. for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  123. if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) {
  124. for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
  125. bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
  126. /*
  127. * TODO: For now, stopping the timer does not reset
  128. * pm_action[j].
  129. * The reason is because some of the internal logic that
  130. * (re)assigns the pm_action[] values is taking into account
  131. * the older value; e.g., see the pm_action[] assignment in
  132. * function bta_dm_pm_start_timer().
  133. * Such subtlety in the execution logic is error prone, and
  134. * should be eliminiated in the future.
  135. */
  136. }
  137. break;
  138. }
  139. }
  140. }
  141. /*******************************************************************************
  142. **
  143. ** Function bta_pm_action_to_timer_idx
  144. **
  145. ** Description convert power mode into timer index for each connected device
  146. **
  147. **
  148. ** Returns index of the power mode delay timer
  149. **
  150. *******************************************************************************/
  151. static UINT8 bta_pm_action_to_timer_idx(UINT8 pm_action)
  152. {
  153. if (pm_action == BTA_DM_PM_SUSPEND) {
  154. return BTA_DM_PM_SUSPEND_TIMER_IDX;
  155. } else if (pm_action == BTA_DM_PM_PARK) {
  156. return BTA_DM_PM_PARK_TIMER_IDX;
  157. } else if ((pm_action & BTA_DM_PM_SNIFF) == BTA_DM_PM_SNIFF) {
  158. return BTA_DM_PM_SNIFF_TIMER_IDX;
  159. }
  160. /* Active, no preference, no action and retry */
  161. return BTA_DM_PM_MODE_TIMER_MAX;
  162. }
  163. /*******************************************************************************
  164. **
  165. ** Function bta_dm_pm_stop_timer_by_mode
  166. **
  167. ** Description stop a PM timer
  168. **
  169. **
  170. ** Returns void
  171. **
  172. *******************************************************************************/
  173. static void bta_dm_pm_stop_timer_by_mode(BD_ADDR peer_addr, UINT8 power_mode)
  174. {
  175. const UINT8 timer_idx = bta_pm_action_to_timer_idx(power_mode);
  176. if (timer_idx == BTA_DM_PM_MODE_TIMER_MAX) {
  177. return;
  178. }
  179. for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  180. if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) {
  181. if (bta_dm_cb.pm_timer[i].srvc_id[timer_idx] != BTA_ID_MAX) {
  182. bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], timer_idx);
  183. /*
  184. * TODO: Intentionally setting pm_action[timer_idx].
  185. * This assignment should be eliminated in the future - see the
  186. * pm_action[] related comment inside function
  187. * bta_dm_pm_stop_timer().
  188. */
  189. bta_dm_cb.pm_timer[i].pm_action[timer_idx] = power_mode;
  190. }
  191. break;
  192. }
  193. }
  194. }
  195. /*******************************************************************************
  196. **
  197. ** Function bta_dm_pm_stop_timer_by_srvc_id
  198. **
  199. ** Description stop all timer started by the service ID.
  200. **
  201. **
  202. ** Returns index of the power mode delay timer
  203. **
  204. *******************************************************************************/
  205. static void bta_dm_pm_stop_timer_by_srvc_id(BD_ADDR peer_addr, UINT8 srvc_id)
  206. {
  207. for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  208. if (bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr)) {
  209. for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
  210. if (bta_dm_cb.pm_timer[i].srvc_id[j] == srvc_id) {
  211. bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i], j);
  212. bta_dm_cb.pm_timer[i].pm_action[j] = BTA_DM_PM_NO_ACTION;
  213. break;
  214. }
  215. }
  216. }
  217. }
  218. }
  219. /*******************************************************************************
  220. **
  221. ** Function bta_dm_pm_start_timer
  222. **
  223. ** Description start a PM timer
  224. **
  225. **
  226. ** Returns void
  227. **
  228. *******************************************************************************/
  229. static void bta_dm_pm_start_timer(tBTA_PM_TIMER *p_timer, UINT8 timer_idx,
  230. INT32 timeout, UINT8 srvc_id, UINT8 pm_action)
  231. {
  232. p_timer->in_use = TRUE;
  233. p_timer->timer[timer_idx].p_cback = bta_dm_pm_timer_cback;
  234. if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX) {
  235. p_timer->active++;
  236. }
  237. if (p_timer->pm_action[timer_idx] < pm_action) {
  238. p_timer->pm_action[timer_idx] = pm_action;
  239. }
  240. p_timer->srvc_id[timer_idx] = srvc_id;
  241. bta_sys_start_timer(&p_timer->timer[timer_idx], 0, timeout);
  242. }
  243. /*******************************************************************************
  244. **
  245. ** Function bta_dm_pm_stop_timer_by_index
  246. **
  247. ** Description stop a PM timer
  248. **
  249. **
  250. ** Returns void
  251. **
  252. *******************************************************************************/
  253. static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer,
  254. UINT8 timer_idx)
  255. {
  256. if ((p_timer == NULL) || (timer_idx >= BTA_DM_PM_MODE_TIMER_MAX)) {
  257. return;
  258. }
  259. if (p_timer->srvc_id[timer_idx] == BTA_ID_MAX) {
  260. return; /* The timer was not scheduled */
  261. }
  262. assert(p_timer->in_use && (p_timer->active > 0));
  263. bta_sys_stop_timer(&p_timer->timer[timer_idx]);
  264. p_timer->srvc_id[timer_idx] = BTA_ID_MAX;
  265. /* NOTE: pm_action[timer_idx] intentionally not reset */
  266. p_timer->active--;
  267. if (p_timer->active == 0) {
  268. p_timer->in_use = FALSE;
  269. }
  270. }
  271. UINT32 bta_dm_pm_get_remaining_ticks (TIMER_LIST_ENT *p_target_tle)
  272. {
  273. return bta_sys_get_remaining_ticks(p_target_tle);
  274. }
  275. /*******************************************************************************
  276. **
  277. ** Function bta_dm_pm_cback
  278. **
  279. ** Description Conn change callback from sys for low power management
  280. **
  281. **
  282. ** Returns void
  283. **
  284. *******************************************************************************/
  285. static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
  286. {
  287. UINT8 i, j;
  288. tBTA_DM_PEER_DEVICE *p_dev;
  289. #if (BTM_SSR_INCLUDED == TRUE)
  290. UINT8 *p = NULL;
  291. int index = BTA_DM_PM_SSR0;
  292. #endif
  293. APPL_TRACE_DEBUG("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id, app_id);
  294. p_dev = bta_dm_find_peer_device(peer_addr);
  295. /* find if there is an power mode entry for the service */
  296. for (i = 1; i <= p_bta_dm_pm_cfg[0].app_id; i++) {
  297. if ((p_bta_dm_pm_cfg[i].id == id)
  298. && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id ))) {
  299. break;
  300. }
  301. }
  302. /* if no entries are there for the app_id and subsystem in p_bta_dm_pm_spec*/
  303. if (i > p_bta_dm_pm_cfg[0].app_id) {
  304. return;
  305. }
  306. bta_dm_pm_stop_timer_by_srvc_id(peer_addr, id);
  307. /*p_dev = bta_dm_find_peer_device(peer_addr);*/
  308. #if (BTM_SSR_INCLUDED == TRUE)
  309. /* set SSR parameters on SYS CONN OPEN */
  310. if ((BTA_SYS_CONN_OPEN == status) && p_dev && (p_dev->info & BTA_DM_DI_USE_SSR)) {
  311. index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
  312. }
  313. #endif
  314. /* if no action for the event */
  315. if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_ACTION) {
  316. #if (BTM_SSR_INCLUDED == TRUE)
  317. if (BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */
  318. #endif
  319. return;
  320. }
  321. for (j = 0; j < bta_dm_conn_srvcs.count ; j++) {
  322. /* check if an entry already present */
  323. if ((bta_dm_conn_srvcs.conn_srvc[j].id == id)
  324. && (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id )
  325. && !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr)) {
  326. bta_dm_conn_srvcs.conn_srvc[j].new_request = TRUE;
  327. break;
  328. }
  329. }
  330. /* if subsystem has no more preference on the power mode remove
  331. the cb */
  332. if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_PREF) {
  333. if (j != bta_dm_conn_srvcs.count) {
  334. bta_dm_conn_srvcs.count--;
  335. for (; j < bta_dm_conn_srvcs.count ; j++) {
  336. memcpy(&bta_dm_conn_srvcs.conn_srvc[j], &bta_dm_conn_srvcs.conn_srvc[j + 1], sizeof(bta_dm_conn_srvcs.conn_srvc[j]));
  337. }
  338. } else {
  339. APPL_TRACE_WARNING("bta_dm_act no entry for connected service cbs");
  340. return;
  341. }
  342. } else if (j == bta_dm_conn_srvcs.count ) {
  343. /* check if we have more connected service that cbs */
  344. if (bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS) {
  345. APPL_TRACE_WARNING("bta_dm_act no more connected service cbs");
  346. return;
  347. }
  348. /* fill in a new cb */
  349. bta_dm_conn_srvcs.conn_srvc[j].id = id;
  350. bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id;
  351. bta_dm_conn_srvcs.conn_srvc[j].new_request = TRUE;
  352. bdcpy(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr);
  353. APPL_TRACE_WARNING("new conn_srvc id:%d, app_id:%d", id, app_id);
  354. bta_dm_conn_srvcs.count++;
  355. bta_dm_conn_srvcs.conn_srvc[j].state = status;
  356. } else {
  357. /* no service is added or removed. only updating status. */
  358. bta_dm_conn_srvcs.conn_srvc[j].state = status;
  359. }
  360. /* stop timer */
  361. bta_dm_pm_stop_timer(peer_addr);
  362. if (p_dev) {
  363. p_dev->pm_mode_attempted = 0;
  364. p_dev->pm_mode_failed = 0;
  365. }
  366. #if (BTM_SSR_INCLUDED == TRUE)
  367. if (p_bta_dm_ssr_spec[index].max_lat
  368. #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
  369. || index == BTA_DM_PM_SSR_HH
  370. #endif
  371. ) {
  372. bta_dm_pm_ssr(peer_addr);
  373. } else {
  374. if ( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
  375. ((NULL != (p = BTM_ReadRemoteFeatures (peer_addr))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
  376. (index == BTA_DM_PM_SSR0)) {
  377. if (status == BTA_SYS_SCO_OPEN) {
  378. APPL_TRACE_DEBUG("%s: SCO inactive, reset SSR to zero", __func__);
  379. BTM_SetSsrParams (peer_addr, 0, 0, 0 );
  380. } else if (status == BTA_SYS_SCO_CLOSE) {
  381. APPL_TRACE_DEBUG("%s: SCO active, back to old SSR", __func__);
  382. bta_dm_pm_ssr(peer_addr);
  383. }
  384. }
  385. }
  386. #endif
  387. bta_dm_pm_set_mode(peer_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_NEW_REQ);
  388. /* perform the HID link workaround if needed
  389. ** 1. If SCO up/down event is received OR
  390. ** 2. If HID connection open is received and SCO is already active.
  391. ** This will handle the case where HID connects when SCO already active
  392. */
  393. if ( BTM_IsDeviceUp() &&
  394. ( ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ||
  395. ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) ) ) {
  396. BOOLEAN bScoActive;
  397. if (status == BTA_SYS_CONN_OPEN) {
  398. bScoActive = TRUE;
  399. } else {
  400. bScoActive = (status == BTA_SYS_SCO_OPEN);
  401. }
  402. bta_dm_pm_hid_check(bScoActive);
  403. }
  404. }
  405. /*******************************************************************************
  406. **
  407. ** Function bta_dm_pm_set_mode
  408. **
  409. ** Description Set the power mode for the device
  410. **
  411. **
  412. ** Returns void
  413. **
  414. *******************************************************************************/
  415. static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_request,
  416. tBTA_DM_PM_REQ pm_req )
  417. {
  418. tBTA_DM_PM_ACTION pm_action = BTA_DM_PM_NO_ACTION;
  419. UINT16 timeout = 0;
  420. UINT8 i, j;
  421. tBTA_DM_PM_ACTION failed_pm = 0;
  422. tBTA_DM_PEER_DEVICE *p_peer_device = NULL;
  423. tBTA_DM_PM_ACTION allowed_modes = 0;
  424. tBTA_DM_PM_ACTION pref_modes = 0;
  425. tBTA_DM_PM_CFG *p_pm_cfg;
  426. tBTA_DM_PM_SPEC *p_pm_spec;
  427. tBTA_DM_PM_ACTN *p_act0, *p_act1;
  428. tBTA_DM_SRVCS *p_srvcs = NULL;
  429. BOOLEAN timer_started = FALSE;
  430. UINT8 timer_idx, available_timer = BTA_DM_PM_MODE_TIMER_MAX;
  431. UINT32 remaining_ticks = 0;
  432. if (!bta_dm_cb.device_list.count) {
  433. return;
  434. }
  435. /* see if any attempt to put device in low power mode failed */
  436. p_peer_device = bta_dm_find_peer_device(peer_addr);
  437. /* if no peer device found return */
  438. if (p_peer_device == NULL) {
  439. return;
  440. }
  441. failed_pm = p_peer_device->pm_mode_failed;
  442. for (i = 0; i < bta_dm_conn_srvcs.count ; i++) {
  443. p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i];
  444. if (!bdcmp(p_srvcs->peer_bdaddr, peer_addr)) {
  445. /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
  446. for (j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
  447. if ((p_bta_dm_pm_cfg[j].id == p_srvcs->id)
  448. && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) ||
  449. (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id))) {
  450. break;
  451. }
  452. }
  453. p_pm_cfg = &p_bta_dm_pm_cfg[j];
  454. p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx];
  455. p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0];
  456. p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1];
  457. APPL_TRACE_DEBUG("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d", p_srvcs->id, p_srvcs->state, j);
  458. allowed_modes |= p_pm_spec->allow_mask;
  459. /* PM actions are in the order of strictness */
  460. /* first check if the first preference is ok */
  461. if (!(failed_pm & p_act0->power_mode)) {
  462. pref_modes |= p_act0->power_mode;
  463. if (p_act0->power_mode >= pm_action) {
  464. pm_action = p_act0->power_mode;
  465. if (pm_req != BTA_DM_PM_NEW_REQ || p_srvcs->new_request) {
  466. p_srvcs->new_request = FALSE;
  467. timeout = p_act0->timeout;
  468. }
  469. }
  470. }
  471. /* if first preference has already failed, try second preference */
  472. else if (!(failed_pm & p_act1->power_mode)) {
  473. pref_modes |= p_act1->power_mode;
  474. if (p_act1->power_mode > pm_action) {
  475. pm_action = p_act1->power_mode;
  476. timeout = p_act1->timeout;
  477. }
  478. }
  479. }
  480. }
  481. if (pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) {
  482. /* some service don't like the mode */
  483. if (!(allowed_modes & pm_action)) {
  484. /* select the other mode if its allowed and preferred, otherwise 0 which is BTA_DM_PM_NO_ACTION */
  485. pm_action = (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes);
  486. /* no timeout needed if no action is required */
  487. if (pm_action == BTA_DM_PM_NO_ACTION) {
  488. timeout = 0;
  489. }
  490. }
  491. }
  492. /* if need to start a timer */
  493. if ((pm_req != BTA_DM_PM_EXECUTE) && timeout) {
  494. for (i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  495. if (bta_dm_cb.pm_timer[i].in_use && bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr) == 0) {
  496. if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX) {
  497. remaining_ticks = bta_dm_pm_get_remaining_ticks(&bta_dm_cb.pm_timer[i].timer[timer_idx]);
  498. if (remaining_ticks < timeout) {
  499. APPL_TRACE_DEBUG("%s remain 0\n", __func__);
  500. /* Cancel and restart the timer */
  501. /*
  502. * TODO: The value of pm_action[timer_idx] is
  503. * conditionally updated between the two function
  504. * calls below when the timer is restarted.
  505. * This logic is error-prone and should be eliminated
  506. * in the future.
  507. */
  508. bta_dm_pm_stop_timer_by_index(&bta_dm_cb.pm_timer[i],
  509. timer_idx);
  510. bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[i], timer_idx, timeout, p_srvcs->id, pm_action);
  511. }
  512. timer_started = TRUE;
  513. }
  514. break;
  515. } else if (!bta_dm_cb.pm_timer[i].in_use) {
  516. APPL_TRACE_DEBUG("%s dm_pm_timer:%d, %d", __func__, i, timeout);
  517. if (available_timer == BTA_DM_PM_MODE_TIMER_MAX) {
  518. available_timer = i;
  519. }
  520. }
  521. }
  522. /* new power mode for a new active connection */
  523. if (!timer_started) {
  524. if ( available_timer != BTA_DM_PM_MODE_TIMER_MAX) {
  525. bdcpy(bta_dm_cb.pm_timer[available_timer].peer_bdaddr, peer_addr);
  526. if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX) {
  527. bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[available_timer], timer_idx, timeout, p_srvcs->id, pm_action);
  528. timer_started = TRUE;
  529. }
  530. }
  531. /* no more timers */
  532. else {
  533. APPL_TRACE_WARNING("bta_dm_act dm_pm_timer no more");
  534. }
  535. }
  536. return;
  537. }
  538. /* if pending power mode timer expires, and currecnt link is in a
  539. lower power mode than current profile requirement, igonre it */
  540. if (pm_req == BTA_DM_PM_EXECUTE && pm_request < pm_action) {
  541. APPL_TRACE_ERROR("Ignore the power mode request: %d", pm_request)
  542. return;
  543. }
  544. if (pm_action == BTA_DM_PM_PARK) {
  545. p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK;
  546. bta_dm_pm_park(peer_addr);
  547. } else if (pm_action & BTA_DM_PM_SNIFF) {
  548. /* dont initiate SNIFF, if link_policy has it disabled */
  549. if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE) {
  550. p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF;
  551. bta_dm_pm_sniff(p_peer_device, (UINT8)(pm_action & 0x0F) );
  552. } else {
  553. APPL_TRACE_DEBUG("bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request");
  554. }
  555. } else if (pm_action == BTA_DM_PM_ACTIVE) {
  556. bta_dm_pm_active(peer_addr);
  557. }
  558. }
  559. /*******************************************************************************
  560. **
  561. ** Function bta_ag_pm_park
  562. **
  563. ** Description Switch to park mode.
  564. **
  565. **
  566. ** Returns TRUE if park attempted, FALSE otherwise.
  567. **
  568. *******************************************************************************/
  569. static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr)
  570. {
  571. tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
  572. /* if not in park mode, switch to park */
  573. BTM_ReadPowerMode(peer_addr, &mode);
  574. if (mode != BTM_PM_MD_PARK) {
  575. BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &p_bta_dm_pm_md[BTA_DM_PM_PARK_IDX]);
  576. }
  577. return TRUE;
  578. }
  579. /*******************************************************************************
  580. **
  581. ** Function bta_ag_pm_sniff
  582. **
  583. ** Description Switch to sniff mode.
  584. **
  585. **
  586. ** Returns TRUE if sniff attempted, FALSE otherwise.
  587. **
  588. *******************************************************************************/
  589. static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
  590. {
  591. tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
  592. tBTM_PM_PWR_MD pwr_md;
  593. tBTM_STATUS status;
  594. #if (BTM_SSR_INCLUDED == TRUE)
  595. UINT8 *p_rem_feat = NULL;
  596. #endif
  597. BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
  598. #if (BTM_SSR_INCLUDED == TRUE)
  599. p_rem_feat = BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr);
  600. APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info);
  601. if (mode != BTM_PM_MD_SNIFF ||
  602. (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) && p_rem_feat &&
  603. HCI_SNIFF_SUB_RATE_SUPPORTED(p_rem_feat) &&
  604. !(p_peer_dev->info & BTA_DM_DI_USE_SSR)))
  605. #else
  606. APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
  607. if (mode != BTM_PM_MD_SNIFF)
  608. #endif
  609. {
  610. #if (BTM_SSR_INCLUDED == TRUE)
  611. /* Dont initiate Sniff if controller has alreay accepted
  612. * remote sniff params. This avoid sniff loop issue with
  613. * some agrresive headsets who use sniff latencies more than
  614. * DUT supported range of Sniff intervals.*/
  615. if ((mode == BTM_PM_MD_SNIFF) && (p_peer_dev->info & BTA_DM_DI_ACP_SNIFF)) {
  616. APPL_TRACE_DEBUG("%s: already in remote initiate sniff", __func__);
  617. return TRUE;
  618. }
  619. #endif
  620. /* if the current mode is not sniff, issue the sniff command.
  621. * If sniff, but SSR is not used in this link, still issue the command */
  622. memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof (tBTM_PM_PWR_MD));
  623. if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF) {
  624. pwr_md.mode |= BTM_PM_MD_FORCE;
  625. }
  626. status = BTM_SetPowerMode (bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md);
  627. if (status == BTM_CMD_STORED || status == BTM_CMD_STARTED) {
  628. p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF);
  629. p_peer_dev->info |= BTA_DM_DI_SET_SNIFF;
  630. } else if (status == BTM_SUCCESS) {
  631. APPL_TRACE_DEBUG("bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS");
  632. p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
  633. } else { /* error */
  634. APPL_TRACE_ERROR("bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status);
  635. p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
  636. }
  637. }
  638. return TRUE;
  639. }
  640. /*******************************************************************************
  641. **
  642. ** Function bta_dm_pm_ssr
  643. **
  644. ** Description checks and sends SSR parameters
  645. **
  646. ** Returns void
  647. **
  648. *******************************************************************************/
  649. #if (BTM_SSR_INCLUDED == TRUE)
  650. static void bta_dm_pm_ssr(BD_ADDR peer_addr)
  651. {
  652. tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur;
  653. UINT8 i, j;
  654. int ssr = BTA_DM_PM_SSR0;
  655. /* go through the connected services */
  656. for (i = 0; i < bta_dm_conn_srvcs.count ; i++) {
  657. if (!bdcmp(bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr, peer_addr)) {
  658. /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
  659. for (j = 1; j <= p_bta_dm_pm_cfg[0].app_id; j++) {
  660. /* find the associated p_bta_dm_pm_cfg */
  661. if ((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id)
  662. && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID )
  663. || (p_bta_dm_pm_cfg[j].app_id == bta_dm_conn_srvcs.conn_srvc[i].app_id))) {
  664. APPL_TRACE_WARNING("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d",
  665. bta_dm_conn_srvcs.conn_srvc[i].id, bta_dm_conn_srvcs.conn_srvc[i].app_id);
  666. break;
  667. }
  668. }
  669. /* find the ssr index with the smallest max latency. */
  670. p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr];
  671. p_spec = &p_bta_dm_ssr_spec[ssr];
  672. #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
  673. /* HH has the per connection SSR preference, already read the SSR params from BTA HH */
  674. if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr == BTA_DM_PM_SSR_HH) {
  675. if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR) {
  676. continue;
  677. }
  678. }
  679. #endif
  680. if (p_spec_cur->max_lat < p_spec->max_lat ||
  681. (ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0)) {
  682. ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr;
  683. }
  684. }
  685. }
  686. p_spec = &p_bta_dm_ssr_spec[ssr];
  687. APPL_TRACE_WARNING("bta_dm_pm_ssr:%d, lat:%d", ssr, p_spec->max_lat);
  688. if (p_spec->max_lat) {
  689. /* set the SSR parameters. */
  690. BTM_SetSsrParams (peer_addr, p_spec->max_lat,
  691. p_spec->min_rmt_to, p_spec->min_loc_to);
  692. }
  693. }
  694. #endif
  695. /*******************************************************************************
  696. **
  697. ** Function bta_dm_pm_active
  698. **
  699. ** Description Brings connection to active mode
  700. **
  701. **
  702. ** Returns void
  703. **
  704. *******************************************************************************/
  705. void bta_dm_pm_active(BD_ADDR peer_addr)
  706. {
  707. tBTM_PM_PWR_MD pm;
  708. memset( (void *)&pm, 0, sizeof(pm));
  709. /* switch to active mode */
  710. pm.mode = BTM_PM_MD_ACTIVE;
  711. BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm);
  712. }
  713. /*******************************************************************************
  714. **
  715. ** Function bta_dm_pm_btm_cback
  716. **
  717. ** Description BTM power manager callback.
  718. **
  719. **
  720. ** Returns void
  721. **
  722. *******************************************************************************/
  723. static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status)
  724. {
  725. tBTA_DM_PM_BTM_STATUS *p_buf;
  726. if ((p_buf = (tBTA_DM_PM_BTM_STATUS *) osi_malloc(sizeof(tBTA_DM_PM_BTM_STATUS))) != NULL) {
  727. p_buf->hdr.event = BTA_DM_PM_BTM_STATUS_EVT;
  728. p_buf->status = status;
  729. p_buf->value = value;
  730. p_buf->hci_status = hci_status;
  731. bdcpy(p_buf->bd_addr, bd_addr);
  732. bta_sys_sendmsg(p_buf);
  733. }
  734. }
  735. /*******************************************************************************
  736. **
  737. ** Function bta_dm_pm_timer_cback
  738. **
  739. ** Description Power management timer callback.
  740. **
  741. **
  742. ** Returns void
  743. **
  744. *******************************************************************************/
  745. static void bta_dm_pm_timer_cback(void *p_tle)
  746. {
  747. UINT8 i, j;
  748. for (i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
  749. APPL_TRACE_DEBUG("dm_pm_timer[%d] in use? %d", i, bta_dm_cb.pm_timer[i].in_use);
  750. if (bta_dm_cb.pm_timer[i].in_use) {
  751. for (j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
  752. if (&bta_dm_cb.pm_timer[i].timer[j] == (TIMER_LIST_ENT *) p_tle) {
  753. bta_dm_cb.pm_timer[i].active --;
  754. bta_dm_cb.pm_timer[i].srvc_id[j] = BTA_ID_MAX;
  755. APPL_TRACE_DEBUG("dm_pm_timer[%d] expires, timer_idx=%d", i, j);
  756. break;
  757. }
  758. }
  759. if (bta_dm_cb.pm_timer[i].active == 0) {
  760. bta_dm_cb.pm_timer[i].in_use = FALSE;
  761. }
  762. if (j < BTA_DM_PM_MODE_TIMER_MAX) {
  763. break;
  764. }
  765. }
  766. }
  767. /* no more timers */
  768. if (i == BTA_DM_NUM_PM_TIMER) {
  769. return;
  770. }
  771. tBTA_DM_PM_TIMER *p_buf = (tBTA_DM_PM_TIMER *) osi_malloc(sizeof(tBTA_DM_PM_TIMER));
  772. if (p_buf != NULL) {
  773. p_buf->hdr.event = BTA_DM_PM_TIMER_EVT;
  774. p_buf->pm_request = bta_dm_cb.pm_timer[i].pm_action[j];
  775. bdcpy(p_buf->bd_addr, bta_dm_cb.pm_timer[i].peer_bdaddr);
  776. bta_sys_sendmsg(p_buf);
  777. }
  778. }
  779. /*******************************************************************************
  780. **
  781. ** Function bta_dm_pm_btm_status
  782. **
  783. ** Description Process pm status event from btm
  784. **
  785. **
  786. ** Returns void
  787. **
  788. *******************************************************************************/
  789. void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data)
  790. {
  791. APPL_TRACE_DEBUG("%s status: %d", __func__, p_data->pm_status.status);
  792. tBTA_DM_PEER_DEVICE *p_dev = bta_dm_find_peer_device(p_data->pm_status.bd_addr);
  793. if (NULL == p_dev) {
  794. return;
  795. }
  796. tBTA_DM_DEV_INFO info = p_dev->info;
  797. /* check new mode */
  798. switch (p_data->pm_status.status) {
  799. case BTM_PM_STS_ACTIVE:
  800. /* if our sniff or park attempt failed
  801. we should not try it again*/
  802. if (p_data->pm_status.hci_status != 0) {
  803. APPL_TRACE_ERROR("%s hci_status=%d", __func__, p_data->pm_status.hci_status);
  804. p_dev->info &= ~(BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF | BTA_DM_DI_SET_SNIFF);
  805. if (p_dev->pm_mode_attempted & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF)) {
  806. p_dev->pm_mode_failed
  807. |= ((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted);
  808. bta_dm_pm_stop_timer_by_mode(p_data->pm_status.bd_addr, p_dev->pm_mode_attempted);
  809. bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
  810. }
  811. } else {
  812. #if (BTM_SSR_INCLUDED == TRUE)
  813. if (p_dev->prev_low) {
  814. /* need to send the SSR paramaters to controller again */
  815. bta_dm_pm_ssr(p_dev->peer_bdaddr);
  816. }
  817. p_dev->prev_low = BTM_PM_STS_ACTIVE;
  818. #endif
  819. /* link to active mode, need to restart the timer for next low power mode if needed */
  820. bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
  821. bta_dm_pm_set_mode(p_data->pm_status.bd_addr, BTA_DM_PM_NO_ACTION, BTA_DM_PM_RESTART);
  822. }
  823. break;
  824. #if (BTM_SSR_INCLUDED == TRUE)
  825. case BTM_PM_STS_PARK:
  826. case BTM_PM_STS_HOLD:
  827. /* save the previous low power mode - for SSR.
  828. * SSR parameters are sent to controller on "conn open".
  829. * the numbers stay good until park/hold/detach */
  830. if (p_dev->info & BTA_DM_DI_USE_SSR) {
  831. p_dev->prev_low = p_data->pm_status.status;
  832. }
  833. break;
  834. case BTM_PM_STS_SSR:
  835. if (p_data->pm_status.value) {
  836. p_dev->info |= BTA_DM_DI_USE_SSR;
  837. } else {
  838. p_dev->info &= ~BTA_DM_DI_USE_SSR;
  839. }
  840. break;
  841. #endif
  842. case BTM_PM_STS_SNIFF:
  843. if (p_data->pm_status.hci_status == 0) {
  844. /* Stop PM timer now if already active for
  845. * particular device since link is already
  846. * put in sniff mode by remote device, and
  847. * PM timer sole purpose is to put the link
  848. * in sniff mode from host side.
  849. */
  850. bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
  851. } else {
  852. p_dev->info &= ~(BTA_DM_DI_SET_SNIFF | BTA_DM_DI_INT_SNIFF | BTA_DM_DI_ACP_SNIFF);
  853. if (info & BTA_DM_DI_SET_SNIFF) {
  854. p_dev->info |= BTA_DM_DI_INT_SNIFF;
  855. } else {
  856. p_dev->info |= BTA_DM_DI_ACP_SNIFF;
  857. }
  858. }
  859. break;
  860. case BTM_PM_STS_ERROR:
  861. p_dev->info &= ~BTA_DM_DI_SET_SNIFF;
  862. break;
  863. default:
  864. break;
  865. }
  866. }
  867. /*******************************************************************************
  868. **
  869. ** Function bta_dm_pm_timer
  870. **
  871. ** Description Process pm timer event from btm
  872. **
  873. **
  874. ** Returns void
  875. **
  876. *******************************************************************************/
  877. void bta_dm_pm_timer(tBTA_DM_MSG *p_data)
  878. {
  879. APPL_TRACE_EVENT("%s", __func__);
  880. bta_dm_pm_set_mode(p_data->pm_timer.bd_addr, p_data->pm_timer.pm_request, BTA_DM_PM_EXECUTE);
  881. }
  882. /*******************************************************************************
  883. **
  884. ** Function bta_dm_is_sco_active
  885. **
  886. ** Description Loop through connected services for HFP+State=SCO
  887. **
  888. ** Returns BOOLEAN. TRUE if SCO active, else FALSE
  889. **
  890. *******************************************************************************/
  891. static BOOLEAN bta_dm_pm_is_sco_active (void)
  892. {
  893. int j;
  894. BOOLEAN bScoActive = FALSE;
  895. for (j = 0; j < bta_dm_conn_srvcs.count ; j++) {
  896. /* check if an entry already present */
  897. if ( (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG ) && (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN) ) {
  898. bScoActive = TRUE;
  899. break;
  900. }
  901. }
  902. APPL_TRACE_DEBUG("bta_dm_is_sco_active: SCO active: %d", bScoActive);
  903. return bScoActive;
  904. }
  905. /*******************************************************************************
  906. **
  907. ** Function bta_dm_pm_hid_check
  908. **
  909. ** Description Disables/Enables sniff in link policy based on SCO Up/Down
  910. **
  911. ** Returns None
  912. **
  913. *******************************************************************************/
  914. static void bta_dm_pm_hid_check(BOOLEAN bScoActive)
  915. {
  916. int j;
  917. /* if HID is active, disable the link policy */
  918. for (j = 0; j < bta_dm_conn_srvcs.count ; j++) {
  919. /* check if an entry already present */
  920. if (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH ) {
  921. APPL_TRACE_DEBUG ("SCO status change(Active: %d), modify HID link policy. state: %d",
  922. bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state);
  923. bta_dm_pm_set_sniff_policy( bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr), bScoActive);
  924. /* if we had disabled link policy, seems like the hid device stop retrying SNIFF after a few tries. force sniff if needed */
  925. if (!bScoActive) {
  926. bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, BTA_DM_PM_NO_ACTION,
  927. BTA_DM_PM_RESTART);
  928. }
  929. }
  930. }
  931. }
  932. /*******************************************************************************
  933. **
  934. ** Function bta_dm_pm_set_sniff_policy
  935. **
  936. ** Description Disables/Enables sniff in link policy for the give device
  937. **
  938. ** Returns None
  939. **
  940. *******************************************************************************/
  941. static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable)
  942. {
  943. UINT16 policy_setting;
  944. if (!p_dev) {
  945. return;
  946. }
  947. if (bDisable) {
  948. policy_setting = bta_dm_cb.cur_policy &
  949. (HCI_ENABLE_MASTER_SLAVE_SWITCH |
  950. HCI_ENABLE_HOLD_MODE |
  951. HCI_ENABLE_PARK_MODE);
  952. } else {
  953. /* allow sniff after sco is closed */
  954. policy_setting = bta_dm_cb.cur_policy;
  955. }
  956. /* if disabling SNIFF, make sure link is Active */
  957. if (bDisable) {
  958. bta_dm_pm_active(p_dev->peer_bdaddr);
  959. }
  960. /* update device record and set link policy */
  961. p_dev->link_policy = policy_setting;
  962. BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting);
  963. }
  964. #endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
  965. /*******************************************************************************
  966. **
  967. ** Function bta_dm_get_av_count
  968. **
  969. ** Description Get the number of connected AV
  970. **
  971. **
  972. ** Returns number of av connections
  973. **
  974. *******************************************************************************/
  975. UINT8 bta_dm_get_av_count(void)
  976. {
  977. UINT8 count = 0;
  978. for (int i = 0; i < bta_dm_conn_srvcs.count; i++) {
  979. if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) {
  980. ++count;
  981. }
  982. }
  983. return count;
  984. }
  985. /*******************************************************************************
  986. **
  987. ** Function bta_dm_find_peer_device
  988. **
  989. ** Description Given an address, find the associated control block.
  990. **
  991. ** Returns tBTA_DM_PEER_DEVICE
  992. **
  993. *******************************************************************************/
  994. tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr)
  995. {
  996. tBTA_DM_PEER_DEVICE *p_dev = NULL;
  997. for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
  998. if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) {
  999. p_dev = &bta_dm_cb.device_list.peer_device[i];
  1000. break;
  1001. }
  1002. }
  1003. return p_dev;
  1004. }
  1005. #if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE) && SDP_INCLUDED == TRUE)
  1006. /*******************************************************************************
  1007. **
  1008. ** Function bta_dm_pm_obtain_controller_state
  1009. **
  1010. ** Description This function obtains the consolidated controller power state
  1011. **
  1012. ** Parameters:
  1013. **
  1014. *******************************************************************************/
  1015. tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void)
  1016. {
  1017. /* Did not use counts as it is not sure, how accurate the count values are in
  1018. ** bta_dm_cb.device_list.count > 0 || bta_dm_cb.device_list.le_count > 0 */
  1019. tBTA_DM_CONTRL_STATE cur_state = BTA_DM_CONTRL_UNKNOWN;
  1020. cur_state = BTM_PM_ReadControllerState();
  1021. APPL_TRACE_DEBUG("bta_dm_pm_obtain_controller_state: %d", cur_state);
  1022. return cur_state;
  1023. }
  1024. #endif