EmberNodeId ezspDecodeAddressResponse(uint8_t *response,
                                      EmberEUI64 eui64Return)
{
  uint8_t *payload = response + ZDO_MESSAGE_OVERHEAD;
  if (payload[0] == EMBER_ZDP_SUCCESS) {
    MEMMOVE(eui64Return, payload + 1, EUI64_SIZE);
    return HIGH_LOW_TO_INT(payload[10], payload[9]);
  } else
    return EMBER_NULL_NODE_ID;
}
Exemple #2
0
static FibStatus fibFlashWrite(int32u address, int8u *data, int32u length, int32u dummy)
{
    int32u i;
    int16u *ptr;
    FibStatus status = FIB_SUCCESS;
    // Address and length must be half-word aligned.
    if ((address & 1) || (length & 1))
    {
        return FIB_ERR_UNALIGNED;
    }
    // Start and end address must be in MFB or CIB.
    if (!((address >= MFB_BOTTOM && address + length <= MFB_TOP + 1)
            || (address >= CIB_BOTTOM && address + length <= CIB_TOP + 1)))
    {
        return FIB_ERR_INVALID_ADDRESS;
    }
    enableFlitf();
    ptr = (int16u *)address;
    for (i = 0; i < length; i += 2)
    {
        int16u currentData = *ptr;
        int16u newData = HIGH_LOW_TO_INT(data[i + 1], data[i]);
        // Only program the data if it makes sense to do so.
        if (currentData == newData)
        {
            // If the new data matches the flash, don't bother doing anything.
        }
        else if (currentData == 0xFFFF || newData == 0x0000)
        {
            // If the flash is 0xFFFF we're allowed to write anything.
            // If the new data is 0x0000 it doesn't matter what the flash is.
            // OPTWREN must stay set to keep CIB unlocked.
            if ((CIB_OB_BOTTOM <= (int32u)ptr) && ((int32u)ptr <= CIB_OB_TOP))
            {
                FLASH_CTRL = (FLASH_CTRL_OPTWREN | FLASH_CTRL_OPTPROG);
            }
            else
            {
                FLASH_CTRL = (FLASH_CTRL_OPTWREN | FLASH_CTRL_PROG);
            }
            // Assigning data to the address performs the actual write.
            (*ptr) = newData;
            // Wait for the busy bit to clear, indicating operation is done.
            while ((FLASH_STATUS & FLASH_STATUS_FLA_BSY) != 0) {}
            // Reset the operation complete flag.
            FLASH_STATUS = FLASH_STATUS_EOP;
            // Check if any error bits have been tripped, and if so, exit.
            // The bit PAGE_PROG_ERR is not relevant in this programming mode.
            if (FLASH_STATUS & (FLASH_STATUS_WRP_ERR | FLASH_STATUS_PROG_ERR))
            {
                if (FLASH_STATUS & FLASH_STATUS_WRP_ERR)
                {
                    status = FIB_ERR_WRITE_PROTECTED;
                }
                else
                {
                    status = FIB_ERR_WRITE_FAILED;
                }
                FLASH_STATUS = FLASH_STATUS_WRP_ERR;
                FLASH_STATUS = FLASH_STATUS_PROG_ERR;
                break;
            }
        }
        else
        {
            status = FIB_ERR_ERASE_REQUIRED;
            break;
        }
        ptr++;
    }
    disableFlitf();
    return status;
}
// A pairing index value of 0xFF means "local attributes".
void emAfRf4ceZrcReadOrWriteAttribute(uint8_t pairingIndex,
                                      uint8_t attrId,
                                      uint16_t entryIdOrValueLength,
                                      bool isRead,
                                      uint8_t *val)
{
  bool localAttributes = (pairingIndex == 0xFF);
  EmAfRf4ceZrcAttributes *attributes = (localAttributes)
                                       ? &emAfRf4ceZrcLocalNodeAttributes
                                       : &emAfRf4ceZrcRemoteNodeAttributes;

  if (isRead) {
    switch (attrId) {
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_VERSION:
      val[0] = LOW_BYTE(attributes->zrcProfileVersion);
      val[1] = HIGH_BYTE(attributes->zrcProfileVersion);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_CAPABILITIES:
    {
      uint32_t cababilities = ((pairingIndex == 0xFF)
                             ? emAfRf4ceZrcGetLocalNodeCapabilities()
                             : emAfRf4ceZrcGetRemoteNodeCapabilities(pairingIndex));
      val[0] = BYTE_0(cababilities);
      val[1] = BYTE_1(cababilities);
      val[2] = BYTE_2(cababilities);
      val[3] = BYTE_3(cababilities);
    }
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_BANKS_SUPPORTED_RX:
      MEMCOPY(val, attributes->actionBanksSupportedRx->contents, ZRC_BITMASK_SIZE);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_BANKS_SUPPORTED_TX:
      MEMCOPY(val, attributes->actionBanksSupportedTx->contents, ZRC_BITMASK_SIZE);
      break;
#if (defined(EMBER_AF_PLUGIN_RF4CE_ZRC20_LOCAL_IRDB_VENDOR_ATTRIBUTE_SUPPORT)       \
     || defined(EMBER_AF_PLUGIN_RF4CE_ZRC20_REMOTE_IRDB_VENDOR_ATTRIBUTES_SUPPORT)  \
     || defined(EMBER_SCRIPTED_TEST))
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_IRDB_VENDOR_SUPPORT:
    {
      // Can't just perform a MEMCOPY, endianness matters.
      uint8_t i;
      uint8_t entriesNum = (localAttributes
                          ? EMBER_AF_RF4CE_ZRC_IRDB_VENDOR_ID_COUNT
                          : EMBER_AF_PLUGIN_RF4CE_ZRC20_REMOTE_IRDB_VENDORS_SUPPORTED_TABLE_SIZE);

      // Non-valid entries are set to EMBER_RF4CE_NULL_VENDOR_ID.
      for(i=0; (i<entriesNum
                && attributes->IRDBVendorSupport[i] != EMBER_RF4CE_NULL_VENDOR_ID);
          i++) {
        val[2*i] = LOW_BYTE(attributes->IRDBVendorSupport[i]);
        val[2*i+1] = HIGH_BYTE(attributes->IRDBVendorSupport[i]);
      }
    }
      break;
#endif // EMBER_AF_PLUGIN_RF4CE_ZRC20_LOCAL_IRDB_VENDOR_ATTRIBUTE_SUPPORT || EMBER_AF_PLUGIN_RF4CE_ZRC20_REMOTE_IRDB_VENDOR_ATTRIBUTES_SUPPORT
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_BANKS_VERSION:
      val[0] = LOW_BYTE(attributes->zrcActionBanksVersion);
      val[1] = HIGH_BYTE(attributes->zrcActionBanksVersion);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_CODES_SUPPORTED_RX:
#if (defined (EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_RECIPIENT) || defined(EMBER_SCRIPTED_TEST))
      // RX action codes related to HA action banks should be all 0xFF if the
      // node is an HA actions recipient.
      if (entryIdOrValueLength >= EMBER_AF_RF4CE_ZRC_ACTION_BANK_HOME_AUTOMATION_INSTANCE_0
          && entryIdOrValueLength <= EMBER_AF_RF4CE_ZRC_ACTION_BANK_HOME_AUTOMATION_INSTANCE_31) {
        MEMSET(val, 0xFF, ZRC_BITMASK_SIZE);
        break;
      }
      // Fall-through here
#endif // EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_RECIPIENT
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_CODES_SUPPORTED_TX:
    {
      uint8_t *attrPtr = emAfRf4ceZrcGetActionCodesAttributePointer(attrId,
                                                                  entryIdOrValueLength,
                                                                  pairingIndex);
      assert(attrPtr != NULL);
      MEMCOPY(val, attrPtr, ZRC_BITMASK_SIZE);
      break;
    }
#if defined(EMBER_AF_PLUGIN_RF4CE_ZRC20_ACTION_MAPPING_SUPPORT) || defined(EMBER_SCRIPTED_TEST)
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_MAPPABLE_ACTIONS:
    {
      EmberAfRf4ceZrcMappableAction mappableAction;
      assert (emberAfPluginRf4ceZrc20GetMappableActionCallback(pairingIndex,
                                                               entryIdOrValueLength,
                                                               &mappableAction)
              == EMBER_SUCCESS);

      val[MAPPABLE_ACTION_ACTION_DEVICE_TYPE_OFFSET] = mappableAction.actionDeviceType;
      val[MAPPABLE_ACTION_ACTION_BANK_OFFSET] = mappableAction.actionBank;
      val[MAPPABLE_ACTION_ACTION_CODE_OFFSET] = mappableAction.actionCode;
    }
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_MAPPINGS:
    {
      EmberAfRf4ceZrcActionMapping actionMapping;
      assert (emberAfPluginRf4ceZrc20GetActionMappingCallback(pairingIndex,
                                                              entryIdOrValueLength,
                                                              &actionMapping)
              == EMBER_SUCCESS);

      *val++ = actionMapping.mappingFlags;
      if (READBITS(actionMapping.mappingFlags,
                   (EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_RF_SPECIFIED_BIT
                     | EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_USE_DEFAULT_BIT))
          == EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_RF_SPECIFIED_BIT) {
        *val++ = actionMapping.rfConfig;
        *val++ = actionMapping.rf4ceTxOptions;
        *val++ = actionMapping.actionDataLength;
        assert(actionMapping.actionData != NULL);
        MEMCOPY(val, actionMapping.actionData, actionMapping.actionDataLength);
        val += actionMapping.actionDataLength;
      }

      if (READBITS(actionMapping.mappingFlags,
                   (EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_IR_SPECIFIED_BIT
                     | EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_USE_DEFAULT_BIT))
          == EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_IR_SPECIFIED_BIT) {
        *val++ = actionMapping.irConfig;
        if (actionMapping.irConfig
            & ACTION_MAPPING_IR_CONFIG_VENDOR_SPECIFIC_BIT) {
          *val++ = LOW_BYTE(actionMapping.irVendorId);
          *val++ = HIGH_BYTE(actionMapping.irVendorId);
        }
        *val++ = actionMapping.irCodeLength;
        assert(actionMapping.irCode != NULL);
        MEMCOPY(val, actionMapping.irCode, actionMapping.irCodeLength);
      }
    }
      break;
#endif // EMBER_AF_PLUGIN_RF4CE_ZRC20_ACTION_MAPPING_SUPPORT

#if (defined(EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_ORIGINATOR)             \
     || defined (EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_RECIPIENT)          \
     || defined(EMBER_SCRIPTED_TEST))
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_HOME_AUTOMATION:
      // This attribute can only be pulled and is stored at the application.
      // This plugin can only access this attribute via callback. As result,
      // we will get here only after having called (and it returns 'success')
      // emAfRf4ceZrcIsArrayedAttributeSupported() in the pullAttributes()
      // handler function. emAfRf4ceZrcIsArrayedAttributeSupported() saves the
      // contents in the static object tempHaAttribute. So we just copy it
      // here.
      assert(tempHaAttribute.contentsLength < (MAX_ZRC_ATTRIBUTE_SIZE - 1));
      *val++ = HA_ATTRIBUTE_STATUS_VALUE_AVAILABLE_FLAG;
      MEMCOPY(val, tempHaAttribute.contents, tempHaAttribute.contentsLength);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_HOME_AUTOMATION_SUPPORTED:
      emberAfPluginRf4ceZrc20GetHomeAutomationSupportedCallback(pairingIndex,
                                                                entryIdOrValueLength,
                                                                (EmberAfRf4ceZrcHomeAutomationSupported*)val);
      break;
#endif // EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_ORIGINATOR || EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_RECIPIENT
    }
  } else { // !isRead
    switch (attrId) {
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_VERSION:
      attributes->zrcProfileVersion = HIGH_LOW_TO_INT(val[1], val[0]);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_CAPABILITIES:
      // We only allow setting remote nodes capabilities.
      if (pairingIndex < 0xFF) {
        emAfRf4ceZrcSetRemoteNodeCapabilities(pairingIndex,
                                              emberFetchLowHighInt32u(val));
      }
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_BANKS_SUPPORTED_RX:
      MEMCOPY(attributes->actionBanksSupportedRx->contents, val, ZRC_BITMASK_SIZE);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_BANKS_SUPPORTED_TX:
      MEMCOPY(attributes->actionBanksSupportedTx->contents, val, ZRC_BITMASK_SIZE);
      break;
#if defined(EMBER_AF_PLUGIN_RF4CE_ZRC20_REMOTE_IRDB_VENDOR_ATTRIBUTES_SUPPORT) || defined(EMBER_SCRIPTED_TEST)
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_IRDB_VENDOR_SUPPORT:
    {
      // Only remote IRDB vendor support attributes can written.
      uint8_t i;
      for (i=0; i < EMBER_AF_PLUGIN_RF4CE_ZRC20_REMOTE_IRDB_VENDORS_SUPPORTED_TABLE_SIZE; i++) {
        uint16_t vendorId;
        if (i < entryIdOrValueLength / 2) {
          vendorId = HIGH_LOW_TO_INT(val[2*i+1], val[2*i]);
        } else {
          // The rest of the entries are set to NULL_VENDOR_ID.
          vendorId = EMBER_RF4CE_NULL_VENDOR_ID;
        }

        attributes->IRDBVendorSupport[i] = vendorId;

#if defined(EMBER_SCRIPTED_TEST)
        simpleScriptCheck("", "Remote IRDB attribute, entry set", "ii",
                          i,
                          vendorId);
#endif // EMBER_SCRIPTED_TEST
      }
    }
      break;
#endif // EMBER_AF_PLUGIN_RF4CE_ZRC20_REMOTE_IRDB_VENDOR_ATTRIBUTES_SUPPORT
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_BANKS_VERSION:
      attributes->zrcActionBanksVersion = HIGH_LOW_TO_INT(val[1], val[0]);
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_CODES_SUPPORTED_RX:
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_CODES_SUPPORTED_TX:
    {
      uint8_t *attrPtr = emAfRf4ceZrcGetActionCodesAttributePointer(attrId,
                                                                  entryIdOrValueLength,
                                                                  pairingIndex);
      assert(attrPtr != NULL);
      MEMCOPY(attrPtr, val, ZRC_BITMASK_SIZE);
      break;
    }

#if defined(EMBER_AF_PLUGIN_RF4CE_ZRC20_ACTION_MAPPING_SUPPORT) || defined(EMBER_SCRIPTED_TEST)
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_MAPPABLE_ACTIONS:
    {
      EmberAfRf4ceZrcMappableAction mappableAction;
      mappableAction.actionDeviceType = val[0];
      mappableAction.actionBank = val[1];
      mappableAction.actionCode = val[2];
      emberAfPluginRf4ceZrc20IncomingMappableActionCallback(emberAfRf4ceGetPairingIndex(),
                                                            entryIdOrValueLength,
                                                            &mappableAction);
    }
      break;
    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_ACTION_MAPPINGS:
    {
      EmberAfRf4ceZrcActionMapping actionMapping;
      uint8_t *finger = val;
      actionMapping.actionData = NULL;
      actionMapping.irCode = NULL;

      // Mapping flags
      actionMapping.mappingFlags = *finger++;

      // RF descriptor
      if (READBITS(actionMapping.mappingFlags,
                   (EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_RF_SPECIFIED_BIT
                     | EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_USE_DEFAULT_BIT))
          == EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_RF_SPECIFIED_BIT) {
        actionMapping.rfConfig = *finger++;
        actionMapping.rf4ceTxOptions = *finger++;
        actionMapping.actionDataLength = *finger++;
        actionMapping.actionData = finger;
        finger += actionMapping.actionDataLength;
      }

      // IR descriptor
      if (READBITS(actionMapping.mappingFlags,
                   (EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_IR_SPECIFIED_BIT
                     | EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_USE_DEFAULT_BIT))
          == EMBER_AF_RF4CE_ZRC_ACTION_MAPPING_MAPPING_FLAGS_IR_SPECIFIED_BIT) {
        actionMapping.irConfig = *finger++;
        if (actionMapping.irConfig
            & ACTION_MAPPING_IR_CONFIG_VENDOR_SPECIFIC_BIT) {
          actionMapping.irVendorId = HIGH_LOW_TO_INT(finger[1], finger[0]);
          finger += 2;
        }
        actionMapping.irCodeLength = *finger++;
        actionMapping.irCode = finger;
      }

      emberAfPluginRf4ceZrc20IncomingActionMappingCallback(emberAfRf4ceGetPairingIndex(),
                                                           entryIdOrValueLength,
                                                           &actionMapping);
    }
      break;
#endif // EMBER_AF_PLUGIN_RF4CE_ZRC20_ACTION_MAPPING_SUPPORT

#if (defined(EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_ORIGINATOR)             \
     || defined (EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_RECIPIENT)          \
     || defined(EMBER_SCRIPTED_TEST))

    // EMBER_AF_RF4CE_ZRC_ATTRIBUTE_HOME_AUTOMATION attributes sets are handled
    // in the HA action code.

    case EMBER_AF_RF4CE_ZRC_ATTRIBUTE_HOME_AUTOMATION_SUPPORTED:
      emberAfPluginRf4ceZrc20IncomingHomeAutomationSupportedCallback(emberAfRf4ceGetPairingIndex(),
                                                                     entryIdOrValueLength,
                                                                     (EmberAfRf4ceZrcHomeAutomationSupported*)val);
      break;
#endif // EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_ORIGINATOR || EMBER_AF_RF4CE_ZRC_IS_HA_ACTIONS_RECIPIENT
    }
  }
}