Пример #1
0
/*********************************************************************
 * @fn      scanParamWriteAttrCB
 *
 * @brief   Validate attribute data prior to a write operation
 *
 * @param   connHandle - connection message was received on
 * @param   pAttr - pointer to attribute
 * @param   pValue - pointer to data to be written
 * @param   len - length of data
 * @param   offset - offset of the first octet to be written
 * @param   complete - whether this is the last packet
 * @param   oper - whether to validate and/or write attribute value
 *
 * @return  Success or Failure
 */
static bStatus_t scanParamWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                                  uint8 *pValue, uint8 len, uint16 offset )
{
  bStatus_t status = SUCCESS;

  // Make sure it's not a blob operation (no attributes in the profile are long)
  if ( offset > 0 )
  {
    return ( ATT_ERR_ATTR_NOT_LONG );
  }

  uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);

  // Only one writeable attribute
  if ( uuid == SCAN_INTERVAL_WINDOW_UUID )
  {
    // require encryption
    if ( linkDB_Encrypted( connHandle ) == FALSE )
    {
      return ( ATT_ERR_INSUFFICIENT_ENCRYPT );
    }

    if ( len == SCAN_INTERVAL_WINDOW_CHAR_LEN )
    {
      uint16 interval = BUILD_UINT16( pValue[0], pValue[1] );
      uint16 window = BUILD_UINT16( pValue[0], pValue[1] );

      // Validate values
      if ( window <= interval )
      {
        osal_memcpy( pAttr->pValue, pValue, len );

        (*scanParamServiceCB)( SCAN_INTERVAL_WINDOW_SET );
      }
      else
      {
        status = ATT_ERR_INVALID_VALUE;
      }
    }
    else
    {
      status = ATT_ERR_INVALID_VALUE_SIZE;
    }
  }
  else if ( uuid == GATT_CLIENT_CHAR_CFG_UUID )
  {
    status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                             offset, GATT_CLIENT_CFG_NOTIFY );
  }
  else
  {
    status = ATT_ERR_ATTR_NOT_FOUND;
  }

  return ( status );
}
Пример #2
0
/*********************************************************************
 * @fn          glucose_ReadAttrCB
 *
 * @brief       Read an attribute.
 *
 * @param       connHandle - connection message was received on
 * @param       pAttr - pointer to attribute
 * @param       pValue - pointer to data to be read
 * @param       pLen - length of data to be read
 * @param       offset - offset of the first octet to be read
 * @param       maxLen - maximum length of data to be read
 *
 * @return      Success or Failure
 */
static uint8 glucose_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                            uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen )
{
  bStatus_t status = SUCCESS;

  // Require security for all characteristics
  if ( linkDB_Encrypted( connHandle ) == FALSE )
  {
    return ATT_ERR_INSUFFICIENT_ENCRYPT;
  }

  // Make sure it's not a blob operation (no attributes in the profile are long)
  if ( offset > 0 )
  {
    return ( ATT_ERR_ATTR_NOT_LONG );
  }

  if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  {
    // 16-bit UUID
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
    switch ( uuid )
    {
      // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
      // gattserverapp handles those types for reads

      case GLUCOSE_FEATURE_UUID:
        *pLen = 2;
        pValue[0] = LO_UINT16( glucoseFeature );
        pValue[1] = HI_UINT16( glucoseFeature );
        break;

      default:
        // Should never get here! (characteristics 3 and 4 do not have read permissions)
        *pLen = 0;
        status = ATT_ERR_ATTR_NOT_FOUND;
        break;
    }
  }

  return ( status );
}
Пример #3
0
/*********************************************************************
 * @fn      glucose_WriteAttrCB
 *
 * @brief   Validate attribute data prior to a write operation
 *
 * @param   connHandle - connection message was received on
 * @param   pAttr - pointer to attribute
 * @param   pValue - pointer to data to be written
 * @param   len - length of data
 * @param   offset - offset of the first octet to be written
 *
 * @return  Success or Failure
 */
static bStatus_t glucose_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                                 uint8 *pValue, uint8 len, uint16 offset )
{
  bStatus_t status = SUCCESS;

  // Require security for all characteristics
  if ( linkDB_Encrypted( connHandle ) == FALSE )
  {
    return ATT_ERR_INSUFFICIENT_ENCRYPT;
  }

  // Make sure it's not a blob operation (no attributes in the profile are long)
  if ( offset > 0 )
  {
    return ( ATT_ERR_ATTR_NOT_LONG );
  }

  uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);

  switch ( uuid )
  {

  case  GATT_CLIENT_CHAR_CFG_UUID:
      // Glucose Notifications
      if ((pAttr->handle == glucoseAttrTbl[GLUCOSE_MEAS_CONFIG_POS].handle ||
           pAttr->handle == glucoseAttrTbl[GLUCOSE_CONTEXT_CONFIG_POS].handle))
      {
        status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                 offset, GATT_CLIENT_CFG_NOTIFY );
        if ( status == SUCCESS )
        {
          uint16 charCfg = BUILD_UINT16( pValue[0], pValue[1] );

          if(pAttr->handle == glucoseAttrTbl[GLUCOSE_MEAS_CONFIG_POS].handle)
          {
            (*glucoseServiceCB)((charCfg == 0) ? GLUCOSE_MEAS_NTF_DISABLED :
                                                 GLUCOSE_MEAS_NTF_ENABLED, NULL, NULL);
          }
          else
          {
            (*glucoseServiceCB)((charCfg == 0) ? GLUCOSE_CONTEXT_NTF_DISABLED :
                                                 GLUCOSE_CONTEXT_NTF_ENABLED, NULL, NULL);
          }
        }
      }
      // Glucose Indications
      else if ( pAttr->handle == glucoseAttrTbl[GLUCOSE_CTL_PNT_CONFIG_POS].handle )
      {
        status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                 offset, GATT_CLIENT_CFG_INDICATE );
        if ( status == SUCCESS )
        {
            uint16 charCfg = BUILD_UINT16( pValue[0], pValue[1] );

            (*glucoseServiceCB)((charCfg == 0) ? GLUCOSE_CTL_PNT_IND_DISABLED :
                                                 GLUCOSE_CTL_PNT_IND_ENABLED, NULL, NULL);
        }
      }
      else
      {
        status = ATT_ERR_INVALID_VALUE;
      }
    break;

    case  RECORD_CONTROL_POINT_UUID:
      if(len >= GLUCOSE_CTL_PNT_MIN_SIZE  && len <= GLUCOSE_CTL_PNT_MAX_SIZE)
      {
        uint8 opcode = pValue[0];

        // if transfer in progress
        if (opcode != CTL_PNT_OP_ABORT && glucoseSendAllRecords)
        {
          status = GLUCOSE_ERR_IN_PROGRESS;
        }
        // if CCC not configured for glucose measurement
        else if ( opcode == CTL_PNT_OP_REQ &&
                 !( GATTServApp_ReadCharCfg( connHandle, glucoseMeasConfig ) & GATT_CLIENT_CFG_NOTIFY ) )
        {
          status = GLUCOSE_ERR_CCC_CONFIG;
        }
        else
        {
          (*glucoseServiceCB)(GLUCOSE_CTL_PNT_CMD, pValue, len);
        }
      }
      else
      {
        status = ATT_ERR_INVALID_VALUE_SIZE;
      }
    break;

    default:
      status = ATT_ERR_ATTR_NOT_FOUND;
      break;
  }

  return ( status );
}