/*********************************************************************
 * @fn      OADTarget_getNextBlockReq
 *
 * @brief   Process the Request for next image block.
 *
 * @param   connHandle - connection message was received on
 * @param   blkNum - block number to request from OAD Manager.
 *
 * @return  None
 */
static void OADTarget_getNextBlockReq(uint16_t connHandle, uint16_t blkNum)
{
  uint16_t value = GATTServApp_ReadCharCfg(connHandle, oadImgBlockConfig);

  // If notifications enabled
  if (value & GATT_CLIENT_CFG_NOTIFY)
  {
    attHandleValueNoti_t noti;
    
    noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI, 2, NULL);
    
    if (noti.pValue != NULL)
    {
      gattAttribute_t *pAttr = GATTServApp_FindAttr(oadAttrTbl, 
                                                    GATT_NUM_ATTRS(oadAttrTbl),
                                                    oadCharVals+OAD_CHAR_IMG_BLOCK);
      noti.handle = pAttr->handle;
      noti.len = 2;
      
      noti.pValue[0] = LO_UINT16(blkNum);
      noti.pValue[1] = HI_UINT16(blkNum);
      
      if (GATT_Notification(connHandle, &noti, FALSE) != SUCCESS)
      {
        GATT_bm_free((gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI);
      }
    }
  }
}
Exemplo n.º 2
0
/*********************************************************************
 * @fn      SimplePropBeacon_freeAttRsp
 *
 * @brief   Free ATT response message.
 *
 * @param   status - response transmit status
 *
 * @return  none
 */
static void SimplePropBeacon_freeAttRsp(uint8_t status)
{
  // See if there's a pending ATT response message
  if (pAttRsp != NULL)
  {
    // See if the response was sent out successfully
    if (status == SUCCESS)
    {
      Display_print1(dispHandle, 5, 0, "Rsp sent retry: %d", rspTxRetry);
    }
    else
    {
      // Free response payload
      GATT_bm_free(&pAttRsp->msg, pAttRsp->method);

      Display_print1(dispHandle, 5, 0, "Rsp retry failed: %d", rspTxRetry);
    }

    // Free response message
    ICall_freeMsg(pAttRsp);

    // Reset our globals
    pAttRsp = NULL;
    rspTxRetry = 0;
  }
}
/*********************************************************************
 * @fn      OADTarget_rejectImage
 *
 * @brief   Reject the Image identified by the OAD manager, send back
 *          active image version, length and UID to manager.
 *
 * @param   connHandle - connection message was received on.
 * @param   pImgHdr    - pointer to the img_hdr_t data to send.
 *
 * @return  None.
 */
static void OADTarget_rejectImage(uint16_t connHandle, img_hdr_t *pImgHdr)
{
  uint16_t value = GATTServApp_ReadCharCfg(connHandle, oadImgIdentifyConfig);

  // If notifications enabled
  if (value & GATT_CLIENT_CFG_NOTIFY)
  {
    attHandleValueNoti_t noti;
    
    noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI, 8, NULL);
    
    if (noti.pValue != NULL)
    {
      gattAttribute_t *pAttr = GATTServApp_FindAttr(oadAttrTbl,
                                                    GATT_NUM_ATTRS(oadAttrTbl),
                                                    oadCharVals+OAD_CHAR_IMG_IDENTIFY);
      noti.handle = pAttr->handle;
      noti.len = OAD_IMG_HDR_SIZE;
      
      noti.pValue[0] = LO_UINT16(pImgHdr->ver);
      noti.pValue[1] = HI_UINT16(pImgHdr->ver);

      noti.pValue[2] = LO_UINT16(pImgHdr->len);
      noti.pValue[3] = HI_UINT16(pImgHdr->len);

      (void)memcpy(noti.pValue+4, pImgHdr->uid, sizeof(pImgHdr->uid));

      if (GATT_Notification(connHandle, &noti, FALSE) != SUCCESS)
      {
        GATT_bm_free((gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI);
      }
    }
  }
}
Exemplo n.º 4
0
uint8 glucoseCtlPntWrite(uint8 opcode, uint8 oper)
{
  attWriteReq_t writeReq;
  uint8 status;
  
  writeReq.pValue = GATT_bm_alloc(glucCollConnHandle, ATT_WRITE_REQ,
                                  GLUCOSE_CTL_PNT_LEN, NULL);
  if (writeReq.pValue != NULL)
  {
    writeReq.pValue[0] = opcode;
    writeReq.pValue[1] = oper;
    
    writeReq.len = GLUCOSE_CTL_PNT_LEN;
    writeReq.sig = 0;
    writeReq.cmd = 0;
    
    writeReq.handle = glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_START];
    
    // Send the write request
    status = GATT_WriteCharValue( glucCollConnHandle, &writeReq, glucCollTaskId );
    if (status != SUCCESS)
    {
      GATT_bm_free((gattMsg_t *)&writeReq, ATT_WRITE_REQ);
    }
  }
  else
  {
    status = bleMemAllocError;
  }
  
  return status;
}
Exemplo n.º 5
0
/*********************************************************************
 * @fn          battNotifyCB
 *
 * @brief       Send a notification of the level state characteristic.
 *
 * @param       connHandle - linkDB item
 *
 * @return      None.
 */
static void battNotifyCB( linkDBItem_t *pLinkItem )
{
  if ( pLinkItem->stateFlags & LINK_CONNECTED )
  {
    uint16 value = GATTServApp_ReadCharCfg( pLinkItem->connectionHandle,
                                            battLevelClientCharCfg );
    if ( value & GATT_CLIENT_CFG_NOTIFY )
    {
      attHandleValueNoti_t noti;

      noti.pValue = GATT_bm_alloc( pLinkItem->connectionHandle,
                                   ATT_HANDLE_VALUE_NOTI,
                                   BATT_LEVEL_VALUE_LEN, NULL );
      if ( noti.pValue != NULL )
      {
        noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
        noti.len = BATT_LEVEL_VALUE_LEN;
        noti.pValue[0] = battLevel;

        if ( GATT_Notification( pLinkItem->connectionHandle, &noti, FALSE ) != SUCCESS )
        {
          GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
        }
      }
    }
  }
}
Exemplo n.º 6
0
/*********************************************************************
 * @fn      timeAppProcessGattMsg
 *
 * @brief   Process GATT messages
 *
 * @return  none
 */
static void timeAppProcessGattMsg( gattMsgEvent_t *pMsg )
{
  if ( pMsg->method == ATT_HANDLE_VALUE_NOTI ||
       pMsg->method == ATT_HANDLE_VALUE_IND )
  {
    timeAppIndGattMsg( pMsg );
  }
  else if ( ( pMsg->method == ATT_READ_RSP || pMsg->method == ATT_WRITE_RSP ) ||
            ( pMsg->method == ATT_ERROR_RSP &&
              ( pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ ||
                pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ ) ) )
  {
    timeAppConfigState = timeAppConfigGattMsg ( timeAppConfigState, pMsg );
    if ( timeAppConfigState == TIMEAPP_CONFIG_CMPL )
    {
      timeAppDiscoveryCmpl = TRUE;
    }
  }
  else
  {
    timeAppDiscState = timeAppDiscGattMsg( timeAppDiscState, pMsg );
    if ( timeAppDiscState == DISC_IDLE )
    {      
      // Start characteristic configuration
      timeAppConfigState = timeAppConfigNext( TIMEAPP_CONFIG_START );
    }
  }
  
  GATT_bm_free( &pMsg->msg, pMsg->method );
}
Exemplo n.º 7
0
/*********************************************************************
 * @fn      ScanParam_RefreshNotify
 *
 * @brief   Notify the peer to refresh the scan parameters.
 *
 * @param   connHandle - connection handle
 *
 * @return  None
 */
void ScanParam_RefreshNotify( uint16 connHandle )
{
  uint16 value;

  value  = GATTServApp_ReadCharCfg( connHandle, scanParamRefreshClientCharCfg );
  if ( value & GATT_CLIENT_CFG_NOTIFY )
  {
    attHandleValueNoti_t noti;
    
    noti.pValue = GATT_bm_alloc( connHandle, ATT_HANDLE_VALUE_NOTI, 
                                 SCAN_PARAM_REFRESH_LEN, NULL );
    if (noti.pValue != NULL)
    {
      // send notification
      noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle;
      noti.len = SCAN_PARAM_REFRESH_LEN;
      noti.pValue[0] = SCAN_PARAM_REFRESH_REQ;
      
      if ( GATT_Notification( connHandle, &noti, FALSE ) != SUCCESS )
      {
        GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
      }
    }
  }
}
Exemplo n.º 8
0
/*********************************************************************
 * @fn      simpleTopology_freeAttRsp
 *
 * @brief   Free ATT response message.
 *
 * @param   status - response transmit status
 *
 * @return  none
 */
static void simpleTopology_freeAttRsp(uint8_t status)
{
  // See if there's a pending ATT response message
  if (pAttRsp != NULL)
  {
    // See if the response was sent out successfully
    if (status == SUCCESS)
    {
      LCD_WRITE_STRING_VALUE("Rsp sent, retry:", rspTxRetry, 10, LCD_PAGE6);
    }
    else
    {
      // Free response payload
      GATT_bm_free(&pAttRsp->msg, pAttRsp->method);
      
      LCD_WRITE_STRING_VALUE("Rsp retry failed:", rspTxRetry, 10, LCD_PAGE6);
    }
    
    // Free response message
    ICall_freeMsg(pAttRsp);
    
    // Reset our globals
    pAttRsp = NULL;
    rspTxRetry = 0;
  }
}
/*********************************************************************
 * @fn      RunningSensor_processGATTMsg
 *
 * @brief   process incoming GATT msg.
 *
 * @param   pMsg - pointer to message to be read.
 *
 * @return  none
 */
void RunningSensor_processGATTMsg(gattMsgEvent_t *pMsg)
{
  if (pMsg->method == ATT_HANDLE_VALUE_CFM)
  {
    // Indication receipt was confirmed by the client.
    // This is a placeholder for future.
  }
  
  GATT_bm_free(&pMsg->msg, pMsg->method);
}
Exemplo n.º 10
0
/*********************************************************************
 * @fn      heartRateMeasNotify
 *
 * @brief   Prepare and send a heart rate measurement notification
 *
 * @return  none
 */
static void heartRateMeasNotify(void)
{
  // Heart rate measurement value stored in this structure
  attHandleValueNoti_t heartRateMeas;

  heartRateMeas.pValue = GATT_bm_alloc( gapConnHandle, ATT_HANDLE_VALUE_NOTI,
                                        HR_MEAS_LEN, NULL );
  if ( heartRateMeas.pValue != NULL )
  {
    uint8 *p = heartRateMeas.pValue;
    uint8 flags = heartRateFlags[heartRateFlagsIdx];
    
    // build heart rate measurement structure from simulated values
    *p++ = flags;
    *p++ = heartRateBpm;
    
    if (flags & HEARTRATE_FLAGS_FORMAT_UINT16)
    {
      // additional byte for 16 bit format
      *p++ = 0;
    }
    
    if (flags & HEARTRATE_FLAGS_ENERGY_EXP)
    {
      *p++ = LO_UINT16(heartRateEnergy);
      *p++ = HI_UINT16(heartRateEnergy);
    }
    
    if (flags & HEARTRATE_FLAGS_RR)
    {
      *p++ = LO_UINT16(heartRateRrInterval1);
      *p++ = HI_UINT16(heartRateRrInterval1);  
      *p++ = LO_UINT16(heartRateRrInterval2);
      *p++ = HI_UINT16(heartRateRrInterval2);  
    }
    
    heartRateMeas.len = (uint8) (p - heartRateMeas.pValue);
    
    if ( HeartRate_MeasNotify( gapConnHandle, &heartRateMeas ) != SUCCESS )
    {
      GATT_bm_free( (gattMsg_t *)&heartRateMeas, ATT_HANDLE_VALUE_IND );
    }
    
    // update simulated values 
    heartRateEnergy += ENERGY_INCREMENT;
    if (++heartRateBpm == BPM_MAX)
    {
      heartRateBpm = BPM_DEFAULT;
    }
    
    heartRateRrInterval1 = heartRateRrInterval2 = HEARTRATE_BPM_TO_RR(heartRateBpm);
  }
}
Exemplo n.º 11
0
/*********************************************************************
 * @fn      HeartRate_measNotify
 *
 * @brief   Prepare and send a heart rate measurement notification.
 *
 * @return  none
 */
static void HeartRate_measNotify(void)
{
  attHandleValueNoti_t heartRateMeas;

  heartRateMeas.pValue = GATT_bm_alloc(gapConnHandle, ATT_HANDLE_VALUE_NOTI,
                                       HEARTRATE_MEAS_LEN, NULL);
  if (heartRateMeas.pValue != NULL)
  {
    uint8_t *p = heartRateMeas.pValue;
    uint8_t flags = heartRateflags[flagsIdx];
    
    // Build heart rate measurement structure from simulated values.
    *p++ = flags;
    *p++ = heartRateBpm;
    
    if (flags & HEARTRATE_FLAGS_FORMAT_UINT16)
    {
      // Additional byte for 16 bit format.
      *p++ = 0;
    }
    
    if (flags & HEARTRATE_FLAGS_ENERGY_EXP)
    {
      *p++ = LO_UINT16(heartRateEnergyLvl);
      *p++ = HI_UINT16(heartRateEnergyLvl);
    }
    
    if (flags & HEARTRATE_FLAGS_RR)
    {
      *p++ = LO_UINT16(heartRateRrInterval);
      *p++ = HI_UINT16(heartRateRrInterval);  
      *p++ = LO_UINT16(heartRateRrInterval2);
      *p++ = HI_UINT16(heartRateRrInterval2);  
    }
    
    heartRateMeas.len = (uint8)(p - heartRateMeas.pValue);
    
    // Send notification.
    if (HeartRate_MeasNotify(gapConnHandle, &heartRateMeas) != SUCCESS)
    {
      GATT_bm_free((gattMsg_t *)&heartRateMeas, ATT_HANDLE_VALUE_NOTI);
    }
    
    // Update simulated values.
    heartRateEnergyLvl += HEARTRATE_ENERGY_INCREMENT;
    if (++heartRateBpm == HEARTRATE_BPM_MAX)
    {
      heartRateBpm = HEARTRATE_BPM_DEFAULT;
    }
    
    heartRateRrInterval = heartRateRrInterval2 = HEARTRATE_BPM2RR(heartRateBpm);
  }
}
Exemplo n.º 12
0
 /*********************************************************************
 * @fn      gattServApp_SendNotiInd
 *
 * @brief   Send an ATT Notification/Indication.
 *
 * @param   connHandle - connection handle to use.
 * @param   cccValue - client characteristic configuration value.
 * @param   authenticated - whether an authenticated link is required.
 * @param   pAttr - pointer to attribute record.
 * @param   taskId - task to be notified of confirmation.
 * @param   pfnReadAttrCB - read callback function pointer.
 *
 * @return  Success or Failure
 */
static bStatus_t gattServApp_SendNotiInd( uint16 connHandle, uint8 cccValue,
                                          uint8 authenticated, gattAttribute_t *pAttr,
                                          uint8 taskId, pfnGATTReadAttrCB_t pfnReadAttrCB )
{
  attHandleValueNoti_t noti;
  uint16 len;
  bStatus_t status;

  // If the attribute value is longer than (ATT_MTU - 3) octets, then
  // only the first (ATT_MTU - 3) octets of this attributes value can
  // be sent in a notification.
  noti.pValue = (uint8 *)GATT_bm_alloc( connHandle, ATT_HANDLE_VALUE_NOTI,
                                        GATT_MAX_MTU, &len );
  if ( noti.pValue != NULL )
  {
    status = (*pfnReadAttrCB)( connHandle, pAttr, noti.pValue, &noti.len, 
                               0, len, GATT_LOCAL_READ );
    if ( status == SUCCESS )
    {
      noti.handle = pAttr->handle;
      
      if ( cccValue & GATT_CLIENT_CFG_NOTIFY )
      {
        status = GATT_Notification( connHandle, &noti, authenticated );
      }
      else // GATT_CLIENT_CFG_INDICATE
      {
        status = GATT_Indication( connHandle, (attHandleValueInd_t *)&noti,
                                  authenticated, taskId );
      }
    }
    
    if ( status != SUCCESS )
    {
      GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
    }
  }
  else
  {
    status = bleNoResources;
  }
  
  return ( status );
}
/*********************************************************************
 * @fn     glucCollCentral_processGATTMsg
 *
 * @brief   Process GATT messages
 *
 * @param   pMsg - pointer to Gatt Message Event
 *
 * @return  none
 */
static void glucCollCentral_processGATTMsg(gattMsgEvent_t *pMsg)
{
  if (pMsg->method == ATT_HANDLE_VALUE_NOTI ||
      pMsg->method == ATT_HANDLE_VALUE_IND)
  {
    glucoseIndGattMsg(pMsg);
  }
  else if (pMsg->method == ATT_READ_RSP ||
           pMsg->method == ATT_WRITE_RSP)
  {
    if(glucCollCharHdls == true)
    {
       glucoseCtlPntGattMsg(pMsg);
    }
    else
    {
      glucCollConfigState = glucoseConfigGattMsg (glucCollConfigState, pMsg);
    }
  }
  else if(glucCollDiscState != DISC_IDLE)
  {
    glucCollDiscState = glucoseDiscGattMsg(glucCollDiscState, pMsg);

    if (glucCollDiscState == DISC_IDLE)
    {      
      // Start characteristic configuration
      glucCollConfigState = glucoseConfigNext(GLUCOSE_CONFIG_START);
    }
  }
  else if (pMsg->method == ATT_ERROR_RSP)
  {
    if(glucCollCharHdls == true)
    {
       glucoseCtlPntGattMsg(pMsg);
    }
    else
    {
      glucCollConfigState = glucoseConfigGattMsg (glucCollConfigState, pMsg);
    } 
  }
  
  GATT_bm_free(&pMsg->msg, pMsg->method);
}
Exemplo n.º 14
0
/*********************************************************************
 * @fn      SimplePropBeacon_processGATTMsg
 *
 * @brief   Process GATT messages and events.
 *
 * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
 */
static uint8_t SimplePropBeacon_processGATTMsg(gattMsgEvent_t *pMsg)
{
  // See if GATT server was unable to transmit an ATT response
  if (pMsg->hdr.status == blePending)
  {
    // No HCI buffer was available. Let's try to retransmit the response
    // on the next connection event.
    if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity,
                                   SPB_CONN_EVT_END_EVT) == SUCCESS)
    {
      // First free any pending response
      SimplePropBeacon_freeAttRsp(FAILURE);

      // Hold on to the response message for retransmission
      pAttRsp = pMsg;

      // Don't free the response message yet
      return (FALSE);
    }
  }
  else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
  {
    // ATT request-response or indication-confirmation flow control is
    // violated. All subsequent ATT requests or indications will be dropped.
    // The app is informed in case it wants to drop the connection.

    // Display the opcode of the message that caused the violation.
    Display_print1(dispHandle, 5, 0, "FC Violated:",  pMsg->msg.flowCtrlEvt.opcode);
  }
  else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
  {
    // MTU size updated

    Display_print1(dispHandle, 5, 0, "FC Violated:",  pMsg->msg.mtuEvt.MTU);
  }

  // Free message payload. Needed only for ATT Protocol messages
  GATT_bm_free(&pMsg->msg, pMsg->method);

  // It's safe to free the incoming message
  return (TRUE);
}
Exemplo n.º 15
0
/*********************************************************************
 * @fn      timeAppWriteCtrl
 *
 * @brief   Write a control point.
 *
 * @param   handle - attribute handle
 * @param   value - attribute value
 *
 * @return  none
 */
static void timeAppWriteCtrl( uint16 handle, uint8 value )
{
  attWriteReq_t req;
   
  req.pValue = GATT_bm_alloc( timeAppConnHandle, ATT_WRITE_REQ, 1, NULL );
  if (req.pValue != NULL)
  { 
    req.len = 1;
    req.pValue[0] = value;
    req.sig = 0;
    req.cmd = 1;
    
    req.handle = handle;
    
    // Send write command
    if ( GATT_WriteNoRsp(timeAppConnHandle, &req) != SUCCESS )
    {
      GATT_bm_free( (gattMsg_t *)&req, ATT_WRITE_REQ );
    }
  }
}
Exemplo n.º 16
0
/*********************************************************************
 * @fn      CyclingService_ProcessEvent
 *
 * @brief   process incoming event.
 *
 * @param   task_id - OSAL task id.
 *
 * @param   events - event bit(s) set for the task(s)
 *
 * @return  none
 */
uint16 CyclingService_ProcessEvent( uint8 task_id, uint16 events )
{
  VOID task_id;

  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = osal_msg_receive( cyclingService_TaskID )) != NULL )
    {
      cycling_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 & CSC_CMD_IND_SEND_EVT )
  {
    if ( GATT_Indication( connectionHandle, &cscCmdInd, FALSE, 
                          cyclingService_TaskID ) != SUCCESS )
    {
      GATT_bm_free( (gattMsg_t *)&cscCmdInd, ATT_HANDLE_VALUE_IND );
    }
  
    // Clear out this indication.
    VOID osal_memset( &cscCmdInd, 0, sizeof(attHandleValueInd_t) );

    // Set Control Point Cfg done
    scOpInProgress = FALSE;

    return ( events ^ CSC_CMD_IND_SEND_EVT );
  }

  return 0;
}
Exemplo n.º 17
0
/*********************************************************************
 * @fn      hidappEnableNotification
 *
 * @brief   Enable notification for a given attribute handle.
 *
 * @param   connHandle - connection handle to send notification on
 * @param   attrHandle - attribute handle to send notification for
 *
 * @return  none
 */
static void hidappEnableNotification( uint16 connHandle, uint16 attrHandle )
{
  attWriteReq_t req;
  
  req.pValue = GATT_bm_alloc( connHandle, ATT_WRITE_REQ, 2, NULL );
  if ( req.pValue != NULL )
  {
    uint8 notificationsOn[] = {0x01, 0x00};

    req.handle = attrHandle;

    req.len = 2;
    osal_memcpy(req.pValue, notificationsOn, 2);

    req.sig = 0;
    req.cmd = 0;

    if ( GATT_WriteCharValue( connHandle, &req, hidappTaskId ) != SUCCESS )
    {
      GATT_bm_free( (gattMsg_t *)&req, ATT_WRITE_REQ );
    }
  }
}
Exemplo n.º 18
0
/*********************************************************************
 * @fn      Thermometer_processGattMsg
 *
 * @brief   Process GATT messages.
 *
 * @param   pMsg - pointer the the GATT message.
 *
 * @return  none
 */
static void Thermometer_processGattMsg(gattMsgEvent_t *pMsg)
{
  // Measurement Indication Confirmation.
  if (pMsg->method == ATT_HANDLE_VALUE_CFM)
  {
    Thermometer_sendStoredMeas();
  }
  
  if (pMsg->method == ATT_HANDLE_VALUE_NOTI ||
       pMsg->method == ATT_HANDLE_VALUE_IND)
  {
    Time_indGattMsg(pMsg);
  }
  else if (pMsg->method == ATT_READ_RSP ||
            pMsg->method == ATT_WRITE_RSP)
  {
    thermometer_timeCfgState = Time_configGattMsg(thermometer_timeCfgState, 
                                                  pMsg);
    
    if (thermometer_timeCfgState == TIME_CONFIG_CMPL)
    {
      servDiscComplete = TRUE;
    }
  }
  else
  {
    servDiscState = Time_discGattMsg(servDiscState, pMsg);
    
    if (servDiscState == DISC_IDLE)
    {      
      // Start characteristic configuration.
      thermometer_timeCfgState = Time_configNext(TIME_CONFIG_START);
    }
  }
  
  GATT_bm_free(&pMsg->msg, pMsg->method);
}
Exemplo n.º 19
0
/*********************************************************************
 * @fn      timeAppProcessGattMsg
 *
 * @brief   Process GATT messages
 *
 * @return  none
 */
static void thermometerProcessGattMsg( gattMsgEvent_t *pMsg )
{


    //Measurement Indication Confirmation
    if( pMsg->method ==ATT_HANDLE_VALUE_CFM)
    {
        thermometerSendStoredMeas();
    }

    if ( pMsg->method == ATT_HANDLE_VALUE_NOTI ||
            pMsg->method == ATT_HANDLE_VALUE_IND )
    {
        timeAppIndGattMsg( pMsg );
    }
    else if ( pMsg->method == ATT_READ_RSP ||
              pMsg->method == ATT_WRITE_RSP )
    {
        timeAppConfigState = timeAppConfigGattMsg ( timeAppConfigState, pMsg );
        if ( timeAppConfigState == TIMEAPP_CONFIG_CMPL )
        {
            timeAppDiscoveryCmpl = TRUE;
        }
    }
    else
    {
        timeAppDiscState = timeAppDiscGattMsg( timeAppDiscState, pMsg );
        if ( timeAppDiscState == DISC_IDLE )
        {
            // Start characteristic configuration
            timeAppConfigState = timeAppConfigNext( TIMEAPP_CONFIG_START );
        }
    }

    GATT_bm_free( &pMsg->msg, pMsg->method );
}
Exemplo n.º 20
0
uint8 glucoseCtlPntWriteFilter(uint8 opcode, uint8 oper, uint8 filterType,
                               void* param1, void* param2)
{
  attWriteReq_t writeReq;
  uint8 status;

  writeReq.pValue = GATT_bm_alloc( glucCollConnHandle, ATT_WRITE_REQ,
                                   GLUCOSE_CTL_PNT_FILTER_LEN, NULL );
  if (writeReq.pValue != NULL)
  {
    UTCTimeStruct *time1, *time2;
    uint16 *seqNum1, *seqNum2;
    
    uint8 *p = writeReq.pValue;
    
    *p++ = opcode;
    *p++ = oper;

    // The operator will tells us whether to include the filters or not
    // Note day and month are converted to date time struct values
    switch(oper)
    {
      case CTL_PNT_OPER_LESS_EQUAL:
      case CTL_PNT_OPER_GREATER_EQUAL:
        *p++ = filterType;
        
        if (filterType == CTL_PNT_FILTER_SEQNUM)
        {
          seqNum1 = param1;
          *p++ = LO_UINT16(*seqNum1);
          *p++ = HI_UINT16(*seqNum1);
        }
        else
        {
          time1 = param1;
          *p++ = LO_UINT16(time1->year);
          *p++ = HI_UINT16(time1->year);
          *p++ = (time1->month + 1);
          *p++ = (time1->day + 1);
          *p++ = time1->hour;
          *p++ = time1->minutes;
          *p++ = time1->seconds;
        }
        break;
        
      case CTL_PNT_OPER_RANGE:
        *p++ = filterType;
        
        if (filterType == CTL_PNT_FILTER_SEQNUM)
        {
          seqNum1 = param1;
          seqNum2 = param2;
          *p++ = LO_UINT16(*seqNum1);
          *p++ = HI_UINT16(*seqNum1);
          *p++ = LO_UINT16(*seqNum2);
          *p++ = HI_UINT16(*seqNum2);      
        }
        else
        {
          time1 = param1;
          time2 = param2;
          *p++ = LO_UINT16(time1->year);
          *p++ = HI_UINT16(time1->year);
          *p++ = (time1->month + 1);
          *p++ = (time1->day + 1);
          *p++ = time1->hour;
          *p++ = time1->minutes;
          *p++ = time1->seconds;
          
          *p++ = LO_UINT16(time2->year);
          *p++ = HI_UINT16(time2->year);
          *p++ = (time2->month + 1);
          *p++ = (time2->day + 1);
          *p++ = time2->hour;
          *p++ = time2->minutes;
          *p++ = time2->seconds;
        }
        break;
        
      default:
        break;
    }
    
    writeReq.len = (p - writeReq.pValue);
    writeReq.sig = 0;
    writeReq.cmd = 0;
    
    writeReq.handle = glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_START];
    
    // Send the write request
    status = GATT_WriteCharValue( glucCollConnHandle, &writeReq, glucCollTaskId );
    if (status != SUCCESS)
    {
      GATT_bm_free( (gattMsg_t *)&writeReq, ATT_WRITE_REQ );
    }
  }
  else
  {
    status = bleMemAllocError;
  }
  
  return status;
}
Exemplo n.º 21
0
/*********************************************************************
 * @fn      thermometerMeasNotify
 *
 * @brief   Prepare and send a thermometer measurement notification
 *
 * @return  none
 */
static void thermometerImeasNotify(void)
{
    if (temperatureIMeasCharConfig == true)
    {
        attHandleValueNoti_t thermometerIMeas;

        thermometerIMeas.pValue = GATT_bm_alloc( gapConnHandle,
                                  ATT_HANDLE_VALUE_NOTI,
                                  THERMOMETER_IMEAS_LEN, NULL );
        if ( thermometerIMeas.pValue != NULL )
        {
            // att value notification structure
            uint8 *p = thermometerIMeas.pValue;

            // temperature
            uint32 temperature;

            //flags
            uint8 flags = thermometerFlags[thermometerFlagsIdx];

            // flags 1 byte long
            *p++ = flags;

            if(flags & THERMOMETER_FLAGS_FARENHEIT)
            {
                temperature =  (thermometerCelcius *9/5) +320;
            }
            else
            {
                temperature = thermometerCelcius;
            }

            temperature = 0xFF000000 | temperature;

            //osal_buffer_uint32
            p = osal_buffer_uint32( p, temperature );

            //timestamp
            if (flags & THERMOMETER_FLAGS_TIMESTAMP)
            {
                UTCTimeStruct time;

                // Get time structure from OSAL
                osal_ConvertUTCTime( &time, osal_getClock() );

                *p++ = LO_UINT16(time.year);
                *p++ = HI_UINT16(time.year);
                *p++ = time.month;
                *p++ = time.day;
                *p++ = time.hour;
                *p++ = time.minutes;
                *p++ = time.seconds;
            }

            if(flags & THERMOMETER_FLAGS_TYPE)
            {
                uint8 site;
                Thermometer_GetParameter( THERMOMETER_TYPE, &site );
                *p++ =  site;
            }

            thermometerIMeas.len = (uint8) (p - thermometerIMeas.pValue);

            if ( Thermometer_IMeasNotify( gapConnHandle, &thermometerIMeas) != SUCCESS )
            {
                GATT_bm_free( (gattMsg_t *)&thermometerIMeas, ATT_HANDLE_VALUE_NOTI );
            }
        }
    }
}
Exemplo n.º 22
0
/*********************************************************************
 * @fn      Hidapp_ProcessEvent
 *
 * @brief   This function processes the OSAL events and messages for the
 *          Sample Application.
 *
 * input parameters
 *
 * @param   taskId - Task ID assigned to this app by OSAL at system initialization.
 * @param   events - Bit mask of the pending event(s).
 *
 * output parameters
 *
 * None.
 *
 * @return  The events bit map received via parameter with the bits cleared
 *          which correspond to the event(s) that were processed on this invocation.
 */
uint16 Hidapp_ProcessEvent(uint8 taskId, uint16 events)
{
  (void) taskId; // Unused argument

  if ( events & SYS_EVENT_MSG )
  {
    osal_event_hdr_t  *pMsg;

    while ((pMsg = (osal_event_hdr_t *) osal_msg_receive(hidappTaskId)) != NULL)
    {
      switch (pMsg->event)
      {
        case GATT_MSG_EVENT:
          {
            hidappProcessGATTMsg( (gattMsgEvent_t *)pMsg );
          }
          break;
        case KEY_CHANGE:
          {
            hidappHandleKeys( ((keyChange_t *)pMsg)->keys, ((keyChange_t *)pMsg)->state );
          }
          break;

        default:
          break;
      }

      VOID osal_msg_deallocate((uint8 *) pMsg);
    }

    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & HIDAPP_EVT_START )
  {
    hidappStart();

    return (events ^ HIDAPP_EVT_START);
  }

  if ( events & HIDAPP_EVT_REPORT_RETRY )
  {
    // Report retries event
    if ( ( hidappSendInReport( &lastInReport ) == FALSE ) &&
         ( reportRetries < USB_HID_INPUT_RETRY_COUNT ) )
    {
      reportRetries++;
      osal_start_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY,
                          (reportRetries*HIDAPP_INPUT_RETRY_TIMEOUT) );
    }
    else
    {
      // Done retrying      
      reportRetries = 0;
      
      // Free last report's payload
      GATT_bm_free( (gattMsg_t *)&lastInReport, ATT_HANDLE_VALUE_NOTI );
      
      // Zero out all fields of last report
      VOID osal_memset( &lastInReport, 0, sizeof( attHandleValueNoti_t ) );
    }

    return (events ^ HIDAPP_EVT_REPORT_RETRY);
  }

  if ( events & HIDAPP_EVT_START_DISCOVERY )
  {
    // Start initial discovery
    hidappStartDiscovery();

    return ( events ^ HIDAPP_EVT_START_DISCOVERY );
  }

  if ( events & HIDAPP_EVT_INIT_CONNECT )
  {
    // Still trying to re-connect
    HalLedSet( HAL_LED_1, HAL_LED_MODE_BLINK ); // green led

    return ( events ^ HIDAPP_EVT_INIT_CONNECT );
  }

  return ( 0 );  /* Discard unknown events. */
}
Exemplo n.º 23
0
/*********************************************************************
 * @fn      sensorMeasNotify
 *
 * @brief   Prepare and send a CSC measurement notification
 *
 * @return  none
 */
static void sensorMeasNotify( void )
{
  attHandleValueNoti_t sensorMeas;
  
  sensorMeas.pValue = GATT_bm_alloc( gapConnHandle, ATT_HANDLE_VALUE_NOTI,
                                     CSC_MEAS_LEN, NULL );
  if ( sensorMeas.pValue != NULL )
  {
    uint8 *p = sensorMeas.pValue;
    uint8 flags = sensorFlags[sensorFlagsIdx];

    // Build CSC measurement structure from simulated values
    // Flags simulate the isPresent bits.
    *p++ = flags;

    // If present, add Speed data into measurement
    if (flags & CSC_FLAGS_SPEED)
    {
      *p++ = BREAK_UINT32(cummWheelRevs, 0);
      *p++ = BREAK_UINT32(cummWheelRevs, 1);
      *p++ = BREAK_UINT32(cummWheelRevs, 2);
      *p++ = BREAK_UINT32(cummWheelRevs, 3);

      *p++ = LO_UINT16(lastWheelEvtTime);
      *p++ = HI_UINT16(lastWheelEvtTime);

      // Update simulated values (simulate in the reverse direction)
      if (cummWheelRevs < WHEEL_REV_INCREMENT) //don't allow revolutions to roll over
      {
        cummWheelRevs = 0;
      }
      else
      {
        cummWheelRevs -= WHEEL_REV_INCREMENT;
      }

      lastWheelEvtTime += WHEEL_EVT_INCREMENT;
    }

    // If present, add Cadence data into measurement
    if (flags & CSC_FLAGS_CADENCE)
    {
      *p++ = LO_UINT16(cummCrankRevs);
      *p++ = HI_UINT16(cummCrankRevs);

      *p++ = LO_UINT16(lastCrankEvtTime);
      *p++ = HI_UINT16(lastCrankEvtTime);

      // Update Simualted Values
      cummCrankRevs += CRANK_REV_INCREMENT;
      lastCrankEvtTime += CRANK_EVT_INCREMENT;
    }

    // Get length
    sensorMeas.len = (uint8) (p - sensorMeas.pValue);

    // Send to service to send the notification
    if ( Cycling_MeasNotify( gapConnHandle, &sensorMeas ) != SUCCESS )
    {
      GATT_bm_free( (gattMsg_t *)&sensorMeas, ATT_HANDLE_VALUE_NOTI );
    }
  }
}
Exemplo n.º 24
0
/*********************************************************************
 * @fn      simpleTopology_processGATTMsg
 *
 * @brief   Process GATT messages and events.
 *
 * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
 */
static uint8_t simpleTopology_processGATTMsg(gattMsgEvent_t *pMsg)
{
  // See if GATT server was unable to transmit an ATT response
  if (pMsg->hdr.status == blePending)
  {
    // No HCI buffer was available. Let's try to retransmit the response
    // on the next connection event.
    if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity,
                                   SBT_CONN_EVT_END_EVT) == SUCCESS)
    {
      // First free any pending response
      simpleTopology_freeAttRsp(FAILURE);
      
      // Hold on to the response message for retransmission
      pAttRsp = pMsg;
      
      // Don't free the response message yet
      return (FALSE);
    }
  }
  else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
  {
    // ATT request-response or indication-confirmation flow control is
    // violated. All subsequent ATT requests or indications will be dropped.
    // The app is informed in case it wants to drop the connection.
    
    // Display the opcode of the message that caused the violation.
    LCD_WRITE_STRING_VALUE("FC Violated:", pMsg->msg.flowCtrlEvt.opcode,
                           10, LCD_PAGE6);
  }    
  else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
  {
    // MTU size updated
    LCD_WRITE_STRING_VALUE("MTU Size:", pMsg->msg.mtuEvt.MTU, 10, LCD_PAGE6);
  }
  
  //messages from GATT server
  if ((gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) > 0))
  {
    if ((pMsg->method == ATT_READ_RSP)   ||
        ((pMsg->method == ATT_ERROR_RSP) &&
         (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
    {
      if (pMsg->method == ATT_ERROR_RSP)
      {      
        LCD_WRITE_STRING_VALUE("Read Error", pMsg->msg.errorRsp.errCode, 10,
                               LCD_PAGE6);
      }
      else
      {
        // After a successful read, display the read value
        LCD_WRITE_STRING_VALUE("Read rsp:", pMsg->msg.readRsp.pValue[0], 10,
                               LCD_PAGE6);
      }
      
    }
    else if ((pMsg->method == ATT_WRITE_RSP)  ||
             ((pMsg->method == ATT_ERROR_RSP) &&
              (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
    {
      
      if (pMsg->method == ATT_ERROR_RSP == ATT_ERROR_RSP)
      {     
        LCD_WRITE_STRING_VALUE("Write Error", pMsg->msg.errorRsp.errCode, 10,
                               LCD_PAGE6);
      }
      else
      {
        // After a succesful write, display the value that was written and
        // increment value
        LCD_WRITE_STRING_VALUE("Write sent:", charVal++, 10, LCD_PAGE6);
      }
    }
    else if (discState != BLE_DISC_STATE_IDLE)
    {
      simpleTopology_processGATTDiscEvent(pMsg);
    }
  } // else - in case a GATT message came after a connection has dropped, ignore it.  
  
  // Free message payload. Needed only for ATT Protocol messages
  GATT_bm_free(&pMsg->msg, pMsg->method);
  
  // It's safe to free the incoming message
  return (TRUE);
}
/*********************************************************************
 * @fn      Time_configNext()
 *
 * @brief   Perform the characteristic configuration read or
 *          write procedure.
 *
 * @param   state - Configuration state.
 *
 * @return  New configuration state.
 */
uint8_t Time_configNext(uint8_t state)
{
  bool read;

  // Find next non-zero cached handle of interest
  while (state < TIME_CONFIG_MAX &&
          Time_handleCache[Time_configList[state]] == 0)
  {
    state++;
  }

  // Return if reached end of list
  if (state >= TIME_CONFIG_MAX)
  {
    return TIME_CONFIG_CMPL;
  }

  // Determine what to do with characteristic
  switch (Time_configList[state])
  {
    // Read these characteristics
    case HDL_CURR_TIME_CT_TIME_START:
      read = TRUE;
      break;

    // Set notification for these characteristics
    case HDL_CURR_TIME_CT_TIME_CCCD:
      read = FALSE;
      break;

    default:
      return state;
  }

  if(Time_configDone==TRUE)
  {
    return state;
  }
  
  // Do a GATT read or write
  if (read)
  {
    attReadReq_t  readReq;
      
    readReq.handle = Time_handleCache[Time_configList[state]];
    
    // Send the read request
    GATT_ReadCharValue(Time_connHandle, &readReq, ICall_getEntityId());
    
    // Only reading time right now
    Time_configDone = TRUE;
  }
  else
  {
    attWriteReq_t writeReq;
    
    writeReq.pValue = GATT_bm_alloc(Time_connHandle, ATT_WRITE_REQ, 2, NULL);
    if (writeReq.pValue != NULL)
    {
      writeReq.len = 2;
      writeReq.pValue[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY);
      writeReq.pValue[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY);
      writeReq.sig = 0;
      writeReq.cmd = 0;

      writeReq.handle = Time_handleCache[Time_configList[state]];
      
      // Send the read request
      if (GATT_WriteCharValue(Time_connHandle, &writeReq, 
                              ICall_getEntityId()) != SUCCESS)
      {
        GATT_bm_free((gattMsg_t *)&writeReq, ATT_WRITE_REQ);
      }
    }
  }

  return state;
}
/*********************************************************************
 * @fn      glucoseConfigNext()
 *
 * @brief   Perform the characteristic configuration read or
 *          write procedure.
 *
 * @param   state - Configuration state.
 *
 * @return  New configuration state.
 */
uint8_t glucoseConfigNext(uint8_t state)
{
  bool read;
  uint16_t charCfg;

  // Find next non-zero cached handle of interest
  while (state < GLUCOSE_CONFIG_MAX &&
         glucoseHdlCache[glucoseConfigList[state]] == 0)
  {
    state++;
  }

  // Return if reached end of list
  if (state >= GLUCOSE_CONFIG_MAX)
  {
    glucCollCharHdls = true;
    
    return GLUCOSE_CONFIG_CMPL;
  }

  // Determine what to do with characteristic
  switch (glucoseConfigList[state])
  {
    // Read these characteristics
    case HDL_DEVINFO_SYSTEM_ID:
    case HDL_DEVINFO_MANUFACTURER_NAME:
    case HDL_DEVINFO_MODEL_NUM:
    case HDL_GLUCOSE_FEATURE:
      read = TRUE;
      break;

    // Set notification for these characteristics
    case HDL_GLUCOSE_MEAS_CCCD:
    case HDL_GLUCOSE_CONTEXT_CCCD:
      read = FALSE;
      charCfg = GATT_CLIENT_CFG_NOTIFY;
      break;
      
    // Set indication for these characteristics
    case HDL_GLUCOSE_CTL_PNT_CCCD:
      read = FALSE;
      charCfg = GATT_CLIENT_CFG_INDICATE;
      break;
      
    default:
      return state;
  }

  // Do a GATT read or write
  if (read)
  {
    attReadReq_t readReq;
    
    readReq.handle = glucoseHdlCache[glucoseConfigList[state]];
    
    // Send the read request
    GATT_ReadCharValue(glucCollConnHandle, &readReq, glucCollTaskId);
  }
  else
  {
    attWriteReq_t writeReq;
    
    writeReq.pValue = GATT_bm_alloc(glucCollConnHandle, ATT_WRITE_REQ, 2, NULL);
    if (writeReq.pValue != NULL)
    {
      writeReq.len = 2;
      writeReq.pValue[0] = LO_UINT16(charCfg);
      writeReq.pValue[1] = HI_UINT16(charCfg);
      writeReq.sig = 0;
      writeReq.cmd = 0;
        
      writeReq.handle = glucoseHdlCache[glucoseConfigList[state]];
      
      // Send the write request
      if (GATT_WriteCharValue(glucCollConnHandle, &writeReq, 
                              glucCollTaskId) != SUCCESS)
      {
        GATT_bm_free((gattMsg_t *)&writeReq, ATT_WRITE_REQ);
      }
    }
  }

  return state;
}
Exemplo n.º 27
0
/*********************************************************************
 * @fn      simpleTopology_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 simpleTopology_handleKeys(uint8_t shift, uint8_t keys)
{
  (void)shift;  // Intentionally unreferenced parameter
  
  if (LCDmenu == MAIN_MENU)
  {
    if (keys & KEY_LEFT)  //show discovery results
    {
      selectKey = DISCOVERED_DEVICES;
      
      // If discovery has occurred and a device was found
      if (!scanningStarted && scanRes > 0)
      {
        // Increment index of current result (with wraparound)
        scanIdx++;
        if (scanIdx >= scanRes)
        {
          scanIdx = 0;
        }
        
        LCD_WRITE_STRING_VALUE("Device", (scanIdx + 1), 10, LCD_PAGE3);
        LCD_WRITE_STRING(Util_convertBdAddr2Str(devList[scanIdx].addr), LCD_PAGE4);
      }
      return;
    }
    if (keys & KEY_UP)  //Scan for devices
    {
      // Start or stop discovery
      if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0) //if we can connect to another device
      {
        if (!scanningStarted) //if we're not already scanning
        {
          scanningStarted = TRUE;
          scanRes = 0;
          
          LCD_WRITE_STRING("Discovering...", LCD_PAGE3);
          LCD_WRITE_STRING("", LCD_PAGE4);
          LCD_WRITE_STRING("", LCD_PAGE6);
          
          GAPRole_StartDiscovery(DEFAULT_DISCOVERY_MODE,
                                 DEFAULT_DISCOVERY_ACTIVE_SCAN,
                                 DEFAULT_DISCOVERY_WHITE_LIST);      
        }
        else //cancel scanning
        {
          LCD_WRITE_STRING("Discovery Cancelled", LCD_PAGE3);
          GAPRole_CancelDiscovery();
          scanningStarted = FALSE;
        }
      }
      else // can't add more links at this time
      {
        LCD_WRITE_STRING("Can't scan:no links ", LCD_PAGE3);
      }
      return;
    }
    if (keys & KEY_RIGHT)  // turn advertising on / off
    {
      uint8_t adv;
      uint8_t adv_status;
      GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv_status, NULL);
      if (adv_status) //turn off
      {
        adv = FALSE;
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL);
      }
      else //turn on
      {
        adv = TRUE;
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL);
      }
      return;
    }
    
    if (keys & KEY_SELECT) //connect to a discovered device
    {
      if (selectKey == DISCOVERED_DEVICES)    // connect to a device  
      {
        uint8_t addrType;
        uint8_t *peerAddr;
        
        if (connecting_state == 1) // if already attempting to connect, cancel connection
        {
        	GAPRole_TerminateConnection(0xFFFE);
        	LCD_WRITE_STRING("Connecting stopped.", LCD_PAGE3);
        	connecting_state = 0;
        }
        else //establish new connection
        {
        	// if there is a scan result
        	if (scanRes > 0)
        	{
        		// connect to current device in scan result
        		peerAddr = devList[scanIdx].addr;
        		addrType = devList[scanIdx].addrType;

        		GAPRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
                                	DEFAULT_LINK_WHITE_LIST,
									addrType, peerAddr);
        		connecting_state = 1;

        		LCD_WRITE_STRING("Connecting", LCD_PAGE3);
        		LCD_WRITE_STRING(Util_convertBdAddr2Str(peerAddr), LCD_PAGE4);
        	}
        }
      }
      else if (selectKey == CONNECTED_DEVICES) //enter the device menu
      {
        if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE)
        {
          LCDmenu = DEVICE_MENU;
          LCD_WRITE_STRING("Device Menu", LCD_PAGE3);
          LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr), LCD_PAGE4);
          if (multiConnInfo[connIdx].gapRole_ConnRole == GAP_PROFILE_CENTRAL)
          {
             LCD_WRITE_STRING("Connected as Central", LCD_PAGE5);
             LCD_WRITE_STRING("", LCD_PAGE6);
             LCD_WRITE_STRING("", LCD_PAGE7);
          }
          else //PERIPHERAL
          {
            LCD_WRITE_STRING("Connected as Periph", LCD_PAGE5);
            LCD_WRITE_STRING("", LCD_PAGE6);
            LCD_WRITE_STRING("", LCD_PAGE7);            
          }
          //use this connection for all functionality
          connHandle = multiConnInfo[connIdx].gapRole_ConnectionHandle;
        }
        else // no active connection here
        LCD_WRITE_STRING("No Connection here.", LCD_PAGE3);
      }
      return;
    }
    
    if (keys & KEY_DOWN) //browse connected devices
    {
      LCD_WRITE_STRING("Connected Device:", LCD_PAGE3);
      if (++connIdx >= MAX_NUM_BLE_CONNS) //increment connIdx
      {
        connIdx = 0;
      }   
      if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE) //if there is a connection at this index
      {
        LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr), LCD_PAGE4);
      }
      else
      {
        LCD_WRITE_STRING("N/A", LCD_PAGE4);
      }
      selectKey = CONNECTED_DEVICES;
    } 
    return;
  }
  
  else if (LCDmenu == DEVICE_MENU)
  {
    if (keys & KEY_UP) //read/whrite char
    {
      if (charHdl[connIdx] != 0)
      {
        uint8_t status;
        
        // Do a read or write as long as no other read or write is in progress
        if (doWrite)
        {
          // Do a write
          attWriteReq_t req;
          
          req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
          if ( req.pValue != NULL )
          {
            req.handle = charHdl[connIdx];
            req.len = 1;
            req.pValue[0] = charVal;
            req.sig = 0;
            req.cmd = 0;
            
            status = GATT_WriteCharValue(connHandle, &req, selfEntity);
            if ( status != SUCCESS )
            {
              GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
            }
          }
        }
        else
        {
          // Do a read
          attReadReq_t req;
          
          req.handle = charHdl[connIdx];
          status = GATT_ReadCharValue(connHandle, &req, selfEntity);
        }
        
        if (status == SUCCESS)
        {
          doWrite = !doWrite;
        }
      }
      return;
    }
    
    if (keys & KEY_RIGHT) //connection update...eventually
    {
      asm("NOP");
      return;
    }
    
    if (keys & KEY_SELECT)
    {
      GAPRole_TerminateConnection(connHandle);
      
      LCD_WRITE_STRING("Disconnecting", LCD_PAGE5);
      LCD_WRITE_STRING("", LCD_PAGE6);
      
      return;
    }

    if (keys & KEY_DOWN) //back to main menu
    {
      LCDmenu = MAIN_MENU;
      LCD_WRITE_STRING("Main Menu", LCD_PAGE3);
      //clear screen
      LCD_WRITE_STRING("", LCD_PAGE4);
      LCD_WRITE_STRING("", LCD_PAGE5);
      LCD_WRITE_STRING("", LCD_PAGE6);
      LCD_WRITE_STRING("", LCD_PAGE7);
      LCD_WRITE_STRING_VALUE("Connected to ", gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0);
      
      connIdx = 0;
      
      return;
    }
  }
}
/*********************************************************************
 * @fn      HidEmuKbd_processGattMsg
 *
 * @brief   Process GATT messages
 *
 * @return  none
 */
static void HidEmuKbd_processGattMsg(gattMsgEvent_t *pMsg)
{
  GATT_bm_free(&pMsg->msg, pMsg->method);
}
Exemplo n.º 29
0
static void hidappProcessGATTMsg( gattMsgEvent_t *pPkt )
{
  // Build the message first
  switch ( pPkt->method )
  {
    case ATT_HANDLE_VALUE_NOTI:
      // First try to send out pending HID report
      if ( reportRetries > 0 )
      {
        hidappSendInReport( &lastInReport );
        
        // Free last report's payload
        GATT_bm_free( (gattMsg_t *)&lastInReport, ATT_HANDLE_VALUE_NOTI );
        
        // Zero out all fields of last report
        VOID osal_memset( &lastInReport, 0, sizeof( attHandleValueNoti_t ) );
      
        reportRetries = 0;
        osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY );
      }

      // Send incoming HID report
      if ( hidappSendInReport( &(pPkt->msg.handleValueNoti) ) == FALSE )
      {
        // Save report for retries later
        osal_memcpy( &lastInReport, &(pPkt->msg.handleValueNoti), sizeof( attHandleValueNoti_t ) );

        // Report's payload is part of lastInReport now so no need to free it yet
        pPkt->msg.handleValueNoti.pValue = NULL;
        
        reportRetries = 1;
        osal_start_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY, HIDAPP_INPUT_RETRY_TIMEOUT );
      }
      break;

    case ATT_FIND_BY_TYPE_VALUE_RSP:
      // Response from GATT_DiscPrimaryServiceByUUID
      // Service found, store handles
      if ( pPkt->msg.findByTypeValueRsp.numInfo > 0 )
      {
        serviceStartHandle = 
          ATT_ATTR_HANDLE(pPkt->msg.findByTypeValueRsp.pHandlesInfo, 0);
        serviceEndHandle = 
          ATT_GRP_END_HANDLE(pPkt->msg.findByTypeValueRsp.pHandlesInfo, 0);
      }
      // If procedure complete
      else if ( pPkt->hdr.status == bleProcedureComplete )
      {
        if ( serviceStartHandle != 0 )
        {
          if ( serviceToDiscover == GATT_SERVICE_UUID )
          {
            // Begin the search for characteristic handle of the service
            readReq.startHandle = serviceStartHandle;
            readReq.endHandle = serviceEndHandle;
            readReqType.len = 2;
            readReqType.uuid[0] = LO_UINT16(SERVICE_CHANGED_UUID);
            readReqType.uuid[1] = HI_UINT16(SERVICE_CHANGED_UUID);
            readReq.type = readReqType;

            GATT_DiscCharsByUUID(connHandle, &readReq, hidappTaskId );
          }
          else if ( serviceToDiscover == HID_SERV_UUID )
          {
            // Discover all characteristics
            GATT_DiscAllChars( connHandle, serviceStartHandle, serviceEndHandle, hidappTaskId );
          }
        }
      }
      break;

    case ATT_READ_BY_TYPE_RSP:
      // Response from Discover all Characteristics.
      // Success indicates packet with characteristic discoveries.
      if ( pPkt->hdr.status == SUCCESS )
      {
        attReadByTypeRsp_t *pRsp = &pPkt->msg.readByTypeRsp;
        uint8 idx = 0;

        if ( serviceToDiscover == GATT_SERVICE_UUID )
        {
          // We have discovered the GATT Service Characteristic handle
          serviceChangeHandle = BUILD_UINT16( pRsp->pDataList[3],
                                              pRsp->pDataList[4] );
          
          // Break to skip next part, it doesn't apply here
          break;
        }

        // Search characteristics for those with notification permissions.
        while( idx < ((pRsp->numPairs * pRsp->len) - 1) )
        {
          // Check permissions of characteristic for notification permission
          if ( (pRsp->pDataList[idx+2] & GATT_PROP_NOTIFY ) )
          {
            uint16* pHandle = (mouseCharHandle == GATT_INVALID_HANDLE) ? &mouseCharHandle : &keyCharHandle ;

            if ( pHandle == &keyCharHandle && consumerCtrlCharHandle == GATT_INVALID_HANDLE )
            {
              pHandle = ( keyCharHandle == GATT_INVALID_HANDLE ) ? &keyCharHandle : &consumerCtrlCharHandle;
            }

            if ( *pHandle == GATT_INVALID_HANDLE )
            {
              *pHandle = BUILD_UINT16( pRsp->pDataList[idx+3], pRsp->pDataList[idx+4] );
            }
          }

          idx += pRsp->len;
        }
      }
      // This indicates that there is no more characteristic data
      // to be discovered within the given handle range.
      else if ( pPkt->hdr.status == bleProcedureComplete )
      {
        if ( serviceToDiscover == GATT_SERVICE_UUID )
        {
          // Begin Service Discovery of HID Service
          serviceToDiscover = HID_SERV_UUID;
          hidappDiscoverService( connHandle, HID_SERV_UUID );
          // Break to skip next part, it doesn't apply yet.
          break;
        }

        if ( enableCCCDs == TRUE )
        {
          mouseCCCHandle = mouseCharHandle + 1;

          // Begin configuring the characteristics for notifications
          hidappEnableNotification( connHandle, mouseCCCHandle );
        }
        else
        {
          serviceDiscComplete = TRUE;
        }
      }
      break;

    case ATT_WRITE_RSP:
      if ( pPkt->hdr.status == SUCCESS && !serviceDiscComplete )
      {
        uint16 handle = ( keyCCCHandle == GATT_INVALID_HANDLE ) ?
                        ( keyCCCHandle = keyCharHandle + 1 ) :
                        ( consumerCtrlCCCHandle = consumerCtrlCharHandle + 1 );

        hidappEnableNotification( connHandle, handle );

        if ( consumerCtrlCCCHandle != GATT_INVALID_HANDLE)
        {
          serviceDiscComplete = TRUE;
        }
      }
      break;

    // Service Change indication
    case ATT_HANDLE_VALUE_IND:
      // Note: this logic assumes that the only indications that will be sent
      //       will come from that GATT Service Changed Characteristic
      if ( pPkt->hdr.status == SUCCESS )
      {
        serviceChange = CHANGE_OCCURED;

        // Acknowledge receipt of indication
        ATT_HandleValueCfm( pPkt->connHandle );

        // Handles in server have changed while devices are connected
        if ( ( gapBondMgrState == PAIRED_BONDED_STATE ) &&
            ( serviceChangeHandle == pPkt->msg.handleValueInd.handle ) )
        {
          // Begin Service Discovery of HID Service
          serviceToDiscover = HID_SERV_UUID;
          hidappDiscoverService( connHandle, HID_SERV_UUID );

          serviceChange = NO_CHANGE;
        }
      }
      break;

    default:
      // Unknown event
      break;
  }
  
  GATT_bm_free( &pPkt->msg, pPkt->method );
}
Exemplo n.º 30
0
/*******************************************************************************
 * @fn      SensorTag_processGATTMsg
 *
 * @brief   Process GATT messages
 *
 * @return  none
 */
static void SensorTag_processGATTMsg(gattMsgEvent_t *pMsg)
{
  GATT_bm_free(&pMsg->msg, pMsg->method);
}