/**
* ¸Ä±äµÆ¹âµÄº¯Êý£¬phoneStatus ÊÖ»ú״̬£¬isChange ÊÇ·ñ²¥·ÅÇл»Ð§¹û¡£
* phoneStatus = -2 ±íʾ¶ÁÈ¡µ½ÁËcharacteristic1 µÄÊý×éÖµ¡£
* phoneStatus = -1 ±íʾ¶ÁÈ¡µ½ÁËcharacteristic2 µÄÊý×éÖµ¡£
*/
static void dataChange(int8 phoneStatus,uint8 isChange){
      HalLcdWriteStringValue( "phoneStatus +£º", phoneStatus, 10,  HAL_LCD_LINE_7 );
      uint8 newValueBuf[20]={0};
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, newValueBuf );
   
      //Ö»¶ÁÈ¡µ½Êý×é1µÄÊý¾Ý£¬ÏȲ»¸Ä±äµÆ¹âÖ»¼Ç¼ÏÂÀ´£¬µÈÊý×é2µÄÊý¾Ý±»¶Áµ½ºó²Å½øÐеƹâ¸Ä±äµÄ²Ù×÷¡£
      if(phoneStatus == -2){
        //HalLcdWriteStringValue( "Char 1:", newValueBuf[0], 10,  HAL_LCD_LINE_3 );
        init_QI_Switch(newValueBuf[1]);
        return;
      }
      
      uint8 newValueBuf2[20]={0};
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR2, newValueBuf2 );

      //newValueBuf[0] = 1;
      
      if(phoneStatus >=0){
        newValueBuf[0] = phoneStatus;
        //HalLcdWriteStringValue( "change:", newValueBuf[13], 10,  HAL_LCD_LINE_4 );
        //HalLcdWriteStringValue( "change:", newValueBuf[16], 10,  HAL_LCD_LINE_5 );
      }
       HalLcdWriteStringValue( "status:", newValueBuf[0], 10,  HAL_LCD_LINE_6 );
      if(newValueBuf[0] != 16){
        //дÈëµ½flashÖÐ
        osal_snv_write(0x80,20,newValueBuf);
        osal_snv_write(0x95,20,newValueBuf2);
      }
      //¸Ä±äµÈÑÕÉ«
      setValus(newValueBuf,newValueBuf2,isChange);
      LedChange();
}
Beispiel #2
0
/*********************************************************************
 * @fn      gapCentralRole_ProcessGAPMsg
 *
 * @brief   Process an incoming task message from GAP.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg )
{
  switch ( pMsg->opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          // Save off the generated keys
          VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK );
          VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK );

          // Save off the information
          VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN );
        }
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg;

        if (pPkt->hdr.status == SUCCESS)
        {
          // Notify the Bond Manager of the connection
          VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr,
                                   pPkt->connectionHandle, GAP_PROFILE_CENTRAL );
        }
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle;

        GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg );

        // Cancel RSSI reads
        GAPCentralRole_CancelRssi( connHandle );
      }
      break;

    // temporary workaround
    case GAP_SLAVE_REQUESTED_SECURITY_EVENT:
      GAPBondMgr_ProcessGAPMsg( pMsg );
      break;

    default:
      break;
  }

  // Pass event to app
  if ( pGapCentralRoleCB && pGapCentralRoleCB->eventCB )
  {
    pGapCentralRoleCB->eventCB( (gapCentralRoleEvent_t *) pMsg );
  }
}
/*********************************************************************
 * @fn      simpleProfileChangeCB
 *
 * @brief   Callback from SimpleBLEProfile indicating a value change
 *
 * @param   paramID - parameter ID of the value that was changed.
 *
 * @return  none
 */
static void simpleProfileChangeCB( uint8 paramID )
{
  uint8 newValue;

  switch( paramID )
  {
    case SIMPLEPROFILE_CHAR1:
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue );
	  //存储mp,校准是需要重新写入measured power
      osal_snv_write(0xfe,1,&newValue);
	  //通知重启
	  osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );

      #if (defined HAL_LCD) && (HAL_LCD == TRUE)
        HalLcdWriteStringValue( "Char 1:", (uint16)(newValue), 10,  HAL_LCD_LINE_3 );
      #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

      break;
   
    case SIMPLEPROFILE_CHAR3:
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, &newValue );

      #if (defined HAL_LCD) && (HAL_LCD == TRUE)
        HalLcdWriteStringValue( "Char 3:", (uint16)(newValue), 10,  HAL_LCD_LINE_3 );
      #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

      break;

    default:
      // should not reach here!
      break;
  }
}
Beispiel #4
0
/**
 * @brief   Central Profile Task event processing function.
 *
 * @param   taskId - Task ID
 * @param   events - Events.
 *
 * @return  events not processed
 */
uint16 GAPCentralRole_ProcessEvent( uint8 taskId, uint16 events )
{
  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = osal_msg_receive( gapCentralRoleTaskId )) != NULL )
    {
      gapCentralRole_ProcessOSALMsg( (osal_event_hdr_t *) pMsg );

      // Release the OSAL message
      VOID osal_msg_deallocate( pMsg );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED )
  {
    // Sign counter changed, save it to NV
    VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapCentralRoleSignCounter );

    return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED );
  }

  // Discard unknown events
  return 0;
}
void Init_Para(void)
{
    int8 ret8 = osal_snv_read(0x80, sizeof(SYS_CONFIG), &sys_config);
    // 如果该段内存未曾写入过数据, 直接读,会返回 NV_OPER_FAILED ,
    // 我们利用这个特点作为第一次烧录后的运行, 从而设置参数的出厂设置
    if(NV_OPER_FAILED == ret8)
    {
        // 未初始化
        osal_memset(&sys_config, 0, sizeof(SYS_CONFIG));

        sys_config.update_time_ms = TEMP_DEFAULT_UPDATE_TIME_MS;
        sprintf((char*)sys_config.name, DEFAULT_DEVICE_NAME);  // 默认设备名称

        // 最高温度报警
        sys_config.tempeature_hight = DEFAULT_TEMP_HIGHT_ALERT;

        // 最低温度报警
        sys_config.tempeature_low = DEFAULT_TEMP_LOW_ALERT;

        // 4路 pwm 设置, 相对于0xFF 的占空比
        sys_config.pwm[0] = 0;
        sys_config.pwm[1] = 0;
        sys_config.pwm[2] = 255;
        sys_config.pwm[3] = 0;

        g_initFlag = FALSE;
        
        osal_snv_write(0x80, sizeof(SYS_CONFIG), &sys_config);    // 写所有参数
    }
    else
    {
        g_initFlag = TRUE;
    }
}
/*********************************************************************
 * @fn      gapBondMgrChangeState
 *
 * @brief   Change a state flag in the stateFlags field of the bond record.
 *
 * @param   idx - Bond NV index
 * @param   state - state flag to set or clear
 * @param   set - TRUE to set the flag, FALSE to clear the flag
 *
 * @return  TRUE if NV Record exists, FALSE if NV Record is empty
 */
static uint8 gapBondMgrChangeState( uint8 idx, uint16 state, uint8 set )
{
  gapBondRec_t bondRec;   // Space to read a Bond record from NV
  
  // Look for public address that is used (not all 0xFF's)
  if ( (osal_snv_read( mainRecordNvID(idx), sizeof ( gapBondRec_t ), &bondRec ) == SUCCESS) 
      && (osal_isbufset( bondRec.publicAddr, 0xFF, B_ADDR_LEN ) == FALSE) )
  {
    // Update the state of the bonded device.
    uint8 stateFlags = bondRec.stateFlags;
    if ( set )
    {
      stateFlags |= state;
    }
    else
    {
      stateFlags &= ~(state);
    }
    
    if ( stateFlags != bondRec.stateFlags )
    {
      bondRec.stateFlags = stateFlags;
      VOID osal_snv_write( mainRecordNvID(idx), sizeof ( gapBondRec_t ), &bondRec );
    }
    return ( TRUE );
  }
  return ( FALSE );
}
/**
 * @brief   Central Profile Task event processing function.
 *
 * @param   taskId - Task ID
 * @param   events - Events.
 *
 * @return  events not processed
 */
uint16 GAPCentralRole_ProcessEvent( uint8 taskId, uint16 events )
{
  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = osal_msg_receive( gapCentralRoleTaskId )) != NULL )
    {
      gapCentralRole_ProcessOSALMsg( (osal_event_hdr_t *) pMsg );

      // Release the OSAL message
      VOID osal_msg_deallocate( pMsg );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED )
  {
    // Sign counter changed, save it to NV
    VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapCentralRoleSignCounter );

    return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED );
  }

  if ( events & START_ADVERTISING_EVT )
  {
    if ( gapRole_AdvEnabled )
    {
      gapAdvertisingParams_t params;

      // Setup advertisement parameters
      params.eventType = gapRole_AdvEventType;
      params.initiatorAddrType = gapRole_AdvDirectType;
      VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN );
      params.channelMap = gapRole_AdvChanMap;
      params.filterPolicy = gapRole_AdvFilterPolicy;

      if ( GAP_MakeDiscoverable( gapRole_TaskID, &params ) != SUCCESS )
      {
        gapRole_state = GAPROLE_ERROR;
        // Notify the application
        if ( pGapCentralRoleCB && pGapCentralRoleCB->broadcastCB )
        {
          pGapCentralRoleCB->broadcastCB( gapRole_state );
        }
      }
    }

    return ( events ^ START_ADVERTISING_EVT );
  }  
  
  
  
  // Discard unknown events
  return 0;
}
/*********************************************************************
 * @fn      switchImage
 *
 * @brief   Write to BIM's ledger page to signal the other image should be
 *          executed after reset.
 *
 * @param   none
 *
 * @return  VIMS state
 */
static void switchImage(void)
{
  uint8_t id;
  
  // Write Image B's ID so that it will be loaded on reset.
  id = LOAD_IMG_B;
  
  osal_snv_write(NV_ID_IMAGE_EXECUTE, sizeof(uint8_t), &id);
}
/**
 * @brief   Task entry point for the GAP Peripheral Role.
 *
 * @param   a0 - first argument
 * @param   a1 - second argument
 *
 * @return  none
 */
static void gapCentralRole_taskFxn(UArg a0, UArg a1)
{
  // Initialize profile
  gapCentralRole_init();
  
  // Profile main loop
  for (;;)
  {
    // Waits for a signal to the semaphore associated with the calling thread.
    // Note that the semaphore associated with a thread is signaled when a
    // message is queued to the message receive queue of the thread or when
    // ICall_signal() function is called onto the semaphore.
    ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);

    if (errno == ICALL_ERRNO_SUCCESS)
    {
      ICall_EntityID dest;
      ICall_ServiceEnum src;
      ICall_HciExtEvt *pMsg = NULL;
      
      if (ICall_fetchServiceMsg(&src, &dest, 
                                (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
      {
        uint8_t safeToDealloc = TRUE;
              
        if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
        {
          ICall_Event *pEvt = (ICall_Event *)pMsg;
          
          // Check for BLE stack events first
          if (pEvt->signature == 0xffff)
          {
            if (pEvt->event_flag & GAP_EVENT_SIGN_COUNTER_CHANGED)
            {
              // Sign counter changed, save it to NV
              VOID osal_snv_write(BLE_NVID_SIGNCOUNTER, sizeof(uint32_t), 
                                  &gapCentralRoleSignCounter);
            }
          }
          else
          {
            // Process inter-task message
            safeToDealloc = gapCentralRole_processStackMsg((ICall_Hdr *)pMsg);
          }
        }

        if (pMsg && safeToDealloc)
        {
          ICall_freeMsg(pMsg);
        }
      }
    }
  }
}
/*********************************************************************
 * @fn      gapBondMgrAddBond
 *
 * @brief   Save a bond from a GAP Auth Complete Event
 *
 * @param   pBondRec - basic bond record
 * @param   pLocalLTK - LTK used by this device during pairing
 * @param   pDevLTK - LTK used by the connected device during pairing
 * @param   pIRK - IRK used by the connected device during pairing
 * @param   pSRK - SRK used by the connected device during pairing
 * @param   signCounter - Sign counter used by the connected device during pairing
 *
 * @return  bond index
 */
static uint8 gapBondMgrAddBond( gapBondRec_t *pBondRec, 
                                gapBondLTK_t *pLocalLTK, gapBondLTK_t *pDevLTK,
                                uint8 *pIRK, uint8 *pSRK, uint32 signCounter )
{
  uint8 idx;
  
  if ( pBondRec == NULL )
  {
    return ( GAP_BONDINGS_MAX );
  }
  
  // First see if we already have an existing bond for this device
  idx = gapBondMgrFindAddr( pBondRec->publicAddr );
  if ( idx >= GAP_BONDINGS_MAX )
  {
    idx = gapBondMgrFindEmpty();
  }
  
  if ( idx < GAP_BONDINGS_MAX )
  {
    // Save the main information
    VOID osal_snv_write( mainRecordNvID(idx), sizeof ( gapBondRec_t ), pBondRec );

    // If available, save the LTK information    
    if ( pLocalLTK )
    {
      VOID osal_snv_write( localLTKNvID(idx), sizeof ( gapBondLTK_t ), pLocalLTK );
    }
    
    
    // If available, save the connected device's LTK information
    if ( pDevLTK )
    {
      VOID osal_snv_write( devLTKNvID(idx), sizeof ( gapBondLTK_t ), pDevLTK );
    }
    
    // If available, save the connected device's IRK 
    if ( pIRK )
    {
      VOID osal_snv_write( devIRKNvID(idx), KEYLEN, pIRK );
    }
    
    // If available, save the connected device's Signature information 
    if ( pSRK )
    {
      VOID osal_snv_write( devCSRKNvID(idx), KEYLEN, pSRK );
      VOID osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), &signCounter );
    }
  }
  
  // Update the GAP Privacy Flag Properties
  gapBondSetupPrivFlag();
  
  return ( idx );
}
/*********************************************************************
 * @fn      DualImageConcept_handleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys - bit field for key events. Valid entries:
 *                 HAL_KEY_SW_2
 *                 HAL_KEY_SW_1
 *
 * @return  none
 */
static void DualImageConcept_handleKeys(uint8_t shift, uint8_t keys)
{
  (void)shift;  // Intentionally unreferenced parameter

  if (keys & DIC_SWITCH_IMAGE_BUTTON)
  { 
    // Increment and write shared data
    sharedData++;
    osal_snv_write(NV_ID_SHARED_DATA, sizeof(uint8_t), &sharedData);
    
    // Signal a change in images to run.
    switchImage();
    
    // Reset.
    HAL_SYSTEM_RESET();
    
    // Should never get here.
  }
}
Beispiel #12
0
void lock_init(void)
{
  uint8 read_tmp[6] = {0};
  uint8 use_lock_times[2] = {0};
  uint8 ret8;
   
  osal_memset(read_tmp, '0', sizeof(read_tmp));
  ret8 = osal_snv_write(admin_flash_start_addr, sizeof(read_tmp), read_tmp);
  if(ret8 == NV_OPER_FAILED)
     return;

  osal_memset(read_tmp, '1', sizeof(read_tmp));
  ret8 = osal_snv_write(user_flash_start_addr, sizeof(read_tmp), read_tmp);
  if(ret8 == NV_OPER_FAILED)
     return;
    
  osal_memcpy(read_tmp,  ssid,  6);
  ret8 = osal_snv_write(ssid_flash_start_addr, sizeof(read_tmp), read_tmp);
  if(ret8 == NV_OPER_FAILED)
     return;

  osal_memcpy(scanRspData + 2, read_tmp, 6);
  osal_memcpy(attDeviceName, read_tmp, 6);
  GAP_UpdateAdvertisingData( simpleBLEPeripheral_TaskID, FALSE, sizeof( scanRspData ), scanRspData );
  GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName );
   
  osal_memset(read_tmp, '0', sizeof(read_tmp));
  ret8 = osal_snv_write(dead_date_flash_start_addr, sizeof(read_tmp), read_tmp);
  if(ret8 == NV_OPER_FAILED)
    return;
    
  osal_memset(read_tmp, '0', sizeof(read_tmp));
  ret8 = osal_snv_write(carlock_id_flash_start_addr, sizeof(read_tmp), read_tmp);
  if(ret8 == NV_OPER_FAILED)
     return;

  osal_memset(use_lock_times, 0, sizeof(use_lock_times));
  ret8 = osal_snv_write(use_lock_times_start_addr, sizeof(use_lock_times), use_lock_times);
  if(ret8 == NV_OPER_FAILED)
     return; 
  
  HAL_SYSTEM_RESET();//reset
}
/*********************************************************************
 * @fn      gapBondMgrEraseBonding
 *
 * @brief   Write all 0xFF's to the complete bonding record
 *
 * @param   idx - bonding index
 *
 * @return  SUCCESS if successful.
 *          Otherwise, NV_OPER_FAILED for failure.
 */
static bStatus_t gapBondMgrEraseBonding( uint8 idx )
{
  bStatus_t ret;
  gapBondRec_t bondRec;
  gapBondLTK_t ltk;
  
  VOID osal_memset( &bondRec, 0xFF, sizeof ( gapBondRec_t ) );
  VOID osal_memset( &ltk, 0xFF, sizeof ( gapBondLTK_t ) );

  // Write out FF's over the entire bond entry.  
  ret = osal_snv_write( mainRecordNvID(idx), sizeof ( gapBondRec_t ), &bondRec );
  ret |= osal_snv_write( localLTKNvID(idx), sizeof ( gapBondLTK_t ), &ltk );
  ret |= osal_snv_write( devLTKNvID(idx), sizeof ( gapBondLTK_t ), &ltk );
  ret |= osal_snv_write( devIRKNvID(idx), KEYLEN, ltk.LTK );
  ret |= osal_snv_write( devCSRKNvID(idx), KEYLEN, ltk.LTK );
  ret |= osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), ltk.LTK );
  
  // Update the GAP Privacy Flag Properties
  gapBondSetupPrivFlag();
  
  return ( ret );
}
/*********************************************************************
 * @fn      gapRole_ProcessGAPMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
void gapBondMgr_ProcessGAPMsg( gapEventHdr_t *pMsg )
{
  switch ( pMsg->opcode )
  {
    case GAP_PASSKEY_NEEDED_EVENT:
      {
        gapPasskeyNeededEvent_t *pPkt = (gapPasskeyNeededEvent_t *)pMsg;
        
        if ( pGapBondCB && pGapBondCB->passcodeCB )
        {
          // Ask app for a passcode
          pGapBondCB->passcodeCB( pPkt->deviceAddr, pPkt->connectionHandle, pPkt->uiInputs, pPkt->uiOutputs );
        }
        else
        {
          // No app support, use the default passcode
          if ( GAP_PasscodeUpdate( gapBond_Passcode, pPkt->connectionHandle ) != SUCCESS )
          {
            VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_PASSKEY_ENTRY_FAILED );
          }
        }        
      }
      break;
      
    case GAP_AUTHENTICATION_COMPLETE_EVENT:
      {
        gapAuthCompleteEvent_t *pPkt = (gapAuthCompleteEvent_t *)pMsg;
        
        // Should we save bonding information
        if ( (pPkt->hdr.status == SUCCESS) && (pPkt->authState & SM_AUTH_STATE_BONDING) )
        {
          gapBondRec_t bondRec;
          
          VOID osal_memset( &bondRec, 0, sizeof ( gapBondRec_t ) ) ;
          
          // Do we have a public address in the data?
          if ( pPkt->pIdentityInfo )
          {
            VOID osal_memcpy( bondRec.publicAddr, pPkt->pIdentityInfo->bd_addr, B_ADDR_LEN );
          }
          else
          {
            linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle );
            if ( pLinkItem )
            {
              VOID osal_memcpy( bondRec.publicAddr, pLinkItem->addr, B_ADDR_LEN );
            }
            else
            {
              // We don't have an address, so ignore the message.
              break;
            }
          }
          
          // Save off of the authentication state
          bondRec.stateFlags |= (pPkt->authState & SM_AUTH_STATE_AUTHENTICATED) ? GAP_BONDED_STATE_AUTHENTICATED : 0;
          
          VOID gapBondMgrAddBond( &bondRec, 
                             (gapBondLTK_t *)pPkt->pSecurityInfo, 
                             (gapBondLTK_t *)pPkt->pDevSecInfo,
                             ((uint8 *)((pPkt->pIdentityInfo) ? pPkt->pIdentityInfo->irk : NULL )),
                             ((uint8 *)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->srk : NULL )),
                             ((uint32)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->signCounter : GAP_INIT_SIGN_COUNTER )) );
                             
        }
        
        // Call app state callback
        if ( pGapBondCB && pGapBondCB->pairStateCB )
        {
          pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_COMPLETE, pPkt->hdr.status );
        }
      }
      break;
        
    case GAP_BOND_COMPLETE_EVENT:
      // This message is received when the bonding is complete.  If hdr.status is SUCCESS
      // then call app state callback.  If hdr.status is NOT SUCCESS, the connection will be 
      // dropped at the LL because of a MIC failure, so again nothing to do.
      if ( pGapBondCB && pGapBondCB->pairStateCB && pMsg->hdr.status == SUCCESS )
      {
        pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_BONDED, pMsg->hdr.status );
      }  
      break;
      
    case GAP_SIGNATURE_UPDATED_EVENT:
      {
        uint8 idx;
        gapSignUpdateEvent_t *pPkt = (gapSignUpdateEvent_t *)pMsg;
        
        idx = GAPBondMgr_ResolveAddr( pPkt->addrType, pPkt->devAddr, NULL );
        if ( idx < GAP_BONDINGS_MAX )
        {
          // Save the sign counter
          VOID osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), &(pPkt->signCounter) );
        }
      }
      break;
      
    case GAP_PAIRING_REQ_EVENT:
      {
        gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *)pMsg;
        
        if ( gapBond_AutoFail != FALSE )
        {
          // Auto Fail TEST MODE (DON'T USE THIS) - Sends pre-setup reason
          VOID GAP_TerminateAuth( pPkt->connectionHandle, gapBond_AutoFailReason );
        }
        else if ( gapBond_PairingMode == GAPBOND_PAIRING_MODE_NO_PAIRING )
        {
          // No Pairing - Send error
          VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_NOT_SUPPORTED );
        }
        else
        {
          gapAuthParams_t params;
          linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle );
          
          // Requesting bonding?
          if ( pPkt->pairReq.authReq & SM_AUTH_STATE_BONDING )
          {
            if ( pLinkItem ) 
            {
              if ( (pLinkItem->addrType != ADDRTYPE_PUBLIC) && (pPkt->pairReq.keyDist.mIdKey == FALSE) )
              {
                uint8 publicAddr[B_ADDR_LEN];
                
                // Check if we already have the public address in NV
                if ( GAPBondMgr_ResolveAddr(pLinkItem->addrType, pLinkItem->addr, publicAddr ) == FALSE )
                {
                  // Can't bond to a non-public address if we don't know the public address
                  VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_AUTH_REQ );
                  break;
                }
              }
            }
            else
            {
              // Can't find the connection, ignore the message
              break;
            }
          }

          VOID osal_memset( &params, 0, sizeof ( gapAuthParams_t ) );
          
          // Setup the pairing parameters
          params.connectionHandle = pPkt->connectionHandle;
          params.secReqs.ioCaps = gapBond_IOCap;
          params.secReqs.oobAvailable = gapBond_OOBDataFlag;
          params.secReqs.maxEncKeySize = gapBond_KeySize;
          
          // TBD - Should we distribute keys if bonding is turned off???
          params.secReqs.keyDist.sEncKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_SENCKEY) ? TRUE : FALSE;
          params.secReqs.keyDist.sIdKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_SIDKEY) ? TRUE : FALSE;
          params.secReqs.keyDist.mEncKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_MENCKEY) ? TRUE : FALSE;
          params.secReqs.keyDist.mIdKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_MIDKEY) ? TRUE : FALSE;
          params.secReqs.keyDist.mSign = (gapBond_KeyDistList | GAPBOND_KEYDIST_MSIGN) ? TRUE : FALSE;
          params.secReqs.keyDist.sSign = (gapBond_KeyDistList | GAPBOND_KEYDIST_SSIGN) ? TRUE : FALSE;
          
          // Is bond manager setup for OOB data?
          if ( gapBond_OOBDataFlag )
          {
            VOID osal_memcpy( params.secReqs.oob, gapBond_OOBData, KEYLEN );
          }
          
          if ( (pPkt->pairReq.authReq & SM_AUTH_STATE_BONDING) && (gapBond_Bonding) )
          {
            params.secReqs.authReq |= SM_AUTH_STATE_BONDING;
            if ( pLinkItem->addrType != ADDRTYPE_PUBLIC )
            {
              // Force a master ID key 
              params.secReqs.keyDist.mIdKey = TRUE;
            }
          }
          
          // Is Bond Manager setup for passkey protection?
          if ( gapBond_MITM )
          {
            params.secReqs.authReq |= SM_AUTH_STATE_AUTHENTICATED;
          }
          
          VOID GAP_Authenticate( &params, &(pPkt->pairReq) );
        }
        
        // Call app state callback
        if ( pGapBondCB && pGapBondCB->pairStateCB )
        {
          pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_STARTED, pPkt->hdr.status );
        }        
      }
      break;
      
    default:
      break;
  }
}
/*********************************************************************
 * @fn      SimpleBLEPeripheral_Init
 *
 * @brief   Initialization function for the Simple BLE Peripheral App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notificaiton ... ).
 *
 * @param   task_id - the ID assigned by OSAL.  This ID should be
 *                    used to send messages and set timers.
 *
 * @return  none
 */
void SimpleBLEPeripheral_Init( uint8 task_id )
{
  simpleBLEPeripheral_TaskID = task_id;

  // Setup the GAP
  VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL );
  
  // Setup the GAP Peripheral Role Profile
  {
    #if defined( CC2540_MINIDK )
      // For the CC2540DK-MINI keyfob, device doesn't start advertising until button is pressed
      uint8 initial_advertising_enable = FALSE;
    #else
      // For other hardware platforms, device starts advertising upon initialization
      uint8 initial_advertising_enable = TRUE;
    #endif

    // By setting this to zero, the device will go into the waiting state after
    // being discoverable for 30.72 second, and will not being advertising again
    // until the enabler is set back to TRUE
    uint16 gapRole_AdvertOffTime = 0;

    uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST;
    uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
    uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY;
    uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT;

    // Set the GAP Role Parameters
    GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable );
    GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );

    GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );
    GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );

    GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request );
    GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval );
    GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval );
    GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency );
    GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout );
    
    //ÉèÖÃRSSI »ñÈ¡ËÙÂÊ
    uint16 rssi_rate = RSSI_RATE;
    GAPRole_SetParameter(GAPROLE_RSSI_READ_RATE,sizeof(uint16),&rssi_rate);
  }

  // Set the GAP Characteristics
  GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName );

  // Set advertising interval
  {
    uint16 advInt = DEFAULT_ADVERTISING_INTERVAL;

    GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt );
    GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt );
    GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt );
    GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt );
  }

  // Setup the GAP Bond Manager
  {
    uint32 passkey = 0; // passkey "000000"
    uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
    uint8 mitm = TRUE;
    uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
    uint8 bonding = TRUE;
    GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey );
    GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode );
    GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm );
    GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap );
    GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding );
  }

  // Initialize GATT attributes Ìí¼ÓÁË4¸öService ·þÎñ
  GGS_AddService( GATT_ALL_SERVICES );            // GAP
  GATTServApp_AddService( GATT_ALL_SERVICES );    // GATT attributes
  DevInfo_AddService();                           // Device Information Service
  SimpleProfile_AddService( GATT_ALL_SERVICES );  // Simple GATT Profile ankiÐèÒªÐ޸ĵķþÎñ
#if defined FEATURE_OAD
  VOID OADTarget_AddService();                    // OAD Profile
#endif

  // Setup the SimpleProfile Characteristic Values
  {
    //³õʼ»¯±àÒë½øÈ¥µÄµÆ¹âÑÕÉ«
    uint8 charValue1[20] = {0, 1,255,100,100,255,255,255,   20,1,1,255,1,200,    20,100,100,20,100,10};
    uint8 charValue2[20] = {20,1,1,20,1,1,20,1,250,20,1,250,20,1,250,20,1,250,1};
    uint8 charValue3 = 3;
    uint8 charValue4 = 4;
    uint8 charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };
    
     #if (defined HAL_LCD) && (HAL_LCD == TRUE)
      //´ÓÎļþÖжÁÈ¡
      uint8 wirteTag = osal_snv_read(0x80,20,charValue1);
      osal_snv_read(0x95,20,charValue2);
      if( wirteTag == SUCCESS){
          HalLcdWriteStringValue("read Ok",(uint16)wirteTag,10, HAL_LCD_LINE_6 );
      }else{
        HalLcdWriteStringValue("read failed",(uint16)wirteTag,10, HAL_LCD_LINE_6 );
           //½øÐгõʼ»¯
         wirteTag = osal_snv_write(0x80,20,charValue1);
         osal_snv_write(0x95,20,charValue1);
         if(wirteTag == SUCCESS){
            HalLcdWriteStringValue( "init", (uint16)wirteTag, 10,  HAL_LCD_LINE_7 );
         }else{
            HalLcdWriteStringValue("init failed", (uint16)wirteTag,10, HAL_LCD_LINE_7 );
         }
      }
     #else 
      if( osal_snv_read(0x80,20,charValue1) != SUCCESS){
           //½øÐгõʼ»¯
         //osal_snv_write(0x80,20,charValue1);
         //HalLcdWriteStringValue( "rece:", osal_snv_write(0x80,20,charValue1), 10,  HAL_LCD_LINE_8 );
         osal_snv_write(0x95,20,charValue2);
      }
     #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)
    
    
    SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR1, 20, &charValue1 );
    SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR2, 20, &charValue2 );
    SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR3, sizeof ( uint8 ), &charValue3 );
    //Ç°Ãæ3¾äÖ»ÊǶԶÔÏóÖµµÄÉèÖã¬Õâ¾ä´úÂë ½øÐÐÁË£¬ServiceµÄcharacteristicÉèÖã¬Process Client Characteristis Configuration Change
    SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR4, sizeof ( uint8 ), &charValue4 ); 
    SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5 );
  }


#if defined( CC2540_MINIDK )

  SK_AddService( GATT_ALL_SERVICES ); // Simple Keys Profile

  // Register for all key events - This app will handle all key events¡£ ×¢²á°´Å¥Ê¼þ£¬OSAL´¦Àí°´Å¥Ê¼þ
  RegisterForKeys( simpleBLEPeripheral_TaskID );

  // makes sure LEDs are off
  HalLedSet( (HAL_LED_1 | HAL_LED_2), HAL_LED_MODE_OFF );



#endif // #if defined( CC2540_MINIDK )

#if (defined HAL_LCD) && (HAL_LCD == TRUE)

#if defined FEATURE_OAD
  #if defined (HAL_IMAGE_A)
    HalLcdWriteStringValue( "BLE Peri-A", OAD_VER_NUM( _imgHdr.ver ), 16, HAL_LCD_LINE_1 );
  #else
    HalLcdWriteStringValue( "BLE Peri-B", OAD_VER_NUM( _imgHdr.ver ), 16, HAL_LCD_LINE_1 );
  #endif // HAL_IMAGE_A
#else
  HalLcdWriteString( "BLE Peripheral", HAL_LCD_LINE_1 );
#endif // FEATURE_OAD

#endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

  // Register callback with SimpleGATTprofile
  // ¸Ã»Øµ÷±» simpleProfile_WriteAttrCB ·½·¨´¥·¢£¬simpleProfileCBs °üº¬´Ë·½·¨£¬ÔÚSimpleProfile_AddService µÄʱºò×¢²áµ½GATTЭÒéÕ»·þÎñÖÐ
  //Öµ¸Ä±äÖ®ºó£¬Í¨Öª PROFILES--->SimpleProfileCBs.simpleProfile_WriteAttrCB  È»ºóÔÙ֪ͨAPP--->simpleBLEPeripheral_SimpleProfileCBs
  VOID SimpleProfile_RegisterAppCBs( &simpleBLEPeripheral_SimpleProfileCBs );

  // Enable clock divide on halt
  // This reduces active current while radio is active and CC254x MCU
  // is halted
  //²»É¾³ý  PWM²»Îȶ¨
  //HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT );

#if defined ( DC_DC_P0_7 )

  // Enable stack to toggle bypass control on TPS62730 (DC/DC converter)
  HCI_EXT_MapPmIoPortCmd( HCI_EXT_PM_IO_PORT_P0, HCI_EXT_PM_IO_PORT_PIN7 );

#endif // defined ( DC_DC_P0_7 )

  // Setup a delayed profile startup  ·¢ÆðBLEÁ¬½Ó³õʼ»¯Ïà¹Ø·þÎñ¡£ÏÂÃæ·½·¨¶Ô SBP_START_DEVICE_EVT ʼþ½øÐд¦Àí
  osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );

}
/*********************************************************************
 * @brief   Task Event Processor function.
 *
 * Internal function defined in peripheral.h.
 */
uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events )
{
  VOID task_id; // OSAL required parameter that isn't used in this function
  
  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL )
    {
      gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );

      // Release the OSAL message
      VOID osal_msg_deallocate( pMsg );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED )
  {
    // Sign counter changed, save it to NV
    VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter );

    return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED );
  }
  
  if ( events & START_ADVERTISING_EVT )
  {
    if ( gapRole_AdvEnabled )
    {
      gapAdvertisingParams_t params;

      // Setup advertisement parameters
      if ( gapRole_state == GAPROLE_CONNECTED )
      {
        // While in a connection, we can only advertise non-connectable undirected.
        params.eventType = GAP_ADTYPE_ADV_NONCONN_IND;
      }
      else
      {
        params.eventType = gapRole_AdvEventType;
        params.initiatorAddrType = gapRole_AdvDirectType;
        VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN );
      }
      params.channelMap = gapRole_AdvChanMap;
      params.filterPolicy = gapRole_AdvFilterPolicy;

      if ( GAP_MakeDiscoverable( gapRole_TaskID, &params ) != SUCCESS )
      {
        gapRole_state = GAPROLE_ERROR;
        if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
        {
          pGapRoles_AppCGs->pfnStateChange( gapRole_state );
        }
      }
    }
    return ( events ^ START_ADVERTISING_EVT );
  }

  if ( events & RSSI_READ_EVT )
  {
    // Only get RSSI when in a connection
    if ( (gapRole_state == GAPROLE_CONNECTED)
        || (gapRole_state == GAPROLE_CONNECTED_ADV) )
    {
      // Ask for RSSI
      VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle );

      // Setup next event
      if ( gapRole_RSSIReadRate )
      {
        VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
      }
    }
    return ( events ^ RSSI_READ_EVT );
  }

  if ( events & UPDATE_PARAMS_TIMEOUT_EVT )
  {
    // Clear an existing timeout
    if ( osal_get_timeoutEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ) )
    {
      VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT );
    }

    // The Update Parameters Timeout occurred - Terminate connection
    VOID GAP_TerminateLinkReq( gapRole_TaskID, gapRole_ConnectionHandle, 
                               HCI_DISCONNECT_REMOTE_USER_TERM );

    return ( events ^ UPDATE_PARAMS_TIMEOUT_EVT );
  }

  // Discard unknown events
  return 0;
}
/*********************************************************************
 * @fn      gapRole_ProcessGAPMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg )
{
  uint8 notify = FALSE;   // State changed notify the app? (default no)

  switch ( pMsg->opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
        bStatus_t stat = pPkt->hdr.status;

        if ( stat == SUCCESS )
        {
          // Save off the generated keys
          VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK );
          VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );
          
          // Save off the information
          VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN );

          gapRole_state = GAPROLE_STARTED;

          // Update the advertising data
          stat = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
        }

        if ( stat != SUCCESS )
        {
          gapRole_state = GAPROLE_ERROR;
        }

        notify = TRUE;
      }
      break;

    case GAP_ADV_DATA_UPDATE_DONE_EVENT:
      {
        gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pPkt->adType )
          {
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData );
          }
          else
          {
            // Start advertising
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }

        if ( pPkt->hdr.status != SUCCESS )
        {
          // Set into Error state
          gapRole_state = GAPROLE_ERROR;
          notify = TRUE;
        }
      }
      break;

    case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
    case GAP_END_DISCOVERABLE_DONE_EVENT:
      {
        gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
          {
            if ( gapRole_state == GAPROLE_CONNECTED )
            {
              gapRole_state = GAPROLE_CONNECTED_ADV;
            }
            else
            {
              gapRole_state = GAPROLE_ADVERTISING;
            }
          }
          else // GAP_END_DISCOVERABLE_DONE_EVENT
          {
            
            if ( gapRole_AdvertOffTime != 0 )
            {
              if ( ( gapRole_AdvEnabled ) )
              {
                VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime );
              }
            }
            else
            {            
              // Since gapRole_AdvertOffTime is set to 0, the device should not
              // automatically become discoverable again after a period of time.
              // Set enabler to FALSE; device will become discoverable again when
              // this value gets set to TRUE
              gapRole_AdvEnabled = FALSE;
            }

            // In the Advertising Off period
            gapRole_state = GAPROLE_WAITING;

          }
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN );
          gapRole_ConnectionHandle = pPkt->connectionHandle;
          gapRole_state = GAPROLE_CONNECTED;

          if ( gapRole_RSSIReadRate )
          {
            // Start the RSSI Reads
            VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
          }

          // Check whether update parameter request is enabled, and check the connection parameters
          if ( ( gapRole_ParamUpdateEnable == TRUE ) &&
               ( (pPkt->connInterval < gapRole_MinConnInterval) ||
                 (pPkt->connInterval > gapRole_MaxConnInterval) ||
                 (pPkt->connLatency != gapRole_SlaveLatency)    ||
                 (pPkt->connTimeout != gapRole_TimeoutMultiplier) ))
          {
            gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency );
          }
          
          // Notify the Bond Manager to the connection
          VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL );  
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        VOID GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg );
        osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN );
        
        if ( gapRole_state == GAPROLE_CONNECTED_ADV )
        {
          // End the non-connectable advertising
          GAP_EndDiscoverable( gapRole_TaskID );
          gapRole_state = GAPROLE_CONNECTED;
        }
        else
        {
          gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;
          if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM )
          {
            gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT;
          }
          else
          {
            gapRole_state = GAPROLE_WAITING;
          }

          notify = TRUE;

          VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
        }

        gapRole_ConnectionHandle = INVALID_CONNHANDLE;
      }
      break;

    case GAP_LINK_PARAM_UPDATE_EVENT:
      {
        gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;

        if ( (pPkt->hdr.status != SUCCESS)
            || (pPkt->connInterval < gapRole_MinConnInterval)
              || (pPkt->connInterval > gapRole_MaxConnInterval) )
        {
          // Ask to change the interval
          gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency );
        }
        else
        {
          // All is good stop Update Parameters timeout
          VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT );
        }
      }
      break;
      
    default:
      break;
  }

  if ( notify == TRUE )
  {
    // Notify the application
    if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
    {
      pGapRoles_AppCGs->pfnStateChange( gapRole_state );
    }
  }
}
/*********************************************************************
 * @fn      gapRole_processGAPMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static uint8_t gapRole_processGAPMsg(gapEventHdr_t *pMsg) {
	uint8_t notify = FALSE;   // State changed notify the app? (default no)

	switch (pMsg->opcode) {
	case GAP_DEVICE_INIT_DONE_EVENT: {
		gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg;
		bStatus_t stat = pPkt->hdr.status;

		if (stat == SUCCESS) {
			// Save off the generated keys
			VOID osal_snv_write(BLE_NVID_IRK, KEYLEN, gapRole_IRK);
			VOID osal_snv_write(BLE_NVID_CSRK, KEYLEN, gapRole_SRK);

			// Save off the information
			VOID memcpy(gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN);

			gapRole_peripheralState = GAPROLE_STARTED;
			gapRole_peripheralStateChangeHandler(gapRole_peripheralState);

			// Update the advertising data
			stat = GAP_UpdateAdvertisingData(selfEntity,
			TRUE, gapRole_AdvertDataLen, gapRole_AdvertData);
		}

		if (stat != SUCCESS) {
			gapRole_peripheralState = GAPROLE_ERROR;
			gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
			//gapRole_abort();
		}

		notify = TRUE;
	}
		break;

	case GAP_ADV_DATA_UPDATE_DONE_EVENT: {
		gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *) pMsg;

        if (pPkt->hdr.status == SUCCESS)
        {
          if (pPkt->adType)
          {
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData);
          }
          else if ((gapRole_peripheralState != GAPROLE_ADVERTISING)   &&
                   (gapRole_peripheralState != GAPROLE_CONNECTED_ADV) &&
                   (gapRole_peripheralState != GAPROLE_CONNECTED ||
                    gapRole_AdvNonConnEnabled == TRUE)      &&
                   (Util_isActive(&startAdvClock) == FALSE))
          {
            // Start advertising
            gapRole_setEvent(START_ADVERTISING_EVT);
          }
          notify = FALSE;
        }else {
			// Set into Error state
			gapRole_peripheralState = GAPROLE_ERROR;
			gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
			//gapRole_abort();
			notify = TRUE;
		}
	}
		break;

	case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
	case GAP_END_DISCOVERABLE_DONE_EVENT: {
		gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *) pMsg;

		if (pPkt->hdr.status == SUCCESS) {
			if (pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT) {
				if (gapRole_peripheralState == GAPROLE_CONNECTED) {
					gapRole_peripheralState = GAPROLE_CONNECTED_ADV;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				} else if (gapRole_AdvEnabled) {
					gapRole_peripheralState = GAPROLE_ADVERTISING;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				} else {
					gapRole_peripheralState = GAPROLE_ADVERTISING_NONCONN;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				}
			} else // GAP_END_DISCOVERABLE_DONE_EVENT
			{
				if (gapRole_AdvertOffTime != 0) //restart advertising if param is set
						{
					if ((gapRole_AdvEnabled) || (gapRole_AdvNonConnEnabled)) {
						Util_restartClock(&startAdvClock, gapRole_AdvertOffTime);
					}
				} else {
					// Since gapRole_AdvertOffTime is set to 0, the device should not
					// automatically become discoverable again after a period of time.
					// Set enabler to FALSE; device will become discoverable again when
					// this value gets set to TRUE
					if (gapRole_AdvEnabled == TRUE) {
						gapRole_AdvEnabled = FALSE;
					} else {
						gapRole_AdvNonConnEnabled = FALSE;
					}
				}

				// Update state.
				if (gapRole_peripheralState == GAPROLE_CONNECTED_ADV) {
					// In the Advertising Off period
					gapRole_peripheralState = GAPROLE_CONNECTED;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				} else {
					// In the Advertising Off period
					gapRole_peripheralState = GAPROLE_WAITING;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				}
			}
			notify = TRUE;
		} else if (pPkt->hdr.status == LL_STATUS_ERROR_COMMAND_DISALLOWED) //we're already advertising
		{
			notify = FALSE;
		} else {
			gapRole_peripheralState = GAPROLE_ERROR;
			gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
			//gapRole_abort();
		}
	}
		break;

	case GAP_LINK_ESTABLISHED_EVENT: {
		gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg;

		if (pPkt->hdr.status == SUCCESS) {
			//add to database
			gapRoleInfo_Add(pPkt);

			// advertising will stop when a connection forms in the peripheral role
			if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) {

				gapRole_peripheralState = GAPROLE_CONNECTED;
				gapRole_peripheralStateChangeHandler(gapRole_peripheralState);

				// Check whether update parameter request is enabled
				if (gapRole_ParamUpdateEnable == TRUE) {
						// Get the minimum time upon connection establishment before the
						// peripheral can start a connection update procedure.
						uint16_t timeout = GAP_GetParamValue(
						TGAP_CONN_PAUSE_PERIPHERAL);

						Util_restartClock(&startUpdateClock, timeout * 1000);

				}
			}
			// Notify the Bond Manager to the connection
			VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, pPkt->connRole);
		} else if (pPkt->hdr.status == bleGAPConnNotAcceptable) {
			// Set enabler to FALSE; device will become discoverable again when
			// this value gets set to TRUE
			gapRole_AdvEnabled = FALSE;

	        // Go to WAITING state, and then start advertising
			if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) {
				gapRole_peripheralState = GAPROLE_WAITING;
				gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
			}
		} else {
			if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) {
				gapRole_peripheralState = GAPROLE_ERROR;
				gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
			} else {
				gapRole_abort();
			}
		}
		notify = TRUE;
	}
		break;

	case GAP_LINK_TERMINATED_EVENT: {
		gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *) pMsg;

		// notify bond manager
		GAPBondMgr_LinkTerm(pPkt->connectionHandle);

		// Erase connection information (maybe make this a function)
		uint8 connHandleIndex = gapRoleInfo_Find(pPkt->connectionHandle);
		multiConnInfo[connHandleIndex].gapRole_ConnectionHandle = INVALID_CONNHANDLE;
		multiConnInfo[connHandleIndex].gapRole_ConnInterval = 0;
		multiConnInfo[connHandleIndex].gapRole_ConnSlaveLatency = 0;
		multiConnInfo[connHandleIndex].gapRole_ConnTimeout = 0;

		// Cancel all connection parameter update timers (if any active)
		Util_stopClock(&startUpdateClock);
		Util_stopClock(&updateTimeoutClock);

		notify = TRUE;

		if (multiConnInfo[connHandleIndex].gapRole_ConnRole == GAP_PROFILE_PERIPHERAL) {
			// If device was advertising when connection dropped
			if (gapRole_AdvNonConnEnabled) {
				// Continue advertising.
				gapRole_peripheralState = GAPROLE_ADVERTISING_NONCONN;
				gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
			}
			// Else go to WAITING state.
			else {
				if (pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM) {
					gapRole_peripheralState = GAPROLE_WAITING_AFTER_TIMEOUT;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				} else {
					gapRole_peripheralState = GAPROLE_WAITING;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
				}

				// Start advertising, if enabled.
				gapRole_setEvent(START_ADVERTISING_EVT);
			}
		}
	}
		break;

	case GAP_LINK_PARAM_UPDATE_EVENT: {
		gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *) pMsg;

		// Cancel connection param update timeout timer (if active)
		Util_stopClock(&updateTimeoutClock);

		if (pPkt->hdr.status == SUCCESS) {
			// Store new connection parameters
//              gapRole_ConnInterval = pPkt->connInterval;
//              gapRole_ConnSlaveLatency = pPkt->connLatency;
//              gapRole_ConnTimeout = pPkt->connTimeout;

			// Make sure there's no pending connection update procedure
			if (Util_isActive(&startUpdateClock) == FALSE) {
//                // Notify the application with the new connection parameters
//                if (pGapRoles_ParamUpdateCB != NULL)
//                {
//                  (*pGapRoles_ParamUpdateCB)(gapRole_ConnInterval,
//                                             gapRole_ConnSlaveLatency,
//                                             gapRole_ConnTimeout);
//                }
			}
		}
		notify = TRUE;
	}
		break;

	case GAP_PAIRING_REQ_EVENT: {
		gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *) pMsg;

		// Send Pairing Failed Response
		VOID GAP_TerminateAuth(pPkt->connectionHandle,
		SMP_PAIRING_FAILED_NOT_SUPPORTED);
	}
		break;

	case GAP_SLAVE_REQUESTED_SECURITY_EVENT: {
        uint16_t connHandle = ((gapSlaveSecurityReqEvent_t *)pMsg)->connectionHandle;
        uint8_t authReq = ((gapSlaveSecurityReqEvent_t *)pMsg)->authReq;

        GAPBondMgr_SlaveReqSecurity(connHandle, authReq);
	}
		break;

	case GAP_DEVICE_INFO_EVENT:
	case GAP_DEVICE_DISCOVERY_EVENT:
		notify = TRUE;
		break;

	default:
		notify = FALSE;
		break;
	}

	if (notify == TRUE) //app needs to take further action
	{
		if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnPassThrough) {
			return (pGapRoles_AppCGs->pfnPassThrough((gapMultiRoleEvent_t *) pMsg));
		}
	}

	return TRUE;

}
/*********************************************************************
 * @fn      simpleProfileChangeCB
 *
 * @brief   Callback from SimpleBLEProfile indicating a value change
 *
 * @param   paramID - parameter ID of the value that was changed.
 *
 * @return  none
 */
static void simpleProfileChangeCB( uint8 paramID )
{
  uint8 newValue[20];
  uint8 returnBytes; 

  switch( paramID )
  {
    case SIMPLEPROFILE_CHAR1:  // 收到 CHAR1 的数据
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue, &returnBytes);

      #if (defined HAL_LCD) && (HAL_LCD == TRUE)
        HalLcdWriteStringValue( "Char 1:", (uint16)(newValue[0]), 10,  HAL_LCD_LINE_5 );
      #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

      
      HalLedBlink (HAL_LED_1, 1, 50, 100);//这个的意思是, 100ms内,以50%的占空比闪烁1次, 实际就是点亮50ms  
     break;

    case SIMPLEPROFILE_CHAR5: // 收到 CHAR5 的数据
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR5, &newValue, &returnBytes);

      #if (defined HAL_LCD) && (HAL_LCD == TRUE)
        HalLcdWriteStringValue( "Char 5[0]:", (uint16)(newValue[0]), 16,  HAL_LCD_LINE_5 );
        HalLcdWriteStringValue( "Char 5[1]:", (uint16)(newValue[1]), 16,  HAL_LCD_LINE_6 );
        HalLcdWriteStringValue( "Char 5[2]:", (uint16)(newValue[2]), 16,  HAL_LCD_LINE_7 );
        HalLcdWriteStringValue( "Char 5[3]:", (uint16)(newValue[3]), 16,  HAL_LCD_LINE_8 );
      #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

      // 设定温度更新时间, 注意高位在前  
      if(returnBytes == 4)
      {
        sys_config.update_time_ms = (uint32)newValue[0]<<24 | (uint32)newValue[1]<<16| (uint32)newValue[2]<<8| (uint32)newValue[3]; 
        osal_snv_write(0x80, sizeof(SYS_CONFIG), &sys_config);    // 写所有参数

        if(sys_config.update_time_ms > 0)
        {
            osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_READ_SENSOR_EVT, sys_config.update_time_ms);
        }
        else
        {
            osal_stop_timerEx( simpleBLEPeripheral_TaskID, SBP_READ_SENSOR_EVT);
        }
      }


        HalLedBlink (HAL_LED_2, 1, 50, 100);//这个的意思是, 100ms内,以50%的占空比闪烁1次, 实际就是点亮50ms  

      break;

    case SIMPLEPROFILE_CHAR6:  // 这个是我们添加char6, 用于做串口透传 与从机 notify 数据到主机 很合适
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR6, &newValue, &returnBytes);

      {
        char str[21]={0};
        char str2[32]={0};

        osal_memcpy(str, newValue, returnBytes);
        sprintf(str2,"Char 6: %s", str);
      #if (defined HAL_LCD) && (HAL_LCD == TRUE)
        HalLcdWriteString(str2,  HAL_LCD_LINE_6 );
      #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)        

        // 通过串口透传出去,达到透传目的,amo家的透传就是使用 CHAR6
        NPI_WriteTransport(newValue, returnBytes);

        HalLedBlink (HAL_LED_3, 1, 50, 100);//这个的意思是, 100ms内,以50%的占空比闪烁1次, 实际就是点亮50ms  
      }

      break;

    case SIMPLEPROFILE_CHAR7: // 收到 CHAR7 的数据
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR7, &newValue, &returnBytes);
      osal_memset(sys_config.name, 0, sizeof(sys_config.name));
      osal_memcpy(sys_config.name, newValue, returnBytes);
      osal_snv_write(0x80, sizeof(SYS_CONFIG), &sys_config);    // 写所有参数
      
      HalLcdWriteString( "Char 7 Set", HAL_LCD_LINE_4 );
      HalLcdWriteString( (char*)sys_config.name, HAL_LCD_LINE_5 );
      // 需要重启后设备名生效
      break;

    case SIMPLEPROFILE_CHAR8: // 收到 CHAR8 的数据
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR8, &newValue, &returnBytes);

      // 最高温度报警
      sys_config.tempeature_hight = newValue[0]<<8;
      sys_config.tempeature_hight |= newValue[1];
      
      // 最低温度报警
      sys_config.tempeature_low = newValue[2]<<8;
      sys_config.tempeature_low |= newValue[3];
      break;

    case SIMPLEPROFILE_CHAR9: // adc 只读
      break;

    case SIMPLEPROFILE_CHARA: // // pwm
      SimpleProfile_GetParameter( SIMPLEPROFILE_CHARA, &newValue, &returnBytes);

      #if (defined HAL_LCD) && (HAL_LCD == TRUE)
        HalLcdWriteStringValue( "Char A[0]:", (uint16)(newValue[0]), 16,  HAL_LCD_LINE_5 );
        HalLcdWriteStringValue( "Char A[1]:", (uint16)(newValue[1]), 16,  HAL_LCD_LINE_6 );
        HalLcdWriteStringValue( "Char A[2]:", (uint16)(newValue[2]), 16,  HAL_LCD_LINE_7 );
        HalLcdWriteStringValue( "Char A[3]:", (uint16)(newValue[3]), 16,  HAL_LCD_LINE_8 );
      #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

      // 设定pwm
      if(returnBytes == 4)
      {
          sys_config.pwm[3] = newValue[0]; // 白色
          sys_config.pwm[2] = newValue[1]; // 红色
          sys_config.pwm[1] = newValue[2]; // 绿色
          sys_config.pwm[0] = newValue[3]; // 蓝色

          osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_SET_PWM_EVT, 50);
      }

      break;

    default:
      // should not reach here!
      break;
  }
}
/*
Command sets, chosen options need to be stored in non-volatile memory
- SC,<value>  + set connection mode of device
+ <value> is a single digit number
+ 1 Do not auto-connect to last paired, 2 auto-connect to last paired
- SN,<value>  + set device name
+ <value> device's new name
- S,R Reset the device
- S,D Set device to be discoverable
- S,DC  Disconnect device from host
*/
static void processCommands(void) {
  //buf: Testing variables
  uint8 *buf = rxBuffer;
  buf[rxBufferIndex] = 0;
  
  if(rxBuffer[0] == 'K') { //keyboard commands
    if(rxBufferIndex == 3) {
      //printf("Keyboard key press and release\r\n");
      if(rxBuffer[1] == 'U') {
        //Key released
        KBD_Report_RemoveKey(rxBuffer[2]);
      } else if(rxBuffer[1] == 'D') {
        //Key pressed 
        KBD_Report_AddKey(rxBuffer[2]);
      }
    } else { //command as KS maybe, for Keyboard-report Send
      //printf("Sending report...\r\n");
      KBD_Report_Update();
    }
  } else if(rxBuffer[0] == 'M') { //mouse commands
    //printf("Mouse commands\r\n");
    hidKbdMouseSendMouseReport(rxBuffer[1], rxBuffer[2], rxBuffer[3], rxBuffer[4]);
  } else if(rxBuffer[0] == 'S') { //setting commands
    //printf("Setting commands\r\n");
    if((rxBuffer[1] == 'C') && (rxBuffer[2] == ',')) {
      //TO-DO: SET CONNECTION MODE
      //printf("Connection modes\r\n");
    } else if((rxBuffer[1] == 'N') && (rxBuffer[2] == ',')) {
      uint8 i;
      uint8 deviceNewName[20];
      uint8 deviceNewNameLength;
      uint8 deviceNewNameCRC;
      
      deviceNewNameLength = rxBufferIndex-3;
      if(deviceNewNameLength > 20) {
        printf("Name exceeds permitted length\r\n");
      } else {
        for(i = 3; i < rxBufferIndex; i++) {
          deviceNewName[i-3] = rxBuffer[i];
        }   
        deviceNewName[deviceNewNameLength] = '\0';
        deviceNewNameCRC = getCRC(deviceNewName, deviceNewNameLength);
        
        osal_snv_write(SNV_ID_DEVICE_NAME, 20, deviceNewName);
        osal_snv_write(SNV_ID_DEVICE_NAME_LENGTH, 1, &deviceNewNameLength);
        osal_snv_write(SNV_ID_DEVICE_NAME_CRC, 1, &deviceNewNameCRC);
        //        printf("Name is being set, reset to set new name\r\n");
      }
    } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'R')) {
      //reset the device
      HAL_SYSTEM_RESET();
    } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'D')) {
      if(rxBuffer[3] == 'C') {
        //disconnect the device from host
        //printf("Disconnecting from host...\r\n");
        GAPRole_TerminateConnection();
      } else {
        //set device to be discoverable
        //printf("Set deveice to be discoverable\r\n");
      }
    } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'S')) {
      //enable sleep mode
      printf("SLEEP\r\n");
      sleepModeEnabled = 1;
      sleepMode();
    } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'A')) {
      //disable sleep mode
      printf("ACTIVE\r\n");
      sleepModeEnabled = 0;
      activeMode();
    } 
  }   
  
  //after processing, reset rxBuffer and its index
  memset(rxBuffer, 0, 8);
  rxBufferIndex = 0;
}
/***************************************************************************************************
 * @fn      Uart_Msg_Save_QST_NUM
 *
 * @brief   Uart_Msg_Save_QST_NUM
 *
 * @param   None
 *
 * @return  None
 ***************************************************************************************************/
bool Uart_Msg_Save_QST_NUM( void )
{
	osal_snv_write(BLE_NVID_DEV_B, sizeof(SERIAL_NUM), gSerial_Num+DEV_B);
    have_save_qst_imei = true;
	return true;	
}
Beispiel #22
0
/*********************************************************************
 * @brief   Task Event Processor function.
 *
 * Internal function defined in peripheral.h.
 */
uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events )
{
  VOID task_id; // OSAL required parameter that isn't used in this function

  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL )
    {
      gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );

      // Release the OSAL message
      VOID osal_msg_deallocate( pMsg );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED )
  {
    // Sign counter changed, save it to NV
    VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter );

    return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED );
  }

  if ( events & START_ADVERTISING_EVT )
  {
    if ( gapRole_AdvEnabled )
    {
      gapAdvertisingParams_t params;

      // Setup advertisement parameters
      params.eventType = gapRole_AdvEventType;
      params.initiatorAddrType = gapRole_AdvDirectType;
      VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN );
      params.channelMap = gapRole_AdvChanMap;
      params.filterPolicy = gapRole_AdvFilterPolicy;

      if ( GAP_MakeDiscoverable( gapRole_TaskID, &params ) != SUCCESS )
      {
        gapRole_state = GAPROLE_ERROR;
        
        // Notify the application with the new state change
        if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
        {
          pGapRoles_AppCGs->pfnStateChange( gapRole_state );
        }
      }
    }
    return ( events ^ START_ADVERTISING_EVT );
  }

  if ( events & RSSI_READ_EVT )
  {
    // Only get RSSI when in a connection
    if ( gapRole_state == GAPROLE_CONNECTED )
    {
      // Ask for RSSI
      VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle );

      // Setup next event
      if ( gapRole_RSSIReadRate )
      {
        VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
      }
    }
    return ( events ^ RSSI_READ_EVT );
  }

  if ( events & START_CONN_UPDATE_EVT )
  {
    // Start connection update procedure
    gapRole_startConnUpdate( GAPROLE_NO_ACTION );

    return ( events ^ START_CONN_UPDATE_EVT );
  }
  
  if ( events & CONN_PARAM_TIMEOUT_EVT )
  {
    // Unsuccessful in updating connection parameters
    gapRole_HandleParamUpdateNoSuccess();

    return ( events ^ CONN_PARAM_TIMEOUT_EVT );
  }
  
  // Discard unknown events
  return 0;
}
Beispiel #23
0
/*********************************************************************
 * @fn      gapRole_ProcessGAPMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg )
{
  uint8 notify = FALSE;   // State changed notify the app? (default no)

  switch ( pMsg->opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
        bStatus_t stat = pPkt->hdr.status;

        if ( stat == SUCCESS )
        {
          // Save off the generated keys
          VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK );
          VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );

          // Save off the information
          VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN );

          gapRole_state = GAPROLE_STARTED;

          // Update the advertising data
          stat = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
        }

        if ( stat != SUCCESS )
        {
          gapRole_state = GAPROLE_ERROR;
        }

        notify = TRUE;
      }
      break;

    case GAP_ADV_DATA_UPDATE_DONE_EVENT:
      {
        gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pPkt->adType )
          {
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData );
          }
          else
          {
            // Start advertising
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }

        if ( pPkt->hdr.status != SUCCESS )
        {
          // Set into Error state
          gapRole_state = GAPROLE_ERROR;
          notify = TRUE;
        }
      }
      break;

    case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
    case GAP_END_DISCOVERABLE_DONE_EVENT:
      {
        gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
          {
            gapRole_state = GAPROLE_ADVERTISING;
          }
          else // GAP_END_DISCOVERABLE_DONE_EVENT
          {

            if ( gapRole_AdvertOffTime != 0 )
            {
              if ( ( gapRole_AdvEnabled ) )
              {
                VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime );
              }
            }
            else
            {
              // Since gapRole_AdvertOffTime is set to 0, the device should not
              // automatically become discoverable again after a period of time.
              // Set enabler to FALSE; device will become discoverable again when
              // this value gets set to TRUE
              gapRole_AdvEnabled = FALSE;
            }

            // In the Advertising Off period
            gapRole_state = GAPROLE_WAITING;

          }
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN );
          gapRole_ConnectionHandle = pPkt->connectionHandle;
          gapRole_state = GAPROLE_CONNECTED;

          if ( gapRole_RSSIReadRate )
          {
            // Start the RSSI Reads
            VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
          }

          // Store connection information
          gapRole_ConnInterval = pPkt->connInterval;
          gapRole_ConnSlaveLatency = pPkt->connLatency;
          gapRole_ConnTimeout = pPkt->connTimeout;

          // Check whether update parameter request is enabled
          if ( gapRole_ParamUpdateEnable == TRUE )
          {
            // Get the minimum time upon connection establishment before the 
            // peripheral can start a connection update procedure.
            uint16 timeout = GAP_GetParamValue( TGAP_CONN_PAUSE_PERIPHERAL );
            
            osal_start_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT, timeout*1000 );
          }

          // Notify the Bond Manager to the connection
          VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL );
        }
        else if ( pPkt->hdr.status == bleGAPConnNotAcceptable )
        {
          // Set enabler to FALSE; device will become discoverable again when
          // this value gets set to TRUE
          gapRole_AdvEnabled = FALSE;

          // Go to WAITING state, and then start advertising
          gapRole_state = GAPROLE_WAITING;
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;

        GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg );
        osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN );

        // Erase connection information
        gapRole_ConnInterval = 0;
        gapRole_ConnSlaveLatency = 0;
        gapRole_ConnTimeout = 0;

        // Cancel all connection parameter update timers (if any active)
        VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT );
        VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT );
          
        // Go to WAITING state, and then start advertising
        if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM )
        {
          gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT;
        }
        else
        {
          gapRole_state = GAPROLE_WAITING;
        }

        notify = TRUE;

        VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );

        gapRole_ConnectionHandle = INVALID_CONNHANDLE;
      }
      break;

    case GAP_LINK_PARAM_UPDATE_EVENT:
      {
        gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;

        // Cancel connection param update timeout timer (if active)
        VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT );
        
        if ( pPkt->hdr.status == SUCCESS )
        {
          // Store new connection parameters
          gapRole_ConnInterval = pPkt->connInterval;
          gapRole_ConnSlaveLatency = pPkt->connLatency;
          gapRole_ConnTimeout = pPkt->connTimeout;
          
          // Make sure there's no pending connection update procedure
          if ( osal_get_timeoutEx( gapRole_TaskID, START_CONN_UPDATE_EVT ) == 0 )
          {
            // Notify the application with the new connection parameters
            if ( pGapRoles_ParamUpdateCB != NULL )
            {
              (*pGapRoles_ParamUpdateCB)( gapRole_ConnInterval, 
                                          gapRole_ConnSlaveLatency, 
                                          gapRole_ConnTimeout );
            }
          }
        }
      }
      break;

    default:
      break;
  }

  if ( notify == TRUE )
  {
    // Notify the application with the new state change
    if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
    {
      pGapRoles_AppCGs->pfnStateChange( gapRole_state );
    }
  }
}
/**************************************************************************************************
 * @fn      HalMotionHandleMeasurementStartEvent
 *
 * @brief   Handles event indicating a new 10 msec measurement cycle has begun,
 *          so we should start taking samples.
 *
 * @param   None
 *
 * @return  None
 **************************************************************************************************/
static void HalMotionHandleMeasurementStartEvent( void )
{
  if (HalMotionState == HAL_MOTION_STATE_WAITING_FOR_NEXT_MEASUREMENT)
  {
    int16 x, y, z;
#if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE)
    int8 ax, ay, az;
#endif

    /* Update state */
    HalMotionState = HAL_MOTION_STATE_MEASURING;

    HalGyroRead(&x, &y, &z );

    samples.GyroSamples.X = x;
    samples.GyroSamples.Y = -y;
    samples.GyroSamples.Z = z;

    /* Done with Gyro samples, now get Accelerometer samples */
#if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE)
    HalGyroReadAccelData( &ax, &ay, &az );
    samples.AccSamples.X = ax;
    samples.AccSamples.Y = ay;
    samples.AccSamples.Z = -az;
#endif

    /* Done with samples, so call Movea library routine to process them */
    motion_status = AIR_MOTION_ProcessDelta(samples);

    /* Update state */
    HalMotionState = HAL_MOTION_STATE_WAITING_FOR_NEXT_MEASUREMENT;

    if (motion_status.Status.IsDeltaComputed)
    {
      /* Avalid delta was computed                 */
      /* Inform application that results are ready */
      if (pHalMotionProcessFunction != NULL)
      {
        pHalMotionProcessFunction( motion_status.Delta.X,
                                   motion_status.Delta.Y );
      }
    }
  }
  else if (HalMotionCalibrateGyro == TRUE && HalMotionState == HAL_MOTION_STATE_POWERING_ON)
  {
    // Currently calibrating
    int16 x, y, z;
#if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE)
    int8 ax, ay, az;
#endif

    HalMotionState = HAL_MOTION_STATE_MEASURING;

    HalGyroRead( &x, &y, &z );

    samples.GyroSamples.X = x;
    samples.GyroSamples.Y = -y;
    samples.GyroSamples.Z = z;

    /* Done with Gyro samples, now get Accelerometer samples */
#if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE)
    HalGyroReadAccelData( &ax, &ay, &az );
    samples.AccSamples.X = ax;
    samples.AccSamples.Y = ay;
    samples.AccSamples.Z = -az;
#endif

    /* Done with samples, so call Movea library routine to process them */
    motion_status = AIR_MOTION_ProcessDelta(samples);

    if (motion_status.Status.NewGyroOffset == true)
    {
      // Found a new valid gyro offset
      HalMotionGyroOffsets.x = motion_status.GyroOffsets.X;
      HalMotionGyroOffsets.y = motion_status.GyroOffsets.Y;
      HalMotionGyroOffsets.z = motion_status.GyroOffsets.Z;

      /* Store gyro offsets in NVM */
      (void) osal_snv_write( HAL_MOTION_NV_ITEM_GYRO_OFFSETS_ID,
                             sizeof( HalMotionGyroOffsets ),
                            (uint8 *)&HalMotionGyroOffsets );

      /* Power down motion hardware and go back to initial state */
      HalMotionDisable();

      /* Inform application that calibration is done */
      if (pHalMotionCalCompleteNotificationFunction != NULL)
      {
        pHalMotionCalCompleteNotificationFunction();
      }
    }
    else if (HalNbSamplesCalCnt == 0)
    {
      // Too many attempts ==> Reset the cal process:
      if (pHalMotionCalCompleteNotificationFunction != NULL)
      {
        /* Inform application that the current calibration is still valid */
        pHalMotionCalCompleteNotificationFunction();
      }
      HalMotionDisable();
    }
    else
    {
      HalNbSamplesCalCnt--;
      /* Update state */
      HalMotionState = HAL_MOTION_STATE_POWERING_ON;
    }
  }
}
Beispiel #25
0
/*********************************************************************
 * @fn      simpleProfile_WriteAttrCB
 *
 * @brief   Validate attribute data prior to a write operation
 *
 * @param   connHandle - connection message was received on
 * @param   pAttr - pointer to attribute
 * @param   pValue - pointer to data to be written
 * @param   len - length of data
 * @param   offset - offset of the first octet to be written
 * @param   complete - whether this is the last packet
 * @param   oper - whether to validate and/or write attribute value  
 *
 * @return  Success or Failure
 */
static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                                 uint8 *pValue, uint8 len, uint16 offset )
{
  bStatus_t status = SUCCESS;
  uint8 notifyApp = 0xFF;
  
  // If attribute permissions require authorization to write, return error
  if ( gattPermitAuthorWrite( pAttr->permissions ) )
  {
    // Insufficient authorization
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );
  }
  
  if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  {
    // 16-bit UUID
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
    switch ( uuid )
    {
      case SIMPLEPROFILE_CHAR1_UUID:
        //Validate the value
        // Make sure it's not a blob oper
        if ( offset == 0 )
        {
          if ( len != 16 )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }
        
        //Write the value
        if ( status == SUCCESS )
        {

          uint8 beaconID[] = {
            pValue[0],pValue[1],pValue[2],pValue[3],pValue[4],pValue[5],pValue[6],pValue[7],
            pValue[8],pValue[9],pValue[10],pValue[11],pValue[12],pValue[13],pValue[14],pValue[15]
          };
          VOID osal_snv_write(BEACON_ID, BEACON_LEN, &beaconID);
          SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, &beaconID );
          /*VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN );
          if( pAttr->pValue == simpleProfileChar1 )
          {
            notifyApp = SIMPLEPROFILE_CHAR1;        
          }*/
        }
             
        break;
      case SIMPLEPROFILE_CHAR2_UUID:
        //Validate the value
        // Make sure it's not a blob oper
        if ( offset == 0 )
        {
          if ( len != 4 )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }
        
        //Write the value
        if ( status == SUCCESS )
        {

          uint8 major[] = {
            pValue[0],pValue[1],pValue[2],pValue[3],pValue[4],pValue[5],pValue[6],pValue[7],
            pValue[8],pValue[9],pValue[10],pValue[11],pValue[12],pValue[13],pValue[14],pValue[15]
          };
          VOID osal_snv_write(MAJOR_ID, MAJOR_LEN, &major);
          SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, &major );
          /*VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR2_LEN );
          if( pAttr->pValue == simpleProfileChar2 )
          {
            notifyApp = SIMPLEPROFILE_CHAR2;        
          }*/
        }
             
        break;
      case SIMPLEPROFILE_CHAR3_UUID:
        //Validate the value
        // Make sure it's not a blob oper
        if ( offset == 0 )
        {
          if ( len != 1 )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }
        
        //Write the value
        if ( status == SUCCESS )
        {

          uint8 power[] = {
            pValue[0]
          };
          VOID osal_snv_write(POWER_ID, POWER_LEN, &power);
        }
             
        break;
        
        case SIMPLEPROFILE_CHAR4_UUID:
        //Validate the value
        // Make sure it's not a blob oper
        if ( offset == 0 )
        {
          if ( len != 1 )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }
        
        //Write the value
        if ( status == SUCCESS )
        {

          if (pValue[0] == 0xFA)
          {
            HAL_SYSTEM_RESET();
          }
        }
             
        break;

      case GATT_CLIENT_CHAR_CFG_UUID:
        status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                 offset, GATT_CLIENT_CFG_NOTIFY );
        break;
        
      default:
        // Should never get here! (characteristics 2 and 4 do not have write permissions)
        status = ATT_ERR_ATTR_NOT_FOUND;
        break;
    }
  }
  else
  {
    // 128-bit UUID
    status = ATT_ERR_INVALID_HANDLE;
  }

  // If a charactersitic value changed then callback function to notify application of change
  if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  {
    simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );  
  }
  
  return ( status );
}
Beispiel #26
0
/*********************************************************************
 * @fn      gapRole_taskFxn
 *
 * @brief   Task entry point for the GAP Peripheral Role.
 *
 * @param   a0 - first argument
 * @param   a1 - second argument
 *
 * @return  none
 */
static void gapRole_taskFxn(UArg a0, UArg a1)
{  
  // Initialize profile
  gapRole_init();
  
  // Profile main loop
  for (;;)
  {
    // Waits for a signal to the semaphore associated with the calling thread.
    // Note that the semaphore associated with a thread is signaled when a
    // message is queued to the message receive queue of the thread or when
    // ICall_signal() function is called onto the semaphore.
    ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);

    if (errno == ICALL_ERRNO_SUCCESS)
    {
      ICall_EntityID dest;
      ICall_ServiceEnum src;
      ICall_HciExtEvt *pMsg = NULL;
      
      if (ICall_fetchServiceMsg(&src, &dest, 
                                (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
      {
        uint8_t safeToDealloc = TRUE;
        
        if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
        {
          ICall_Stack_Event *pEvt = (ICall_Stack_Event *)pMsg;
          
          // Check for BLE stack events first
          if (pEvt->signature == 0xffff)
          {
            if (pEvt->event_flag & GAP_EVENT_SIGN_COUNTER_CHANGED)
            {
              // Sign counter changed, save it to NV
              VOID osal_snv_write(BLE_NVID_SIGNCOUNTER, sizeof(uint32_t), 
                                  &gapRole_signCounter);
            }
          }
          else
          {
            // Process inter-task message
            safeToDealloc = gapRole_processStackMsg((ICall_Hdr *)pMsg);
          }
        }

        if (pMsg && safeToDealloc)
        {
          ICall_freeMsg(pMsg);
        }
      }
    }

    if (events & START_ADVERTISING_EVT)
    { 
      events &= ~START_ADVERTISING_EVT;
      
      if (gapRole_AdvEnabled || gapRole_AdvNonConnEnabled)
      {
        gapAdvertisingParams_t params;

        // Setup advertisement parameters
        if (gapRole_AdvNonConnEnabled)
        {
          // Only advertise non-connectable undirected.
          params.eventType = GAP_ADTYPE_ADV_NONCONN_IND;
        }
        else
        {
          params.eventType = gapRole_AdvEventType;
          params.initiatorAddrType = gapRole_AdvDirectType;
          VOID memcpy(params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN);
        }
        
        params.channelMap = gapRole_AdvChanMap;
        params.filterPolicy = gapRole_AdvFilterPolicy;

        if (GAP_MakeDiscoverable(selfEntity, &params) != SUCCESS)
        {
          gapRole_abort();
        }
      }
    }
    if (events & CONN_PARAM_TIMEOUT_EVT)
    {
      events &= ~CONN_PARAM_TIMEOUT_EVT;

      // Unsuccessful in updating connection parameters
      gapRole_HandleParamUpdateNoSuccess();
    }    
  } // for
}
/*********************************************************************
 * @fn      gapCentralRole_ProcessGAPMsg
 *
 * @brief   Process an incoming task message from GAP.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg )
{
  
  uint8 isBroadcastMsg = FALSE;
  
  switch ( pMsg->opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg;
        bStatus_t stat = pPkt->hdr.status;
        
        if ( pPkt->hdr.status == SUCCESS )
        {
          // Save off the generated keys
          VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK );
          VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK );

          // Save off the information
          VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN );
          
         ///////////////////////////////////////////////////////////////////////
         // Broadcast

          // Save off the information
          VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN );

          gapRole_state = GAPROLE_STARTED;

          // Update the advertising data
          stat =GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE,
                                            gapRole_AdvertDataLen,
                                            gapRole_AdvertData );
        }
        
        if ( stat != SUCCESS )
        {
          gapRole_state = GAPROLE_ERROR;
        }
        
        isBroadcastMsg = TRUE;        
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg;

        if (pPkt->hdr.status == SUCCESS)
        {
          // Notify the Bond Manager of the connection
          VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr,
                                   pPkt->connectionHandle, GAP_PROFILE_CENTRAL );
        }
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle;

        GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg );

        // Cancel RSSI reads
        GAPCentralRole_CancelRssi( connHandle );
      }
      break;

    // temporary workaround
    case GAP_SLAVE_REQUESTED_SECURITY_EVENT:
      GAPBondMgr_ProcessGAPMsg( pMsg );
      break;

    case GAP_ADV_DATA_UPDATE_DONE_EVENT:
      {
        gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pPkt->adType )
          {
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData );
          }
          else
          {
            // Start advertising
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }

        if ( pPkt->hdr.status != SUCCESS )
        {
          // Set into Error state
          gapRole_state = GAPROLE_ERROR;
          isBroadcastMsg = TRUE;
        }
      }
      break;

    case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
    case GAP_END_DISCOVERABLE_DONE_EVENT:
      {
        gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
          {
            gapRole_state = GAPROLE_ADVERTISING;
          }
          else // GAP_END_DISCOVERABLE_DONE_EVENT
          {

            if ( gapRole_AdvertOffTime != 0 )
            {
              if ( ( gapRole_AdvEnabled ) )
              {
                VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime );
              }
            }
            else
            {
              // Since gapRole_AdvertOffTime is set to 0, the device should not
              // automatically become discoverable again after a period of time.
              // Set enabler to FALSE; device will become discoverable again when
              // this value gets set to TRUE
              gapRole_AdvEnabled = FALSE;
            }

            // In the Advertising Off period
            gapRole_state = GAPROLE_WAITING;

          }
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        isBroadcastMsg = TRUE;
      }
      break;
      
    default:
      break;
  }
  
  // If a broadcast event, pass to broadcast callback.
  if ( isBroadcastMsg == TRUE )
  {
    // Notify the application
    if ( pGapCentralRoleCB && pGapCentralRoleCB->broadcastCB )
    {
      pGapCentralRoleCB->broadcastCB( gapRole_state );
    }
  }
  // Otherwise pass to central callback
  else if ( pGapCentralRoleCB && pGapCentralRoleCB->centralCB )
  {
    pGapCentralRoleCB->centralCB( (gapCentralRoleEvent_t *) pMsg );
  }
  
}
Beispiel #28
0
/***************************************************************************************************
 * @fn      BLE_set_par
 *
 * @brief   BLE_set_par
 *
 * @param   None
 *
 * @return  None
 ***************************************************************************************************/
void BLE_set_par( uint8 *buffer)
{
	NPI_PrintValue("set par",0);
	uint8 par_num = *buffer++;
	
	while(par_num)
	{
		switch(*buffer)
		{
	 	  case ID_PAR_DOWN_PULSE:
	 	  {
			ble_parameter.down_pulse_max = *(buffer+2);
			buffer += 3;
			NPI_PrintValue("d pulse",ble_parameter.down_pulse_max);
	 	  }
	      break;
		  
		  case ID_PAR_UP_PULSE:
	 	  {
			ble_parameter.up_pulse_max = *(buffer+2);
			buffer += 3;
			NPI_PrintValue("u pulse",ble_parameter.up_pulse_max);
	 	  }
	      break;
		  
		  case ID_PAR_ADV_POLICY:
	 	  {
			ble_parameter.adv_policy = *(buffer+2);
			buffer += 3;
			NPI_PrintValue("adv p",ble_parameter.adv_policy);
	 	  }
	      break;
		  
		  case ID_PAR_ADV_TIME:
	 	  {
			ble_parameter.adv_time = *(buffer+2);
			buffer += 3;
			NPI_PrintValue("adv_time",ble_parameter.adv_time);
	 	  }
	      break;
          
          case ID_PAR_ABNORMAL_TIME:
	 	  {
			buffer += 6;
	 	  }
	      break;
          
          case ID_PAR_ABNORMAL_POLICY:
	 	  {
			buffer += 3;
	 	  }
	      break;
		  
		  default:
			buffer += 1;
			break;
		}
		par_num--;
	}
	
	//save par to NV
	osal_snv_write(BLE_NVID_PAR, sizeof(BLE_PARAMETER), &ble_parameter);
	
	BLE_Set_Parameter();
	
}
/***************************************************************************************************
 * @fn      Uart_Msg_Parse
 *
 * @brief   parse uart Msg,this msg was came from e009 uart
 *
 * @param   pBuffer: msg; length: msg length
 *
 * @return  None
 ***************************************************************************************************/
bool Uart_Msg_Parse(uint8* pBuffer, uint8 length)
{
    bool ret = TRUE;
    
    // pBuffer[0] = MSG_IDENTIFICATION;pBuffer[1]=msd id
    switch(pBuffer[1])
    {
        case ID_E0092BLE_G_RSP:
		    last_uart_send.msg_buffer[0] = 0;
            break;
			
        case ID_E0092BLE_TIME:
            BLE_Common_Response(ID_E0092BLE_TIME,RSP_OK);
		    uart_pulse_timeout_count = 0;
            Set_Ble_Time(pBuffer+3); 
            break;
			
        case ID_E0092BLE_REBOOT_BLE: 
            BLE_Common_Response(ID_E0092BLE_REBOOT_BLE,RSP_OK);
            BLE_Reboot();
            break;
			
        case ID_E0092BLE_IMEI:
            BLE_Common_Response(ID_E0092BLE_IMEI,RSP_OK);
			//gE009_ready = true;
            //osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_E009_READY, 250 );
			osal_memcpy(gSerial_Num[DEV_B].imei,pBuffer+3,SERIAl_NUM_LEN);
            break;
			
        case ID_E0092BLE_IMSI:
            BLE_Common_Response(ID_E0092BLE_IMSI,RSP_OK);
			gE009_ready = true;
			waiting_e009_powerup = false;
            osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_E009_READY, 250 );
			osal_memcpy(gSerial_Num[DEV_B].imsi,pBuffer+3,SERIAl_NUM_LEN);
			Uart_Msg_Save_QST_NUM();
            break;         
           
         case ID_E0092BLE_BAT:     //QST E009 to BLE
            BLE_Common_Response(ID_E0092BLE_BAT,RSP_OK);
			sys_config.battery = *(pBuffer+3);
			osal_snv_write(BLE_NVID_SYS_CONF, sizeof(SYS_CONFIG), &sys_config);
			BLE_SEND_BAT_TO_HWJ();
            break;

        case ID_E0092BLE_START_E009:
            BLE_Common_Response(ID_E0092BLE_START_E009,RSP_OK);
			BLE_Powerup_QST_E009(true);
            break;  
			
        case ID_E0092BLE_POWEROFF:  //QST E009 to BLE,power off himself
            BLE_Common_Response(ID_E0092BLE_POWEROFF,RSP_OK);
			BLE_Powerup_QST_E009(false);
            break;  
			
        case ID_E0092BLE_REBOOT_OTHER:  //HWJ reboot QST, QST reboot HWJ
            BLE_Common_Response(ID_E0092BLE_REBOOT_OTHER,RSP_OK);
            BLE_Reboot_Other();
            break;   
			
        case ID_E0092BLE_STATE:
			E009_state = *(pBuffer+3);
			if(E009_state == E009_STATE_SLEEP)
			{
				Save_E009_powerup_time( pBuffer+4 );
			}
			BLE_Common_Response(ID_E0092BLE_STATE,E009_state);
            break;   			
			
        case ID_E0092BLE_START_ADV:    //QST E009 to BLE, start advertising
            BLE_Common_Response(ID_E0092BLE_START_ADV,RSP_OK);
            BLE_start_adv();
            break;   	
			
        case ID_E0092BLE_PAR:
		    e009_abnormal_parameter.time = *(pBuffer+21);
			if(*(pBuffer+20) > 0 || *(pBuffer+19) > 0 || *(pBuffer+18) > 0)
				e009_abnormal_parameter.time = 240;
			
			AbnormalDelayBootE009Count = 2*e009_abnormal_parameter.time;
			
			e009_abnormal_parameter.policy = *(pBuffer+24);
			if(e009_abnormal_parameter.policy != 0)
			  	e009_abnormal_parameter.policy = 1;
			
			osal_snv_write(BLE_NVID_PAR_ABNORMAL, sizeof(E009_ABNORMAL_PARAMETER), &e009_abnormal_parameter);
			BLE_Common_Response(ID_E0092BLE_PAR,RSP_OK);
			//BLE_set_par( pBuffer+3 );
            break;  
			
        case ID_E0092BLE_REBOOT:
            BLE_Common_Response(ID_E0092BLE_REBOOT,RSP_OK);
			BLE_Reboot_E009();
            break;  
            
        default:    
            ret = FALSE;            
            break;
    }                 
    
    return ret;
}
Beispiel #30
0
/*********************************************************************
 * @fn      gapRole_processGAPMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static uint8_t gapRole_processGAPMsg(gapEventHdr_t *pMsg)
{
  uint8_t notify = FALSE;   // State changed notify the app? (default no)

  switch (pMsg->opcode)
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
        bStatus_t stat = pPkt->hdr.status;

        if (stat == SUCCESS)
        {
          // Save off the generated keys
          VOID osal_snv_write(BLE_NVID_IRK, KEYLEN, gapRole_IRK);
          VOID osal_snv_write(BLE_NVID_CSRK, KEYLEN, gapRole_SRK);

          // Save off the information
          VOID memcpy(gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN);

          // Update the advertising data
          stat = GAP_UpdateAdvertisingData(selfEntity,
                              TRUE, gapRole_AdvertDataLen, gapRole_AdvertData);
        }

        if (stat != SUCCESS)
        {
          gapRole_abort();
        }

        notify = TRUE;
      }
      break;

    case GAP_ADV_DATA_UPDATE_DONE_EVENT:
      {
        gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;

        if (pPkt->hdr.status == SUCCESS)
        {
          if (pPkt->adType)
          {
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData);
          }
          else if (Util_isActive(&startAdvClock) == FALSE)
          {
            // Start advertising
            gapRole_setEvent(START_ADVERTISING_EVT);
          }
        }

        if (pPkt->hdr.status != SUCCESS)
        {
          // Set into Error state
          gapRole_abort();
          notify = TRUE;
        }
      }
      break;

    case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
    case GAP_END_DISCOVERABLE_DONE_EVENT:
      {
        gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;

        if (pPkt->hdr.status == SUCCESS)
        {
          if (pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
          {
            gapRole_AdvEnabled = TRUE;
          }
          else // GAP_END_DISCOVERABLE_DONE_EVENT
          {
            if (gapRole_AdvertOffTime != 0) //restart advertising if param is set
            {
              if ((gapRole_AdvEnabled) || (gapRole_AdvNonConnEnabled))
              {
                Util_restartClock(&startAdvClock, gapRole_AdvertOffTime);
              }
            }
            else
            {
              // Since gapRole_AdvertOffTime is set to 0, the device should not
              // automatically become discoverable again after a period of time.
              // Set enabler to FALSE; device will become discoverable again when
              // this value gets set to TRUE
              if (gapRole_AdvEnabled == TRUE)
              {
                gapRole_AdvEnabled = FALSE;
              }
            }
          }
          notify = TRUE;
        }
        else if (pPkt->hdr.status == LL_STATUS_ERROR_COMMAND_DISALLOWED) //we're already advertising
        {
          notify = FALSE;
        }
        else
        {
          gapRole_abort();
        }
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;
        uint8_t advertEnable = TRUE;

        if (pPkt->hdr.status == SUCCESS)
        {
          // Notify the Bond Manager to the connection
          VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr,
                                  pPkt->connectionHandle, pPkt->connRole);    

          //advertising will stop after connection formed as slave
          if ((pPkt->connRole) == GAP_PROFILE_PERIPHERAL)
          {
            gapRole_AdvEnabled = FALSE;
            //reenable advertising
            GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                                 &advertEnable, NULL);            
          }
        }
        else if (pPkt->hdr.status == bleGAPConnNotAcceptable)
        {
          // Set enabler to FALSE; device will become discoverable again when
          // this value gets set to TRUE
          gapRole_AdvEnabled = FALSE;
        }
        else
        {
          gapRole_abort();
        }
        
        notify = TRUE;
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;

        linkDBInfo_t pInfo;
        linkDB_GetInfo(pPkt->connectionHandle, &pInfo);
        
        // notify bond manager
        GAPBondMgr_LinkTerm(pPkt->connectionHandle);

        notify = TRUE;
      }
      break;

    case GAP_SLAVE_REQUESTED_SECURITY_EVENT:
      {
        uint16_t connHandle = ((gapSlaveSecurityReqEvent_t *)pMsg)->connectionHandle;
        uint8_t authReq = ((gapSlaveSecurityReqEvent_t *)pMsg)->authReq;
        
        GAPBondMgr_SlaveReqSecurity(connHandle, authReq);
      }
      break;     
      
    case GAP_LINK_PARAM_UPDATE_EVENT:
      {
        gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;
        
        // Cancel connection param update timeout timer (if active)
        Util_stopClock(&updateTimeoutClock);
        
        if (pPkt->hdr.status == SUCCESS)
        {
          notify = TRUE;
        }
      }
      break;
      
    default:
      notify = TRUE;
      break;
  }

  if (notify == TRUE) //app needs to take further action
  {
    if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnPassThrough)
    {
      return (pGapRoles_AppCGs->pfnPassThrough((gapMultiRoleEvent_t *)pMsg));
    }
  }
  
  return TRUE;
    
}