central.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. /**
  2. * @file
  3. * @author chipsea
  4. * @brief
  5. * @version 0.1
  6. * @date 2020-11-30
  7. * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
  8. * @note
  9. */
  10. /*********************************************************************
  11. * INCLUDES
  12. */
  13. #include "sdk_config.h"
  14. #include "bcomdef.h"
  15. #include "OSAL.h"
  16. #include "osal_cbTimer.h"
  17. #include "osal_snv.h"
  18. #include "hci_tl.h"
  19. #include "l2cap.h"
  20. #include "linkdb.h"
  21. #include "gap.h"
  22. #include "gapbondmgr.h"
  23. #include "central.h"
  24. /*********************************************************************
  25. * MACROS
  26. */
  27. /*********************************************************************
  28. * CONSTANTS
  29. */
  30. // Profile Events
  31. #define START_ADVERTISING_EVT 0x0001
  32. #define RSSI_READ_EVT 0x0002
  33. #define UPDATE_PARAMS_TIMEOUT_EVT 0x0004
  34. // Profile OSAL Message IDs
  35. #define GAPCENTRALROLE_RSSI_MSG_EVT 0xE0
  36. /*********************************************************************
  37. * TYPEDEFS
  38. */
  39. // RSSI read data structure
  40. typedef struct
  41. {
  42. uint16 period;
  43. uint16 connHandle;
  44. uint8 timerId;
  45. } gapCentralRoleRssi_t;
  46. // OSAL event structure for RSSI timer events
  47. typedef struct
  48. {
  49. osal_event_hdr_t hdr;
  50. gapCentralRoleRssi_t *pRssi;
  51. } gapCentralRoleRssiEvent_t;
  52. /*********************************************************************
  53. * GLOBAL VARIABLES
  54. */
  55. /*********************************************************************
  56. * EXTERNAL VARIABLES
  57. */
  58. /*********************************************************************
  59. * EXTERNAL FUNCTIONS
  60. */
  61. /*********************************************************************
  62. * LOCAL VARIABLES
  63. */
  64. // Task ID
  65. static uint8 gapCentralRoleTaskId;
  66. // App callbacks
  67. static gapCentralRoleCB_t *pGapCentralRoleCB;
  68. // Array of RSSI read structures
  69. static gapCentralRoleRssi_t gapCentralRoleRssi[GAPCENTRALROLE_NUM_RSSI_LINKS];
  70. /*********************************************************************
  71. * Profile Parameters - reference GAPCENTRALROLE_PROFILE_PARAMETERS for
  72. * descriptions
  73. */
  74. static uint8 gapCentralRoleIRK[KEYLEN];
  75. static uint8 gapCentralRoleSRK[KEYLEN];
  76. static uint32 gapCentralRoleSignCounter;
  77. static uint8 gapCentralRoleBdAddr[B_ADDR_LEN];
  78. static uint8 gapCentralRoleMaxScanRes = 0;
  79. /*********************************************************************
  80. * LOCAL FUNCTIONS
  81. */
  82. static void gapCentralRole_ProcessOSALMsg( osal_event_hdr_t *pMsg );
  83. static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg );
  84. static gapCentralRoleRssi_t *gapCentralRole_RssiAlloc( uint16 connHandle );
  85. static gapCentralRoleRssi_t *gapCentralRole_RssiFind( uint16 connHandle );
  86. static void gapCentralRole_RssiFree( uint16 connHandle );
  87. static void gapCentralRole_timerCB( uint8 *pData );
  88. /*********************************************************************
  89. * PUBLIC FUNCTIONS
  90. */
  91. /**
  92. * @brief Start the device in Central role. This function is typically
  93. * called once during system startup.
  94. *
  95. * Public function defined in central.h.
  96. */
  97. bStatus_t GAPCentralRole_StartDevice( gapCentralRoleCB_t *pAppCallbacks )
  98. {
  99. if ( pAppCallbacks )
  100. {
  101. pGapCentralRoleCB = pAppCallbacks;
  102. }
  103. return GAP_DeviceInit( gapCentralRoleTaskId, GAP_PROFILE_CENTRAL,
  104. gapCentralRoleMaxScanRes, gapCentralRoleIRK,
  105. gapCentralRoleSRK, &gapCentralRoleSignCounter );
  106. }
  107. /**
  108. * @brief Set a parameter in the Central Profile.
  109. *
  110. * Public function defined in central.h.
  111. */
  112. bStatus_t GAPCentralRole_SetParameter( uint16 param, uint8 len, void *pValue )
  113. {
  114. bStatus_t ret = SUCCESS;
  115. switch ( param )
  116. {
  117. case GAPCENTRALROLE_IRK:
  118. if ( len == KEYLEN )
  119. {
  120. VOID osal_memcpy( gapCentralRoleIRK, pValue, KEYLEN ) ;
  121. }
  122. else
  123. {
  124. ret = bleInvalidRange;
  125. }
  126. break;
  127. case GAPCENTRALROLE_SRK:
  128. if ( len == KEYLEN )
  129. {
  130. VOID osal_memcpy( gapCentralRoleSRK, pValue, KEYLEN ) ;
  131. }
  132. else
  133. {
  134. ret = bleInvalidRange;
  135. }
  136. break;
  137. case GAPCENTRALROLE_SIGNCOUNTER:
  138. if ( len == sizeof ( uint32 ) )
  139. {
  140. gapCentralRoleSignCounter = *((uint32*)pValue);
  141. }
  142. else
  143. {
  144. ret = bleInvalidRange;
  145. }
  146. break;
  147. case GAPCENTRALROLE_MAX_SCAN_RES:
  148. if ( len == sizeof ( uint8 ) )
  149. {
  150. gapCentralRoleMaxScanRes = *((uint8*)pValue);
  151. }
  152. else
  153. {
  154. ret = bleInvalidRange;
  155. }
  156. break;
  157. default:
  158. ret = INVALIDPARAMETER;
  159. break;
  160. }
  161. return ret;
  162. }
  163. /**
  164. * @brief Get a parameter in the Central Profile.
  165. *
  166. * Public function defined in central.h.
  167. */
  168. bStatus_t GAPCentralRole_GetParameter( uint16 param, void *pValue )
  169. {
  170. bStatus_t ret = SUCCESS;
  171. switch ( param )
  172. {
  173. case GAPCENTRALROLE_IRK:
  174. VOID osal_memcpy( pValue, gapCentralRoleIRK, KEYLEN ) ;
  175. break;
  176. case GAPCENTRALROLE_SRK:
  177. VOID osal_memcpy( pValue, gapCentralRoleSRK, KEYLEN ) ;
  178. break;
  179. case GAPCENTRALROLE_SIGNCOUNTER:
  180. *((uint32*)pValue) = gapCentralRoleSignCounter;
  181. break;
  182. case GAPCENTRALROLE_BD_ADDR:
  183. VOID osal_memcpy( pValue, gapCentralRoleBdAddr, B_ADDR_LEN ) ;
  184. break;
  185. case GAPCENTRALROLE_MAX_SCAN_RES:
  186. *((uint8*)pValue) = gapCentralRoleMaxScanRes;
  187. break;
  188. default:
  189. ret = INVALIDPARAMETER;
  190. break;
  191. }
  192. return ret;
  193. }
  194. /**
  195. * @brief Terminate a link.
  196. *
  197. * Public function defined in central.h.
  198. */
  199. bStatus_t GAPCentralRole_TerminateLink( uint16 connHandle )
  200. {
  201. return GAP_TerminateLinkReq( gapCentralRoleTaskId, connHandle, HCI_DISCONNECT_REMOTE_USER_TERM ) ;
  202. }
  203. /**
  204. * @brief Establish a link to a peer device.
  205. *
  206. * Public function defined in central.h.
  207. */
  208. bStatus_t GAPCentralRole_EstablishLink( uint8 highDutyCycle, uint8 whiteList,
  209. uint8 addrTypePeer, uint8 *peerAddr )
  210. {
  211. gapEstLinkReq_t params;
  212. params.taskID = gapCentralRoleTaskId;
  213. params.highDutyCycle = highDutyCycle;
  214. params.whiteList = whiteList;
  215. params.addrTypePeer = addrTypePeer;
  216. VOID osal_memcpy( params.peerAddr, peerAddr, B_ADDR_LEN );
  217. return GAP_EstablishLinkReq( &params );
  218. }
  219. /**
  220. * @brief Update the link connection parameters.
  221. *
  222. * Public function defined in central.h.
  223. */
  224. bStatus_t GAPCentralRole_UpdateLink( uint16 connHandle, uint16 connIntervalMin,
  225. uint16 connIntervalMax, uint16 connLatency,
  226. uint16 connTimeout )
  227. {
  228. return (bStatus_t) HCI_LE_ConnUpdateCmd( connHandle, connIntervalMin,
  229. connIntervalMax, connLatency,
  230. connTimeout, 0, 0 );
  231. }
  232. /**
  233. * @brief Start a device discovery scan.
  234. *
  235. * Public function defined in central.h.
  236. */
  237. bStatus_t GAPCentralRole_StartDiscovery( uint8 mode, uint8 activeScan, uint8 whiteList )
  238. {
  239. gapDevDiscReq_t params;
  240. params.taskID = gapCentralRoleTaskId;
  241. params.mode = mode;
  242. params.activeScan = activeScan;
  243. params.whiteList = whiteList;
  244. return GAP_DeviceDiscoveryRequest( &params );
  245. }
  246. /**
  247. * @brief Cancel a device discovery scan.
  248. *
  249. * Public function defined in central.h.
  250. */
  251. bStatus_t GAPCentralRole_CancelDiscovery( void )
  252. {
  253. return GAP_DeviceDiscoveryCancel( gapCentralRoleTaskId );
  254. }
  255. /**
  256. * @brief Start periodic RSSI reads on a link.
  257. *
  258. * Public function defined in central.h.
  259. */
  260. bStatus_t GAPCentralRole_StartRssi( uint16 connHandle, uint16 period )
  261. {
  262. gapCentralRoleRssi_t *pRssi;
  263. // Verify link is up
  264. if (!linkDB_Up(connHandle))
  265. {
  266. return bleIncorrectMode;
  267. }
  268. // If already allocated
  269. if ((pRssi = gapCentralRole_RssiFind( connHandle )) != NULL)
  270. {
  271. // Stop timer
  272. osal_CbTimerStop( pRssi->timerId );
  273. }
  274. // Allocate structure
  275. else if ((pRssi = gapCentralRole_RssiAlloc( connHandle )) != NULL)
  276. {
  277. pRssi->period = period;
  278. }
  279. // Allocate failed
  280. else
  281. {
  282. return bleNoResources;
  283. }
  284. // Start timer
  285. osal_CbTimerStart( gapCentralRole_timerCB, (uint8 *) pRssi,
  286. period, &pRssi->timerId );
  287. return SUCCESS;
  288. }
  289. /**
  290. * @brief Cancel periodic RSSI reads on a link.
  291. *
  292. * Public function defined in central.h.
  293. */
  294. bStatus_t GAPCentralRole_CancelRssi(uint16 connHandle )
  295. {
  296. gapCentralRoleRssi_t *pRssi;
  297. if ((pRssi = gapCentralRole_RssiFind( connHandle )) != NULL)
  298. {
  299. // Stop timer
  300. osal_CbTimerStop( pRssi->timerId );
  301. // Free RSSI structure
  302. gapCentralRole_RssiFree( connHandle );
  303. return SUCCESS;
  304. }
  305. // Not found
  306. return bleIncorrectMode;
  307. }
  308. /**
  309. * @brief Central Profile Task initialization function.
  310. *
  311. * @param taskId - Task ID.
  312. *
  313. * @return void
  314. */
  315. void GAPCentralRole_Init( uint8 taskId )
  316. {
  317. uint8 i;
  318. gapCentralRoleTaskId = taskId;
  319. // Initialize internal data
  320. for ( i = 0; i < GAPCENTRALROLE_NUM_RSSI_LINKS; i++ )
  321. {
  322. gapCentralRoleRssi[i].connHandle = GAP_CONNHANDLE_ALL;
  323. gapCentralRoleRssi[i].timerId = INVALID_TIMER_ID;
  324. }
  325. // Initialize parameters
  326. // Retore items from NV
  327. // VOID osal_snv_read( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK );
  328. // VOID osal_snv_read( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK );
  329. // VOID osal_snv_read( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapCentralRoleSignCounter );
  330. // Register for HCI messages (for RSSI)
  331. GAP_RegisterForHCIMsgs( taskId );
  332. }
  333. /**
  334. * @brief Central Profile Task event processing function.
  335. *
  336. * @param taskId - Task ID
  337. * @param events - Events.
  338. *
  339. * @return events not processed
  340. */
  341. uint16 GAPCentralRole_ProcessEvent( uint8 taskId, uint16 events )
  342. {
  343. if ( events & SYS_EVENT_MSG )
  344. {
  345. uint8 *pMsg;
  346. if ( (pMsg = osal_msg_receive( gapCentralRoleTaskId )) != NULL )
  347. {
  348. gapCentralRole_ProcessOSALMsg( (osal_event_hdr_t *) pMsg );
  349. // Release the OSAL message
  350. VOID osal_msg_deallocate( pMsg );
  351. }
  352. // return unprocessed events
  353. return (events ^ SYS_EVENT_MSG);
  354. }
  355. if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED )
  356. {
  357. // Sign counter changed, save it to NV
  358. // VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapCentralRoleSignCounter );
  359. return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED );
  360. }
  361. // Discard unknown events
  362. return 0;
  363. }
  364. /*********************************************************************
  365. * @fn gapCentralRole_ProcessOSALMsg
  366. *
  367. * @brief Process an incoming task message.
  368. *
  369. * @param pMsg - message to process
  370. *
  371. * @return none
  372. */
  373. static void gapCentralRole_ProcessOSALMsg( osal_event_hdr_t *pMsg )
  374. {
  375. switch ( pMsg->event )
  376. {
  377. case HCI_GAP_EVENT_EVENT:
  378. if ( pMsg->status == HCI_COMMAND_COMPLETE_EVENT_CODE )
  379. {
  380. hciEvt_CmdComplete_t *pPkt = (hciEvt_CmdComplete_t *) pMsg;
  381. if ( pPkt->cmdOpcode == HCI_READ_RSSI )
  382. {
  383. uint16 connHandle = BUILD_UINT16( pPkt->pReturnParam[1], pPkt->pReturnParam[2] );
  384. int8 rssi = (int8) pPkt->pReturnParam[3];
  385. // Report RSSI to app
  386. if ( pGapCentralRoleCB && pGapCentralRoleCB->rssiCB )
  387. {
  388. pGapCentralRoleCB->rssiCB( connHandle, rssi );
  389. }
  390. }
  391. }
  392. break;
  393. case GAP_MSG_EVENT:
  394. gapCentralRole_ProcessGAPMsg( (gapEventHdr_t *) pMsg );
  395. break;
  396. case GAPCENTRALROLE_RSSI_MSG_EVT:
  397. {
  398. gapCentralRoleRssi_t *pRssi = ((gapCentralRoleRssiEvent_t *) pMsg)->pRssi;
  399. // If link is up and RSSI reads active
  400. if (pRssi->connHandle != GAP_CONNHANDLE_ALL &&
  401. linkDB_Up(pRssi->connHandle))
  402. {
  403. // Restart timer
  404. osal_CbTimerStart( gapCentralRole_timerCB, (uint8 *) pRssi,
  405. pRssi->period, &pRssi->timerId );
  406. // Read RSSI
  407. VOID HCI_ReadRssiCmd( pRssi->connHandle );
  408. }
  409. }
  410. break;
  411. default:
  412. break;
  413. }
  414. }
  415. /*********************************************************************
  416. * @fn gapCentralRole_ProcessGAPMsg
  417. *
  418. * @brief Process an incoming task message from GAP.
  419. *
  420. * @param pMsg - message to process
  421. *
  422. * @return none
  423. */
  424. static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg )
  425. {
  426. switch ( pMsg->opcode )
  427. {
  428. case GAP_DEVICE_INIT_DONE_EVENT:
  429. {
  430. gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg;
  431. if ( pPkt->hdr.status == SUCCESS )
  432. {
  433. // Save off the generated keys
  434. // VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK );
  435. // VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK );
  436. // Save off the information
  437. VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN );
  438. }
  439. }
  440. break;
  441. case GAP_LINK_ESTABLISHED_EVENT:
  442. {
  443. gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg;
  444. if (pPkt->hdr.status == SUCCESS)
  445. {
  446. // Notify the Bond Manager of the connection
  447. VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr,
  448. pPkt->connectionHandle, GAP_PROFILE_CENTRAL );
  449. }
  450. }
  451. break;
  452. case GAP_LINK_TERMINATED_EVENT:
  453. {
  454. uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle;
  455. VOID GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg );
  456. // Cancel RSSI reads
  457. GAPCentralRole_CancelRssi( connHandle );
  458. }
  459. break;
  460. // temporary workaround
  461. case GAP_SLAVE_REQUESTED_SECURITY_EVENT:
  462. VOID GAPBondMgr_ProcessGAPMsg( pMsg );
  463. break;
  464. default:
  465. break;
  466. }
  467. // Pass event to app
  468. if ( pGapCentralRoleCB && pGapCentralRoleCB->eventCB )
  469. {
  470. pGapCentralRoleCB->eventCB( (gapCentralRoleEvent_t *) pMsg );
  471. }
  472. }
  473. /*********************************************************************
  474. * @fn gapCentralRole_RssiAlloc
  475. *
  476. * @brief Allocate an RSSI structure.
  477. *
  478. * @param connHandle - Connection handle
  479. *
  480. * @return pointer to structure or NULL if allocation failed.
  481. */
  482. static gapCentralRoleRssi_t *gapCentralRole_RssiAlloc( uint16 connHandle )
  483. {
  484. uint8 i;
  485. // Find free RSSI structure
  486. for ( i = 0; i < GAPCENTRALROLE_NUM_RSSI_LINKS; i++ )
  487. {
  488. if ( gapCentralRoleRssi[i].connHandle == GAP_CONNHANDLE_ALL )
  489. {
  490. gapCentralRoleRssi[i].connHandle = connHandle;
  491. return &gapCentralRoleRssi[i];
  492. }
  493. }
  494. // No free structure found
  495. return NULL;
  496. }
  497. /*********************************************************************
  498. * @fn gapCentralRole_RssiFind
  499. *
  500. * @brief Find an RSSI structure.
  501. *
  502. * @param connHandle - Connection handle
  503. *
  504. * @return pointer to structure or NULL if not found.
  505. */
  506. static gapCentralRoleRssi_t *gapCentralRole_RssiFind( uint16 connHandle )
  507. {
  508. uint8 i;
  509. // Find free RSSI structure
  510. for ( i = 0; i < GAPCENTRALROLE_NUM_RSSI_LINKS; i++ )
  511. {
  512. if ( gapCentralRoleRssi[i].connHandle == connHandle )
  513. {
  514. return &gapCentralRoleRssi[i];
  515. }
  516. }
  517. // Not found
  518. return NULL;
  519. }
  520. /*********************************************************************
  521. * @fn gapCentralRole_RssiFree
  522. *
  523. * @brief Free an RSSI structure.
  524. *
  525. * @param connHandle - Connection handle
  526. *
  527. * @return none
  528. */
  529. static void gapCentralRole_RssiFree( uint16 connHandle )
  530. {
  531. uint8 i;
  532. // Find RSSI structure
  533. for ( i = 0; i < GAPCENTRALROLE_NUM_RSSI_LINKS; i++ )
  534. {
  535. if ( gapCentralRoleRssi[i].connHandle == connHandle )
  536. {
  537. gapCentralRoleRssi[i].connHandle = GAP_CONNHANDLE_ALL;
  538. break;
  539. }
  540. }
  541. }
  542. /*********************************************************************
  543. * @fn gapCentralRole_timerCB
  544. *
  545. * @brief OSAL timer callback function
  546. *
  547. * @param pData - Data pointer
  548. *
  549. * @return none
  550. */
  551. static void gapCentralRole_timerCB( uint8 *pData )
  552. {
  553. gapCentralRoleRssiEvent_t *pMsg;
  554. // Timer has expired so clear timer ID
  555. ((gapCentralRoleRssi_t *) pData)->timerId = INVALID_TIMER_ID;
  556. // Send OSAL message
  557. pMsg = (gapCentralRoleRssiEvent_t *) osal_msg_allocate( sizeof(gapCentralRoleRssiEvent_t) );
  558. if ( pMsg )
  559. {
  560. pMsg->hdr.event = GAPCENTRALROLE_RSSI_MSG_EVT;
  561. pMsg->pRssi = (gapCentralRoleRssi_t *) pData;
  562. osal_msg_send ( gapCentralRoleTaskId, (uint8 *) pMsg );
  563. }
  564. }
  565. /*********************************************************************
  566. *********************************************************************/