Exemple #1
0
/*********************************************************************
 * @fn      SNP_processStateChangeEvt
 *
 * @brief   Process a pending GAP Role state change event.
 *
 * @param   newState - new state
 *
 * @return  None.
 */
void SNP_processStateChangeEvt(gaprole_States_t newState)
{
  static bool firstConnFlag = false;
  static gaprole_States_t currentState = GAPROLE_STARTED;
  static uint16_t currentConnectHandle;
  
 
  switch (newState)
  {
    case GAPROLE_STARTED:
      GAPRole_GetParameter(GAPROLE_CONNHANDLE, &currentConnectHandle);
      break;

    case GAPROLE_ADVERTISING:
      break;

    case GAPROLE_ADVERTISING_NONCONN:
    /* After a connection is dropped a device will continue
     * sending non-connectable advertisements and shall sending this change of 
     * state to the application.  These are then disabled here so that sending 
     * connectable advertisements can resume.
     */
      {
        if(firstConnFlag)
        {
          // We were in a connection.
          uint8_t param[3];

          param[0] = LO_UINT16(currentConnectHandle);
          param[1] = HI_UINT16(currentConnectHandle);
          GAPRole_GetParameter(GAPROLE_CONN_TERM_REASON, &param[2]);

          //reset the GATT state for this connection handle
          SNP_resetGATT(*((uint16_t*) &param[0])); 
          //Connection Ended
          SNP_eventToHost_send(SNP_CONN_TERM_EVT, NULL, sizeof(param), param);
        }
        // Reset flag for next connection.
        firstConnFlag = false;
      }
      break;
    case GAPROLE_CONNECTED:
      if(firstConnFlag == false)
      {
        uint8_t peerAddress[B_ADDR_LEN];

        GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
        GAPRole_GetParameter(GAPROLE_CONNHANDLE, &currentConnectHandle);
        {
          uint8_t param[15];
          GAPRole_GetParameter(GAPROLE_CONNHANDLE, &param[0]);
          GAPRole_GetParameter(GAPROLE_CONN_INTERVAL, &param[2]);
          GAPRole_GetParameter(GAPROLE_CONN_LATENCY, &param[4]);
          GAPRole_GetParameter(GAPROLE_CONN_TIMEOUT, &param[6]);
          GAPRole_GetParameter(GAPROLE_BD_ADDR_TYPE, &param[8]);
          memcpy(&param[9], peerAddress, 6);
          //Advertisement Ended due to the connection
          SNP_eventToHost_send(SNP_CONN_EST_EVT, 
                                NULL, sizeof(param), param);
        }

        // if 4.1 feature are enable on the controller, 
        // then the adv needs to be forced to 
        // be non-connectable, since peripheral.c does not support multiple 
        // connection.
        // Only turn advertising on for this state when we first connect
        // otherwise, when we go from connected_advertising back to this 
        // state we will be turning advertising back on.
        firstConnFlag = true;                   
      }
      break;

    case GAPROLE_CONNECTED_ADV:
      break;

    case GAPROLE_WAITING:
      {
        if(firstConnFlag)
        {
          // We were in a connection.
          uint8_t param[3];
          
          param[0] = LO_UINT16(currentConnectHandle);
          param[1] = HI_UINT16(currentConnectHandle);
          GAPRole_GetParameter(GAPROLE_CONN_TERM_REASON, &param[2]);

          //reset the GATT state for this connection handle
          SNP_resetGATT(*((uint16_t*)&param[0])); 
          //Connection Ended
          SNP_eventToHost_send(SNP_CONN_TERM_EVT, NULL, sizeof(param), param);
         
          // Reset flag for next connection.
          firstConnFlag = false;
        }        
      }
      break;

    case GAPROLE_WAITING_AFTER_TIMEOUT:
      if(firstConnFlag)
      {
          uint8_t param[3];
          param[0] = LO_UINT16(currentConnectHandle);
          param[1] = HI_UINT16(currentConnectHandle);
          GAPRole_GetParameter(GAPROLE_CONN_TERM_REASON, &param[2]);

          //reset the GATT state for this connection handle
          SNP_resetGATT(*((uint16_t*) &param[0])); 
          
          //Connection Ended
          SNP_eventToHost_send(SNP_CONN_TERM_EVT, 
                                NULL, sizeof(param), param);
      } 
      // Reset flag for next connection.
      firstConnFlag = false;
     break;

    case GAPROLE_ERROR:
      break;

    default:
      break;
  }
  SNP_AdvStateChange(newState, currentState);
  currentState = newState;
}
/*********************************************************************
 * @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;
}
Exemple #3
0
/*********************************************************************
 * @fn      GlucoseDevInfoDisc
 *
 * @brief   Current glucose service and characteristic discovery. 
 *
 * @param   state - Discovery state.
 * @param   pMsg - GATT message.
 *
 * @return  New discovery state.
 */
static uint8_t GlucoseDevInfoDisc(uint8_t state, gattMsgEvent_t *pMsg)
{
  uint8_t newState = state;
  
  switch (state)
  {
    case DISC_DEVINFO_START:  
      {
        uint8_t uuid[ATT_BT_UUID_SIZE] = { LO_UINT16(DEVINFO_SERV_UUID),
                                           HI_UINT16(DEVINFO_SERV_UUID) };

        // Initialize service discovery variables
        glucoseSvcStartHdl = glucoseSvcEndHdl = 0;
        glucoseEndHdlIdx = 0;
        
        // Discover service by UUID
        GATT_DiscPrimaryServiceByUUID(glucCollConnHandle, uuid,
                                      ATT_BT_UUID_SIZE, glucCollTaskId);      

        newState = DISC_DEVINFO_SVC;
      } 
      break;

    case DISC_DEVINFO_SVC:
      // Service found, store handles
      if (pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
          pMsg->msg.findByTypeValueRsp.numInfo > 0)
      {
        glucoseSvcStartHdl = 
          ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
        glucoseSvcEndHdl = 
          ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
      }
      
      // If procedure complete
      if ((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  && 
           pMsg->hdr.status == bleProcedureComplete) ||
          (pMsg->method == ATT_ERROR_RSP))
      {
        // If service found
        if (glucoseSvcStartHdl != 0)
        {
          // Discover all characteristics
          GATT_DiscAllChars(glucCollConnHandle, glucoseSvcStartHdl,
                            glucoseSvcEndHdl, glucCollTaskId);
          
          newState = DISC_DEVINFO_CHAR;
        }
        else
        {
          // Service not found
          newState = DISC_FAILED;
        }
      }    
      break;

    case DISC_DEVINFO_CHAR:
      {
        uint8_t   i;
        uint8_t   *p;
        uint16_t  handle;
        uint16_t  uuid;
        
        // Characteristics found
        if (pMsg->method == ATT_READ_BY_TYPE_RSP &&
            pMsg->msg.readByTypeRsp.numPairs > 0 && 
            pMsg->msg.readByTypeRsp.len == CHAR_DESC_HDL_UUID16_LEN)
        {
          // For each characteristic declaration
          p = pMsg->msg.readByTypeRsp.pDataList;
          
          for (i = pMsg->msg.readByTypeRsp.numPairs; i > 0; i--)
          {
            // Parse characteristic declaration
            handle = BUILD_UINT16(p[3], p[4]);
            uuid = BUILD_UINT16(p[5], p[6]);
                   
            // If UUID is of interest, store handle
            switch (uuid)
            {
              case MANUFACTURER_NAME_UUID:
                glucoseHdlCache[HDL_DEVINFO_MANUFACTURER_NAME] = handle;
                break;                
                
              case SYSTEM_ID_UUID:
                glucoseHdlCache[HDL_DEVINFO_SYSTEM_ID] = handle;
                break;
                
              case MODEL_NUMBER_UUID:
                glucoseHdlCache[HDL_DEVINFO_MODEL_NUM] = handle;
                break;
                
              default:
                break;
            }
            
            p += CHAR_DESC_HDL_UUID16_LEN;
          }
        }
          
        // If procedure complete
        if ((pMsg->method == ATT_READ_BY_TYPE_RSP  && 
             pMsg->hdr.status == bleProcedureComplete) ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          // If didn't find required device info
          if (glucoseHdlCache[HDL_DEVINFO_MANUFACTURER_NAME] == 0 ||
              glucoseHdlCache[HDL_DEVINFO_SYSTEM_ID] == 0 ||
              glucoseHdlCache[HDL_DEVINFO_MODEL_NUM] == 0)
          {
            newState = DISC_FAILED;
          }
          else
          {
            newState = DISC_IDLE;
          }
        }
      }      
      break;
      
    default:
      break;
  }
  
  return newState;
}
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;
}
Exemple #5
0
#define PP_DEFAULT_PATH_LOSS              0x7F

#define SERVAPP_NUM_ATTR_SUPPORTED        5

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

// Link Loss Service UUID
CONST uint8 linkLossServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16( LINK_LOSS_SERV_UUID ), HI_UINT16( LINK_LOSS_SERV_UUID )
};

// Immediate Alert Service UUID
CONST uint8 imAlertServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16( IMMEDIATE_ALERT_SERV_UUID ), HI_UINT16( IMMEDIATE_ALERT_SERV_UUID )
};

// Tx Power Level Service UUID
CONST uint8 txPwrLevelServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16( TX_PWR_LEVEL_SERV_UUID ), HI_UINT16( TX_PWR_LEVEL_SERV_UUID )
};

// Alert Level Attribute UUID
 * CONSTANTS
 */

#define SERVAPP_NUM_ATTR_SUPPORTED        18

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
// Simple GATT Profile Service UUID: 0xFFF0
CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};

// Characteristic 1 UUID: 0xFFF1
CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)
};

// Characteristic 2 UUID: 0xFFF2
CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID)
};

// Characteristic 3 UUID: 0xFFF3
uint8 glucoseCtlPntWriteFilter(uint8 opcode, uint8 oper, uint8 filterType,
                               void* param1, void* param2)
{
  attWriteReq_t writeReq;
  UTCTimeStruct *time1, *time2;
  uint16 *seqNum1, *seqNum2;
  
  uint8 *p = writeReq.value;
  
  *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.value);
  writeReq.sig = 0;
  writeReq.cmd = 0;
  
  writeReq.handle = glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_START];
  return GATT_WriteCharValue( glucCollConnHandle, &writeReq, glucCollTaskId );
}
    'm',
    'e',
    't',
    'e',
    'r',
    'S',
    'e',
    'n',
    's',
    'o',
    'r',
    // connection interval range
    0x05,   // length of this data
    GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
    LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),   // 100ms
    HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
    LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),   // 1s
    HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),

    // Tx power level
    GAP_ADTYPE_POWER_LEVEL,
    0       // 0dBm
};

// Advertisement data
static uint8 advertData[] =
{
    // Flags; this sets the device to use limited discoverable
    // mode (advertises for 30 seconds at a time) instead of general
    // discoverable mode (advertises indefinitely)
    0x02,   // length of this data
/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
// Lights GATT Profile Service UUID: 0xFFB0
CONST uint8 lightsProfileServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(LIGHTSPROFILE_SERV_UUID), HI_UINT16(LIGHTSPROFILE_SERV_UUID)
};

// Characteristic Red UUID: 0xFFB1
CONST uint8 lightsProfileRedUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(LIGHTSPROFILE_RED_UUID), HI_UINT16(LIGHTSPROFILE_RED_UUID)
};

// Characteristic Green UUID: 0xFFB2
CONST uint8 lightsProfileGreenUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(LIGHTSPROFILE_GREEN_UUID), HI_UINT16(LIGHTSPROFILE_GREEN_UUID)
};

// Characteristic Blue UUID: 0xFFB3
Exemple #10
0
/*********************************************************************
 * @fn      thermometer_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 thermometer_HandleKeys( uint8 shift, uint8 keys )
{

    bStatus_t status;
    uint8 notify_interval;

    if ( keys & HAL_KEY_SW_1 )
    {
        // set simulated measurement flag index
        thermometerFlagsIdx+=1;

        if (thermometerFlagsIdx == FLAGS_IDX_MAX)
        {
            thermometerFlagsIdx = 0;
        }
    }


    //read stored interval value
    Thermometer_GetParameter( THERMOMETER_INTERVAL, &notify_interval );

    if(notify_interval == 0)
    {
        thMeasTimerRunning = FALSE;
    }

    if ( keys & HAL_KEY_SW_2 )
    {
        // if device is not in a connection, pressing the right key should toggle
        // advertising on and off. If timer is running, then will adv when meas is ready
        if((gapProfileState != GAPROLE_CONNECTED) &&  (thMeasTimerRunning == FALSE))
        {
            uint8 current_adv_enabled_status;
            uint8 new_adv_enabled_status;

            //Find the current GAP advertisement status
            GAPRole_GetParameter( GAPROLE_ADVERT_ENABLED, &current_adv_enabled_status );

            if ( current_adv_enabled_status == FALSE )
            {
                new_adv_enabled_status = TRUE;
            }
            else
            {
                new_adv_enabled_status = FALSE;
            }

            //change the GAP advertisement status to opposite of current status
            GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &new_adv_enabled_status );
        }
        else //timer is running, so allow simulated changes
        {
            //change temperature, remove single precision
            if((thermometerCelcius) < 0X000175)
            {
                thermometerCelcius +=1;
            }
            else
            {
                uint16 thInterval = 30;

                thermometerCelcius = 0X000173;

                //Simulate interval change
                Thermometer_SetParameter( THERMOMETER_INTERVAL, THERMOMETER_INTERVAL_LEN,
                                          &thInterval );
                if(temperatureIntervalConfig == true)
                {
                    attHandleValueInd_t intervalInd;

                    intervalInd.pValue = GATT_bm_alloc( gapConnHandle, ATT_HANDLE_VALUE_IND,
                                                        THERMOMETER_INTERVAL_LEN, NULL );
                    if ( intervalInd.pValue != NULL )
                    {
                        intervalInd.len = THERMOMETER_INTERVAL_LEN;
                        intervalInd.pValue[0] = LO_UINT16(thInterval);
                        intervalInd.pValue[1] = HI_UINT16(thInterval);
                        intervalInd.handle = THERMOMETER_INTERVAL_VALUE_POS;

                        status = Thermometer_IntervalIndicate( gapConnHandle, &intervalInd,
                                                               thermometerTaskId );
                        // we can fail if there was pending meas or not connected
                        if (status != SUCCESS)
                        {
                            //queue indication
                            thermometerStoreIndications(&intervalInd);
                        }
                    }
                }
            }
        }
    }
}
Exemple #11
0
/*********************************************************************
 * @fn      thermometerMeasIndicate
 *
 * @brief   Prepare and send a thermometer measurement indication
 *
 * @return  none
 */
static void thermometerMeasIndicate(void)
{
    // Thermometer measurement value stored in this structure.
    attHandleValueInd_t thermometerMeas;

    thermometerMeas.pValue = GATT_bm_alloc(gapConnHandle,
                                           ATT_HANDLE_VALUE_IND,
                                           THERMOMETER_MEAS_LEN, NULL);
    if (thermometerMeas.pValue != NULL)
    {
        // att value notification structure
        uint8 *p = thermometerMeas.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;
        }

        thermometerMeas.len = (uint8) (p - thermometerMeas.pValue);
        thermometerMeas.handle = THERMOMETER_TEMP_VALUE_POS;

        // Queue indication.
        thermometerStoreIndications( &thermometerMeas);

        //advertise measurement is ready
        thermometer_Advertise();
    }
}
Exemple #12
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 );
            }
        }
    }
}
  's',
  'u',
  'r',
  'e',
  ' ',
  'S',
  'e',
  'n',
  's',
  'o',
  'r',  
    // connection interval range
  0x05,   // length of this data
  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
  LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),   // 100ms
  HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),  
  LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),   // 1s
  HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),  
  0x02,   // length of this data
  GAP_ADTYPE_POWER_LEVEL, //TX Power Level
  0       // 0dBm  
};

// Advertisement data
static uint8 advertData[] = 
{ 
  // Flags; this sets the device to use limited discoverable
  // mode (advertises for 30 seconds at a time) instead of general
  // discoverable mode (advertises indefinitely)
  0x02,   // length of this data
  GAP_ADTYPE_FLAGS,
/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
// Device information service
CONST uint8 devInfoServUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(DEVINFO_SERV_UUID), HI_UINT16(DEVINFO_SERV_UUID)
};

// System ID
CONST uint8 devInfoSystemIdUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SYSTEM_ID_UUID), HI_UINT16(SYSTEM_ID_UUID)
};

// Model Number String
CONST uint8 devInfoModelNumberUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(MODEL_NUMBER_UUID), HI_UINT16(MODEL_NUMBER_UUID)
};

// Serial Number String
  's',
  'o',
  'r',
};

static uint8 advertData[] =
{
  // flags
  0x02,
  GAP_ADTYPE_FLAGS,
  GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
  // service UUIDs
  0x03,
  GAP_ADTYPE_16BIT_MORE,
  LO_UINT16(RSC_SERV_UUID),
  HI_UINT16(RSC_SERV_UUID),
};

// Device name attribute value
static uint8 attDeviceName[GAP_DEVICE_NAME_LEN] = "RSC Sensor";

// GAP connection handle
static uint16 gapConnHandle;

// Running measurement value stored in this structure
static attHandleValueNoti_t sensorMeas;

// Flags for simulated measurements
static const uint8 sensorFlags[FLAGS_IDX_MAX] =
{
  RSC_FLAGS_ALL,
Exemple #16
0
/*********************************************************************
 * @fn      SerialApp_ProcessMSGCmd
 *
 * @brief   Data message processor callback. This function processes
 *          any incoming data - probably from other devices. Based
 *          on the cluster ID, perform the intended action.
 *
 * @param   pkt - pointer to the incoming message packet
 *
 * @return  TRUE if the 'pkt' parameter is being used and will be freed later,
 *          FALSE otherwise.
 */
void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
{
  uint8 stat;
  uint8 seqnb;
  uint8 delay;

  switch ( pkt->clusterId )
  {
  // A message with a serial data block to be transmitted on the serial port.
  case SERIALAPP_CLUSTERID1:
    seqnb = pkt->cmd.Data[0];

    // Keep message if not a repeat packet
    if ( (seqnb > SerialApp_SeqRx) ||                    // Normal
        ((seqnb < 0x80 ) && ( SerialApp_SeqRx > 0x80)) ) // Wrap-around
    {
      // Transmit the data on the serial port.
      if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1,
                                         (pkt->cmd.DataLength-1) ) )
      {
        // Save for next incoming message
        SerialApp_SeqRx = seqnb;

        stat = OTA_SUCCESS;
      }
      else
      {
        stat = OTA_SER_BUSY;
      }
    }
    else
    {
      stat = OTA_DUP_MSG;
    }

    // Select approproiate OTA flow-control delay.
    delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;

    // Build & send OTA response message.
    rspBuf[0] = stat;
    rspBuf[1] = seqnb;
    rspBuf[2] = LO_UINT16( delay );
    rspBuf[3] = HI_UINT16( delay );
    stat = AF_DataRequest( &(pkt->srcAddr), (endPointDesc_t*)&SerialApp_epDesc,
                            SERIALAPP_CLUSTERID2, SERIAL_APP_RSP_CNT , rspBuf,
                           &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );

    if ( stat != afStatus_SUCCESS )
    {
      osal_start_timerEx( SerialApp_TaskID, SERIALAPP_RSP_RTRY_EVT,
                                            SERIALAPP_RSP_RTRY_TIMEOUT );

      // Store the address for the timeout retry.
      osal_memcpy(&SerialApp_RspDstAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));
    }
    HalLedSet(HAL_LED_2,HAL_LED_MODE_ON);
    break;

  // A response to a received serial data block.
  case SERIALAPP_CLUSTERID2:
    if ( (pkt->cmd.Data[1] == SerialApp_SeqTx) &&
        ((pkt->cmd.Data[0] == OTA_SUCCESS) ||
         (pkt->cmd.Data[0] == OTA_DUP_MSG)) )
    {
      // Remove timeout waiting for response from other device.
      osal_stop_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT );
      FREE_OTABUF();
      HalLedSet(HAL_LED_2,HAL_LED_MODE_ON);
    }
    else
    {
      delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
      // Re-start timeout according to delay sent from other device.
      osal_start_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT, delay );
    }
    break;
#ifndef   ZDO_COORDINATOR
  case SERIALAPP_CLUSTERID_CMD:
    CommandToBox(pkt->cmd.Data[1]);
    break;
#endif
  default:
      break;
  }
}
/*********************************************************************
 * @fn      sensorMeasNotify
 *
 * @brief   Prepare and send a RSC measurement notification
 *
 * @return  none
 */
static void sensorMeasNotify(void)
{
  static uint16 centimeters = 0;
  uint8 *p = sensorMeas.value;
  uint8 flags = sensorFlags[sensorFlagsIdx];

  switch( motion )
  {
    case STANDING_STILL:
      instSpeed = instCadence = instStrideLength =  STANDING_STILL;
      // 0 for walking bit
      flags = flags & 0xFB; //0b1111 1011
      break;

    case WALKING_MOTION:
      instStrideLength = STRIDE_LENGTH_WALKING;
      instCadence = WALKING_CADENCE;
      instSpeed = WALKING_SPEED;
      // 0 for walking bit
      flags = flags & 0xFB;
      break;

    case RUNNING_MOTION:
      instStrideLength = STRIDE_LENGTH_RUNNING;
      instCadence = RUNNING_CADENCE;
      instSpeed = RUNNING_SPEED;
      // set in 1 for walking bit.
      flags = flags | 0x04;
      break;

    default: // Do nothing
      break;
  }

  // Add distance
  centimeters += (uint16)DISTANCE_TRAVELED( instSpeed );

  // If traveled at least a meter
  if ( centimeters >= 100 )
  {
    // add distance, truncated to meters
    totalDistance += (centimeters / 100);
    // and continue to store the remaining centimeters
    centimeters %= 100;
  }

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

  //Included regardless of flags.
  *p++ = LO_UINT16( instSpeed );
  *p++ = HI_UINT16( instSpeed );
  *p++ = instCadence;

  if (flags & RSC_FLAGS_STRIDE)
  {
    *p++ = LO_UINT16( instStrideLength );
    *p++ = HI_UINT16( instStrideLength );
  }

  if (flags & RSC_FLAGS_DIST)
  {
    *p++ = BREAK_UINT32(totalDistance, 0);
    *p++ = BREAK_UINT32(totalDistance, 1);
    *p++ = BREAK_UINT32(totalDistance, 2);
    *p++ = BREAK_UINT32(totalDistance, 3);
  }

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

  // Send to service to send the notification
  Running_MeasNotify( gapConnHandle, &sensorMeas );
}
Exemple #18
0
/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

/**
 * GATT Service
 */

// Immediate Alert Service UUID: 0xFF10
CONST uint8 imAlertServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(IM_ALERT_SERV_UUID), HI_UINT16(IM_ALERT_SERV_UUID)
};

/**
 * GATT Characteristic Types
 */

// Alert Level UUID: 0xFF11
CONST uint8 imAlertLevelUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(IM_ALERT_LEVEL_UUID), HI_UINT16(IM_ALERT_LEVEL_UUID)
};

/*********************************************************************
 * GLOBAL FUNCTIONS
 */
  0x50,   // 'P'
  0x65,   // 'e'
  0x72,   // 'r'
  0x69,   // 'i'
  0x70,   // 'p'
  0x68,   // 'h'
  0x65,   // 'e'
  0x72,   // 'r'
  0x61,   // 'a'
  0x6c,   // 'l'

  // connection interval range
  0x05,   // length of this data
  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
  LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),   // 100ms
  HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
  LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),   // 1s
  HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),

  // Tx power level
  0x02,   // length of this data
  GAP_ADTYPE_POWER_LEVEL,
  0       // 0dBm
};

// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 advertData[] =
{
  // Flags; this sets the device to use limited discoverable
  // mode (advertises for 30 seconds at a time) instead of general
  NULL                       // Authorization callback function pointer
};









// reverse uuid

CONST uint8 BXServUUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(BX_SERV_UUID), HI_UINT16(BX_SERV_UUID)
};


CONST uint8 BXchar1UUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(BX_CHAR1_UUID), HI_UINT16(BX_CHAR1_UUID)
};

CONST uint8 BXchar2UUID[ATT_BT_UUID_SIZE] =
{ 
  LO_UINT16(BX_CHAR2_UUID), HI_UINT16(BX_CHAR2_UUID)
};


// Delay a time to make sure the coordinator can receive data
// if not delay the coordinator can't receive data from other node
#define MONITOR_SEND_DELAY			(RESPONSE_POLL_RATE * 2)

// resend delay
#define MONITOR_RESEND_DELAY	10

/*********************************************************************
 * CONSTANTS
 */
// ACK
const byte ACK[] = {
  0xFE,
  0x00,
  LO_UINT16(ACK_CMD),
  HI_UINT16(ACK_CMD),
  0x00, 
  0x00,
  0x00};

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
// This list should be filled with Application specific Cluster IDs.
const cId_t Monitor_ClusterInList[Monitor_MAX_IN_CLUSTERS] =
{
	ZIGBEE_COMMON_CLUSTER
Exemple #22
0
/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

/**
 * GATT Services
 */
// Generic Access Profile Service UUID
CONST uint8 gapServiceUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16( GAP_SERVICE_UUID ), HI_UINT16( GAP_SERVICE_UUID )
};

// Generic Attribute Profile Service UUID
CONST uint8 gattServiceUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16( GATT_SERVICE_UUID ), HI_UINT16( GATT_SERVICE_UUID )
};

/**
 * GATT Declarations
 */
// Primary Service UUID
CONST uint8 primaryServiceUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16( GATT_PRIMARY_SERVICE_UUID ), HI_UINT16( GATT_PRIMARY_SERVICE_UUID )
/***************************************************************************************************
 * @fn          MT_AfIncomingMsg
 *
 * @brief       Process the callback subscription for AF Incoming data.
 *
 * @param       pkt - Incoming AF data.
 *
 * @return      none
 ***************************************************************************************************/
void MT_AfIncomingMsg(afIncomingMSGPacket_t *pMsg)
{
  #define MT_AF_INC_MSG_LEN  17
  #define MT_AF_INC_MSG_EXT  10

  uint16 dataLen = pMsg->cmd.DataLength;  // Length of the data section in the response packet.
  uint16 respLen = MT_AF_INC_MSG_LEN + dataLen;
  uint8 cmd = MT_AF_INCOMING_MSG;
  uint8 *pRsp, *pTmp;
  mtAfInMsgList_t *pItem = NULL;

#if defined INTER_PAN
  if (StubAPS_InterPan(pMsg->srcAddr.panId, pMsg->srcAddr.endPoint))
  {
    cmd = MT_AF_INCOMING_MSG_EXT;
  }
  else
#endif
  if ((pMsg->srcAddr.addrMode == afAddr64Bit) ||
      (respLen > (uint16)(MT_RPC_DATA_MAX - MT_AF_INC_MSG_EXT)))
  {
    cmd = MT_AF_INCOMING_MSG_EXT;
  }

  if (cmd == MT_AF_INCOMING_MSG_EXT)
  {
    respLen += MT_AF_INC_MSG_EXT;
  }

  if (respLen > (uint16)MT_RPC_DATA_MAX)
  {
    if ((pItem = (mtAfInMsgList_t *)osal_mem_alloc(sizeof(mtAfInMsgList_t) + dataLen)) == NULL)
    {
      return;  // If cannot hold a huge message, cannot give indication at all.
    }

    pItem->data = (uint8 *)(pItem+1);
    respLen -= dataLen;  // Zero data bytes are sent with an over-sized incoming indication.
  }

  // Attempt to allocate memory for the response packet.
  if ((pRsp = osal_mem_alloc(respLen)) == NULL)
  {
    if (pItem != NULL)
    {
      (void)osal_mem_free(pItem);
    }
    return;
  }
  pTmp = pRsp;

  /* Group ID */
  *pTmp++ = LO_UINT16(pMsg->groupId);
  *pTmp++ = HI_UINT16(pMsg->groupId);

  /* Cluster ID */
  *pTmp++ = LO_UINT16(pMsg->clusterId);
  *pTmp++ = HI_UINT16(pMsg->clusterId);

  if (cmd == MT_AF_INCOMING_MSG_EXT)
  {
    *pTmp++ = pMsg->srcAddr.addrMode;

    if (pMsg->srcAddr.addrMode == afAddr64Bit)
    {
      (void)osal_memcpy(pTmp, pMsg->srcAddr.addr.extAddr, Z_EXTADDR_LEN);
    }
    else
    {
      pTmp[0] = LO_UINT16(pMsg->srcAddr.addr.shortAddr);
      pTmp[1] = HI_UINT16(pMsg->srcAddr.addr.shortAddr);
    }
    pTmp += Z_EXTADDR_LEN;

    *pTmp++ = pMsg->srcAddr.endPoint;
#if defined INTER_PAN
    *pTmp++ = LO_UINT16(pMsg->srcAddr.panId);
    *pTmp++ = HI_UINT16(pMsg->srcAddr.panId);
#else
    *pTmp++ = 0;
    *pTmp++ = 0;
#endif
  }
  else
  {
    /* Source Address */
    *pTmp++ = LO_UINT16(pMsg->srcAddr.addr.shortAddr);
    *pTmp++ = HI_UINT16(pMsg->srcAddr.addr.shortAddr);

    /* Source EP */
    *pTmp++ = pMsg->srcAddr.endPoint;
  }

  /* Destination EP */
  *pTmp++ = pMsg->endPoint;

  /* WasBroadCast */
  *pTmp++ = pMsg->wasBroadcast;

  /* LinkQuality */
  *pTmp++ = pMsg->LinkQuality;

  /* SecurityUse */
  *pTmp++ = pMsg->SecurityUse;

  /* Timestamp */
  *pTmp++ = BREAK_UINT32(pMsg->timestamp, 0);
  *pTmp++ = BREAK_UINT32(pMsg->timestamp, 1);
  *pTmp++ = BREAK_UINT32(pMsg->timestamp, 2);
  *pTmp++ = BREAK_UINT32(pMsg->timestamp, 3);


  /* Data Length */
  if (cmd == MT_AF_INCOMING_MSG_EXT)
  {
    /* Z-Tool apparently takes the last Byte before the data buffer as the dynamic length and
     * ignores the bigger UInt16 length of an EXT incoming message. But no data bytes will be sent
     * with a huge message, so it's necessary to work-around and fake-out Z-Tool with a zero here.
     */
    *pTmp++ = 0;  // TODO - workaround Z-Tool shortcoming; should be: = pMsg->cmd.TransSeqNumber;
    *pTmp++ = LO_UINT16(dataLen);
    *pTmp++ = HI_UINT16(dataLen);
  }
  else
  {
    *pTmp++ = pMsg->cmd.TransSeqNumber;
    *pTmp++ = dataLen;
  }

  /* Data */
  if (pItem != NULL)
  {
    // Enqueue the new huge incoming item.
    pItem->next = pMtAfInMsgList;
    pMtAfInMsgList = pItem;

    // Setup to time-out the huge incoming item if host does not MT_AF_DATA_RETRIEVE it.
    pItem->tick = MT_AF_EXEC_CNT;
    if (ZSuccess != osal_start_timerEx(MT_TaskID, MT_AF_EXEC_EVT, MT_AF_EXEC_DLY))
    {
      (void)osal_set_event(MT_TaskID, MT_AF_EXEC_EVT);
    }

    pItem->timestamp = pMsg->timestamp;
    (void)osal_memcpy(pItem->data, pMsg->cmd.Data, dataLen);
  }
  else
  {
    (void)osal_memcpy(pTmp, pMsg->cmd.Data, dataLen);
  }

  /* Build and send back the response */
  MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ|(uint8)MT_RPC_SYS_AF), cmd, respLen, pRsp);

  (void)osal_mem_free(pRsp);
}
Exemple #24
0
/*********************************************************************
 * @fn      hidappDiscoverService
 *
 * @brief   Discover service using UUID.
 *
 * @param   connHandle - connection handle to do discovery on
 * @param   svcUuid - service UUID to discover
 *
 * @return  none
 */
static void hidappDiscoverService( uint16 connHandle, uint16 svcUuid )
{
  uint8 uuid[2] = {LO_UINT16(svcUuid), HI_UINT16(svcUuid)};

  VOID GATT_DiscPrimaryServiceByUUID( connHandle, uuid, ATT_BT_UUID_SIZE, hidappTaskId );
}
Exemple #25
0
  'd'
};

// Advertising data
static uint8 advData[] =
{
  // flags
  0x02,   // length of this data
  GAP_ADTYPE_FLAGS,
  GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

  // appearance
  0x03,   // length of this data
  GAP_ADTYPE_APPEARANCE,
  LO_UINT16(GAP_APPEARE_HID_KEYBOARD),
  HI_UINT16(GAP_APPEARE_HID_KEYBOARD),

  // service UUIDs
  0x05,   // length of this data
  GAP_ADTYPE_16BIT_MORE,
  LO_UINT16(HID_SERVICE_UUID),
  HI_UINT16(HID_SERVICE_UUID),
  LO_UINT16(BATT_SERVICE_UUID),
  HI_UINT16(BATT_SERVICE_UUID)
};

// Device name attribute value
static CONST uint8 attDeviceName[GAP_DEVICE_NAME_LEN] = "HID Keyboard";

// HID Dev configuration
static hidDevCfg_t hidEmuKbdCfg =
Exemple #26
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 );

        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 ) );

        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 = pPkt->msg.findByTypeValueRsp.handlesInfo[0].handle;
        serviceEndHandle   = pPkt->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle;
      }
      // 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_SERVICE_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 rsp = pPkt->msg.readByTypeRsp;
        uint8 idx = 0;

        if ( serviceToDiscover ==  GATT_SERVICE_UUID )
        {
          // We have discovered the GATT Service Characteristic handle
          uint8 low = LO_UINT16(pPkt->msg.readByTypeRsp.dataList[3]);
          uint8 high = HI_UINT16(pPkt->msg.readByTypeRsp.dataList[4]);
          serviceChangeHandle = BUILD_UINT16(low, high);
          // Break to skip next part, it doesn't apply here
          break;
        }

        // Search characteristics for those with notification permissions.
        while( idx < ((rsp.numPairs * rsp.len ) - 1))
        {
          // Check permissions of characteristic for notification permission
          if ( (rsp.dataList[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( rsp.dataList[idx+3], rsp.dataList[idx+4] );
            }
          }

          idx += rsp.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_SERVICE_UUID;
          hidappDiscoverService( connHandle, HID_SERVICE_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_SERVICE_UUID;
          hidappDiscoverService( connHandle, HID_SERVICE_UUID );

          serviceChange = NO_CHANGE;
        }
      }
      break;

    default:
      // Unknown event
      break;
  }
}
Exemple #27
0
/*********************************************************************
 * @fn      GlucoseDisc
 *
 * @brief   Current glucose service and characteristic discovery. 
 *
 * @param   state - Discovery state.
 * @param   pMsg - GATT message.
 *
 * @return  New discovery state.
 */
static uint8_t GlucoseDisc(uint8_t state, gattMsgEvent_t *pMsg)
{
  uint8_t newState = state;
  
  switch (state)
  {
    case DISC_GLUCOSE_START:  
      {
        uint8_t uuid[ATT_BT_UUID_SIZE] = { LO_UINT16(GLUCOSE_SERV_UUID),
                                           HI_UINT16(GLUCOSE_SERV_UUID) };

        // Initialize service discovery variables
        glucoseSvcStartHdl = glucoseSvcEndHdl = 0;
        glucoseEndHdlIdx = 0;
        
        // Discover service by UUID
        GATT_DiscPrimaryServiceByUUID(glucCollConnHandle, uuid,
                                      ATT_BT_UUID_SIZE, glucCollTaskId);      

        newState = DISC_GLUCOSE_SVC;
      } 
      break;

    case DISC_GLUCOSE_SVC:
      // Service found, store handles
      if (pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
          pMsg->msg.findByTypeValueRsp.numInfo > 0)
      {
        glucoseSvcStartHdl = 
          ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
        glucoseSvcEndHdl = 
          ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
      }
      
      // If procedure complete
      if ((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  && 
           pMsg->hdr.status == bleProcedureComplete) ||
          (pMsg->method == ATT_ERROR_RSP))
      {
        // If service found
        if (glucoseSvcStartHdl != 0)
        {
          // Discover all characteristics
          GATT_DiscAllChars(glucCollConnHandle, glucoseSvcStartHdl,
                            glucoseSvcEndHdl, glucCollTaskId);
          
          newState = DISC_GLUCOSE_CHAR;
        }
        else
        {
          // Service not found
          newState = DISC_FAILED;
        }
      }
      break;

    case DISC_GLUCOSE_CHAR:
      {
        uint8_t   i;
        uint8_t   *p;
        uint16_t  handle;
        uint16_t  uuid;

        // Characteristics found
        if (pMsg->method == ATT_READ_BY_TYPE_RSP &&
            pMsg->msg.readByTypeRsp.numPairs > 0 && 
            pMsg->msg.readByTypeRsp.len == CHAR_DESC_HDL_UUID16_LEN)
        {
          // For each characteristic declaration
          p = pMsg->msg.readByTypeRsp.pDataList;

          for (i = pMsg->msg.readByTypeRsp.numPairs; i > 0; i--)
          {
            // Parse characteristic declaration
            handle = BUILD_UINT16(p[3], p[4]);
            uuid = BUILD_UINT16(p[5], p[6]);

            // If looking for end handle
            if (glucoseEndHdlIdx != 0)
            {
              // End handle is one less than handle of characteristic declaration
              glucoseHdlCache[glucoseEndHdlIdx] = BUILD_UINT16(p[0], p[1]) - 1;
              glucoseEndHdlIdx = 0;
            }

            // If UUID is of interest, store handle
            switch (uuid)
            {
              case GLUCOSE_MEAS_UUID:
                glucoseHdlCache[HDL_GLUCOSE_START] = handle;
                glucoseEndHdlIdx = HDL_GLUCOSE_END;
                break;

              case GLUCOSE_CONTEXT_UUID:
                glucoseHdlCache[HDL_GLUCOSE_CONTEXT_START] = handle;
                glucoseEndHdlIdx = HDL_GLUCOSE_CONTEXT_END;
                break;

              case RECORD_CTRL_PT_UUID:
                glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_START] = handle;
                glucoseEndHdlIdx = HDL_GLUCOSE_CTL_PNT_END;
                break;                
                
              case GLUCOSE_FEATURE_UUID:
                glucoseHdlCache[HDL_GLUCOSE_FEATURE] = handle;
                break;
                
              default:
                break;
            }
            
            p += CHAR_DESC_HDL_UUID16_LEN;
          }         
        }
          
        // If procedure complete
        if ((pMsg->method == ATT_READ_BY_TYPE_RSP  && 
             pMsg->hdr.status == bleProcedureComplete) ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          // Special case of end handle at end of service
          if (glucoseEndHdlIdx != 0)
          {
            glucoseHdlCache[glucoseEndHdlIdx] = glucoseSvcEndHdl;
            glucoseEndHdlIdx = 0;
          }
          
          // If didn't find glucose characteristic
          if (glucoseHdlCache[HDL_GLUCOSE_START] == 0)
          {
            newState = DISC_FAILED;
          }
          else if (glucoseHdlCache[HDL_GLUCOSE_START] <
                   glucoseHdlCache[HDL_GLUCOSE_END])
          {
            // Discover characteristic descriptors
            GATT_DiscAllCharDescs(glucCollConnHandle,
                                  glucoseHdlCache[HDL_GLUCOSE_START] + 1,
                                  glucoseHdlCache[HDL_GLUCOSE_END],
                                  glucCollTaskId);
                                        
            newState = DISC_GLUCOSE_CCCD;
          }
          else
          {
            newState = DISC_IDLE;
          }
        }
      }      
      break;

    case DISC_GLUCOSE_CCCD:
      {
        uint8_t i;
        
        // Characteristic descriptors found
        if (pMsg->method == ATT_FIND_INFO_RSP &&
            pMsg->msg.findInfoRsp.numInfo > 0 && 
            pMsg->msg.findInfoRsp.format == ATT_HANDLE_BT_UUID_TYPE)
        {
          attFindInfoRsp_t *pRsp = &(pMsg->msg.findInfoRsp);
                      
          // For each handle/uuid pair
          for (i = 0; i < pRsp->numInfo; i++)
          {           
            // Look for CCCD
            if ( ATT_BT_PAIR_UUID( pRsp->pInfo, i ) == GATT_CLIENT_CHAR_CFG_UUID )
            {
              // CCCD found
              glucoseHdlCache[HDL_GLUCOSE_MEAS_CCCD] = 
                ATT_BT_PAIR_HANDLE( pRsp->pInfo, i );
              
              break;
            }
          }
        }
        
        // If procedure complete
        if ((pMsg->method == ATT_FIND_INFO_RSP  && 
             pMsg->hdr.status == bleProcedureComplete) ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          // If CCCD found
          if (glucoseHdlCache[HDL_GLUCOSE_MEAS_CCCD] != 0)
          {
            // Should we look for unread category status CCCD
            if (glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_START] <
                glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_END])
            {
              // Discover unread category status characteristic descriptors
              GATT_DiscAllCharDescs(glucCollConnHandle,
                                    glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_START] + 1,
                                    glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_END],
                                    glucCollTaskId);
                                          
              newState = DISC_GLUCOSE_CTL_PNT_CCCD;
            }
            else
            {
              // Missing required characteristic
              newState = DISC_FAILED;
            }
          }
          else
          {
            // Missing required characteristic descriptor
            glucoseHdlCache[HDL_GLUCOSE_MEAS_CCCD] = 0;
            newState = DISC_FAILED;
          }          
        }
      }
      break;
         
   case DISC_GLUCOSE_CTL_PNT_CCCD:
      {
        uint8_t i;
        
        // Characteristic descriptors found
        if (pMsg->method == ATT_FIND_INFO_RSP &&
            pMsg->msg.findInfoRsp.numInfo > 0 && 
            pMsg->msg.findInfoRsp.format == ATT_HANDLE_BT_UUID_TYPE)
        {
          attFindInfoRsp_t *pRsp = &(pMsg->msg.findInfoRsp);
          
          // For each handle/uuid pair
          for (i = 0; i < pRsp->numInfo; i++)
          {
            // Look for CCCD
            if ( ATT_BT_PAIR_UUID( pRsp->pInfo, i ) == GATT_CLIENT_CHAR_CFG_UUID )
            {
              // CCCD found
              glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_CCCD] =
                ATT_BT_PAIR_HANDLE( pRsp->pInfo, i );
              
              break;
            }
          }
        }
        
        // If procedure complete
        if ((pMsg->method == ATT_FIND_INFO_RSP  && 
             pMsg->hdr.status == bleProcedureComplete) ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          // If CCCD found
          if (glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_CCCD] != 0)
          {
            // Should we look for unread category status CCCD
            if (glucoseHdlCache[HDL_GLUCOSE_CONTEXT_START] <
                glucoseHdlCache[HDL_GLUCOSE_CONTEXT_END])
            {
              // Discover unread category status characteristic descriptors
              GATT_DiscAllCharDescs(glucCollConnHandle,
                                    glucoseHdlCache[HDL_GLUCOSE_CONTEXT_START] + 1,
                                    glucoseHdlCache[HDL_GLUCOSE_CONTEXT_END],
                                    glucCollTaskId);
                                          
              newState = DISC_GLUCOSE_CONTEXT_CCCD;
            }
            else
            {
              // Done
              newState = DISC_IDLE;
            }
          }
          else
          {
            // Missing required characteristic descriptor
            glucoseHdlCache[HDL_GLUCOSE_CTL_PNT_CCCD] = 0;
            newState = DISC_FAILED;
          }          
        }
      }
      break;

   case DISC_GLUCOSE_CONTEXT_CCCD:
      {
        uint8_t i;
        
        // Characteristic descriptors found
        if (pMsg->method == ATT_FIND_INFO_RSP &&
            pMsg->msg.findInfoRsp.numInfo > 0 && 
            pMsg->msg.findInfoRsp.format == ATT_HANDLE_BT_UUID_TYPE)
        {
          attFindInfoRsp_t *pRsp = &(pMsg->msg.findInfoRsp);
          
          // For each handle/uuid pair
          for (i = 0; i < pRsp->numInfo; i++)
          {
            // Look for CCCD
            if ( ATT_BT_PAIR_UUID( pRsp->pInfo, i ) == GATT_CLIENT_CHAR_CFG_UUID )
            {
              // CCCD found
              glucoseHdlCache[HDL_GLUCOSE_CONTEXT_CCCD] =
                ATT_BT_PAIR_HANDLE( pRsp->pInfo, i );
              
              break;
            }
          }
        }
        
        // If procedure complete
        if ((pMsg->method == ATT_FIND_INFO_RSP  && 
             pMsg->hdr.status == bleProcedureComplete) ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          newState = DISC_IDLE;
        }
      }
      break;
      
    default:
      break;
  }
  
  return newState;
}
Exemple #28
0
/******************************************************************************
 * @fn      OTA_WriteHeader
 *
 * @brief   Writes the OTA header to the output buffer.
 *
 * @param   pHdr - pointer to the header information
 * @param   pHdr - pointer to the output buffer
 *
 * @return  none
 */
uint8 *OTA_WriteHeader(OTA_ImageHeader_t *pHdr, uint8 *pBuf)
{
  uint8 i;

  // Output the Magic Number
  // osal_buffer_uint32 not available under windows
  //pBuf = osal_buffer_uint32(pBuf, pHdr->magicNumber);
  *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 0);
  *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 1);
  *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 2);
  *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 3);

  // Output the Header Version
  *pBuf++ = LO_UINT16(pHdr->headerVersion);
  *pBuf++ = HI_UINT16(pHdr->headerVersion);

  // Output the Header Length
  *pBuf++ = LO_UINT16(pHdr->headerLength);
  *pBuf++ = HI_UINT16(pHdr->headerLength);

  // Output the Field Control
  *pBuf++ = LO_UINT16(pHdr->fieldControl);
  *pBuf++ = HI_UINT16(pHdr->fieldControl);

  // Output the Manufacturer ID
  *pBuf++ = LO_UINT16(pHdr->fileId.manufacturer);
  *pBuf++ = HI_UINT16(pHdr->fileId.manufacturer);

  // Output the Image Type
  *pBuf++ = LO_UINT16(pHdr->fileId.type);
  *pBuf++ = HI_UINT16(pHdr->fileId.type);

  // Output the File Version
  // osal_buffer_uint32 not available under windows
  //pBuf = osal_buffer_uint32(pBuf, pHdr->fileId.version);
  *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 0);
  *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 1);
  *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 2);
  *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 3);

  // Output the Stack Version
  *pBuf++ = LO_UINT16(pHdr->stackVersion);
  *pBuf++ = HI_UINT16(pHdr->stackVersion);

  // Output the Header string
  for (i=0; i<OTA_HEADER_STR_LEN; i++)
  {
    *pBuf++ = pHdr->headerString[i];
  }

  // Output the Image Size
  // osal_buffer_uint32 not available under windows
  //pBuf = osal_buffer_uint32(pBuf, pHdr->imageSize);
  *pBuf++ = BREAK_UINT32(pHdr->imageSize, 0);
  *pBuf++ = BREAK_UINT32(pHdr->imageSize, 1);
  *pBuf++ = BREAK_UINT32(pHdr->imageSize, 2);
  *pBuf++ = BREAK_UINT32(pHdr->imageSize, 3);

  // Output the Security Credential Version
  if (pHdr->fieldControl & OTA_FC_SCV_PRESENT)
  {
    *pBuf++ = pHdr->secCredentialVer;
  }

  // Output the Upgrade File Destination
  if (pHdr->fieldControl & OTA_FC_DSF_PRESENT)
  {
    for (i=0; i<Z_EXTADDR_LEN; i++)
    {
      *pBuf++ = pHdr->destIEEE[i];
    }
  }

  // Output the Min and Max Hardware Versions
  if (pHdr->fieldControl & OTA_FC_HWV_PRESENT)
  {
    *pBuf++ = LO_UINT16(pHdr->minHwVer);
    *pBuf++ = HI_UINT16(pHdr->minHwVer);

    *pBuf++ = LO_UINT16(pHdr->maxHwVer);
    *pBuf++ = HI_UINT16(pHdr->maxHwVer);
  }

  return pBuf;
}
/** \brief Processes the \ref GET_STATUS request (returns status for the specified recipient)
 *
 * The recipient bits in \ref USB_SETUP_HEADER.requestType specify the desired recipient. This is either the
 * (one and only) device, a specific interface, or a specific endpoint. Some of the status bits can be
 * changed with the SET_FEATURE and CLEAR_FEATURE requests.
 *
 * <b>Parameters</b>:
 * - VALUE: Always 0
 * - INDEX: Depends upon the recipient:
 *     - DEVICE: Always 0
 *     - INTERFACE: Interface number
 *     - ENDPOINT: Endpoint address
 * - LENGTH: Always 2
 *
 * <b>Data (IN)</b>:
 * Depends upon the recipient (the bit field illustrations are MSB first, LSB last):
 * - DEVICE: <tt>00000000.000000RS</tt>, where R(1) = DEVICE_REMOTE_WAKEUP and S(0) = SELF_POWERED
 * - INTERFACE: <tt>00000000.00000000</tt> (all bits are reserved)
 * - ENDPOINT: <tt>00000000.0000000H</tt>, where H(0) = ENDPOINT_HALT
 */
void usbsrGetStatus(void)
{
   uint8 endpoint;
   static uint16 __xdata status;

   // Common sanity check
   if (usbSetupHeader.value || HI_UINT16(usbSetupHeader.index) || (usbSetupHeader.length != 2)) {
      usbfwData.ep0Status = EP_STALL;

   // Return status for device, interface, or endpoint
   } else {
      switch (usbSetupHeader.requestType) {

         // Device status:
         //     Bit 0: Self powered
         //     Bit 1: Remote wake-up allowed
      case RT_IN_DEVICE:

         // Sanity check
         if (LO_UINT16(usbSetupHeader.index)) {
            usbfwData.ep0Status = EP_STALL;

         // Get the bit values from the USBFW_DATA struct
         } else {

            // Self powered?
            status = usbfwData.selfPowered ? 0x0001 : 0x0000;

            // Remote wakeup?
            if (usbfwData.remoteWakeup) status |= 0x0002;
         }
         break;

         // Interface status:
         //     All bits are reserved
      case RT_IN_INTERFACE:

         // Sanity check
         if (usbfwData.usbState != DEV_CONFIGURED) {
            usbfwData.ep0Status = EP_STALL;
         } else {
            status = 0x0000;
         }
         break;

         // Endpoint status:
         //     Bit 0: Endpoint halted
      case RT_IN_ENDPOINT:
         endpoint = LO_UINT16(usbSetupHeader.index) & 0x7F;

         // Sanity check
         if ((usbfwData.usbState != DEV_CONFIGURED) || (endpoint > 5)) {
            usbfwData.ep0Status = EP_STALL;

         // Translate endpoint address to status index and return the status
         } else {

            // IN
            if (LO_UINT16(usbSetupHeader.index) & 0x80) {
               status = (usbfwData.pEpInStatus[endpoint - 1] == EP_HALT) ? 0x0001 : 0x0000;

            // OUT
            } else {
               status = (usbfwData.pEpOutStatus[endpoint - 1] == EP_HALT) ? 0x0001 : 0x0000;
            }
         }
         break;

      default:
         usbfwData.ep0Status = EP_STALL;
         break;
      }

      if (usbfwData.ep0Status != EP_STALL) {
         // Send it
         usbSetupData.pBuffer = (uint8 __xdata *)&status;
         usbSetupData.bytesLeft = 2;
         usbfwData.ep0Status = EP_TX;
      }
   }
} // usbsrGetStatus
Exemple #30
0
#define BATT_ADC_LEVEL_2V           273

#define BATT_LEVEL_VALUE_IDX        2 // Position of battery level in attribute array
#define BATT_LEVEL_VALUE_CCCD_IDX   3 // Position of battery level CCCD in attribute array

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
// Battery service
CONST uint8 battServUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(BATT_SERVICE_UUID), HI_UINT16(BATT_SERVICE_UUID)
};

// Battery level characteristic
CONST uint8 battLevelUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(BATT_LEVEL_UUID), HI_UINT16(BATT_LEVEL_UUID)
};

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */