util.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. /**
  2. *
  3. * Copyright (c) 2020-2021 Project CHIP Authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. *
  19. * Copyright (c) 2020 Silicon Labs
  20. *
  21. * Licensed under the Apache License, Version 2.0 (the "License");
  22. * you may not use this file except in compliance with the License.
  23. * You may obtain a copy of the License at
  24. *
  25. * http://www.apache.org/licenses/LICENSE-2.0
  26. *
  27. * Unless required by applicable law or agreed to in writing, software
  28. * distributed under the License is distributed on an "AS IS" BASIS,
  29. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  30. * See the License for the specific language governing permissions and
  31. * limitations under the License.
  32. */
  33. /***************************************************************************/
  34. /**
  35. * @file
  36. * @brief This file contains all of the common ZCL
  37. *command and attribute handling code for Ember's ZCL
  38. *implementation
  39. *******************************************************************************
  40. ******************************************************************************/
  41. #include "app/util/common.h"
  42. #include <app-common/zap-generated/attribute-id.h>
  43. #include <app-common/zap-generated/attribute-type.h>
  44. #include <app-common/zap-generated/callback.h>
  45. #include <app-common/zap-generated/cluster-id.h>
  46. #include <app-common/zap-generated/command-id.h>
  47. #include <app-common/zap-generated/print-cluster.h>
  48. #include <app/util/af-event.h>
  49. #include <app/util/af-main.h>
  50. #include <app/util/af.h>
  51. #include <zap-generated/PluginApplicationCallbacks.h>
  52. #ifdef EMBER_AF_PLUGIN_GROUPS_SERVER
  53. #include <app/clusters/groups-server/groups-server.h>
  54. #endif // EMBER_AF_PLUGIN_GROUPS_SERVER
  55. using namespace chip;
  56. // Function for Compatibility
  57. namespace chip {
  58. namespace app {
  59. namespace Compatibility {
  60. bool IMEmberAfSendDefaultResponseWithCallback(EmberAfStatus status);
  61. bool __attribute__((weak)) IMEmberAfSendDefaultResponseWithCallback(EmberAfStatus status)
  62. {
  63. return false;
  64. }
  65. } // namespace Compatibility
  66. } // namespace app
  67. } // namespace chip
  68. //------------------------------------------------------------------------------
  69. // Forward Declarations
  70. //------------------------------------------------------------------------------
  71. // Globals
  72. // Storage and functions for turning on and off devices
  73. bool afDeviceEnabled[MAX_ENDPOINT_COUNT];
  74. #ifdef EMBER_AF_ENABLE_STATISTICS
  75. // a variable containing the number of messages send from the utilities
  76. // since emberAfInit was called.
  77. uint32_t afNumPktsSent;
  78. #endif
  79. const EmberAfClusterName zclClusterNames[] = {
  80. CLUSTER_IDS_TO_NAMES // defined in print-cluster.h
  81. { ZCL_NULL_CLUSTER_ID, EMBER_AF_NULL_MANUFACTURER_CODE, NULL }, // terminator
  82. };
  83. // A pointer to the current command being processed
  84. // This struct is allocated inside ember-compatibility-functions.cpp.
  85. // The pointer below is set to NULL when not processing a command.
  86. EmberAfClusterCommand * emAfCurrentCommand;
  87. // A pointer to the global exchange manager
  88. chip::Messaging::ExchangeManager * emAfExchangeMgr = nullptr;
  89. // DEPRECATED.
  90. uint8_t emberAfIncomingZclSequenceNumber = 0xFF;
  91. // Sequence used for outgoing messages if they are
  92. // not responses.
  93. uint8_t emberAfSequenceNumber = 0xFF;
  94. static uint8_t /*enum EmberAfRetryOverride*/ emberAfApsRetryOverride = EMBER_AF_RETRY_OVERRIDE_NONE;
  95. static uint8_t /*enum EmberAfDisableDefaultResponse*/ emAfDisableDefaultResponse = EMBER_AF_DISABLE_DEFAULT_RESPONSE_NONE;
  96. static uint8_t /*enum EmberAfDisableDefaultResponse*/ emAfSavedDisableDefaultResponseVale = EMBER_AF_DISABLE_DEFAULT_RESPONSE_NONE;
  97. // Holds the response type
  98. uint8_t emberAfResponseType = ZCL_UTIL_RESP_NORMAL;
  99. static EmberAfInterpanHeader interpanResponseHeader;
  100. uint8_t emAfExtendedPanId[EXTENDED_PAN_ID_SIZE] = {
  101. 0, 0, 0, 0, 0, 0, 0, 0,
  102. };
  103. #ifdef EMBER_AF_GENERATED_PLUGIN_TICK_FUNCTION_DECLARATIONS
  104. EMBER_AF_GENERATED_PLUGIN_TICK_FUNCTION_DECLARATIONS
  105. #endif
  106. //------------------------------------------------------------------------------
  107. // Device enabled/disabled functions
  108. bool emberAfIsDeviceEnabled(EndpointId endpoint)
  109. {
  110. uint16_t index;
  111. #ifdef ZCL_USING_BASIC_CLUSTER_DEVICE_ENABLED_ATTRIBUTE
  112. bool deviceEnabled;
  113. if (emberAfReadServerAttribute(endpoint, ZCL_BASIC_CLUSTER_ID, ZCL_DEVICE_ENABLED_ATTRIBUTE_ID, (uint8_t *) &deviceEnabled,
  114. sizeof(deviceEnabled)) == EMBER_ZCL_STATUS_SUCCESS)
  115. {
  116. return deviceEnabled;
  117. }
  118. #endif
  119. index = emberAfIndexFromEndpoint(endpoint);
  120. if (index != 0xFFFF && index < sizeof(afDeviceEnabled))
  121. {
  122. return afDeviceEnabled[index];
  123. }
  124. return false;
  125. }
  126. void emberAfSetDeviceEnabled(EndpointId endpoint, bool enabled)
  127. {
  128. uint16_t index = emberAfIndexFromEndpoint(endpoint);
  129. if (index != 0xFFFF && index < sizeof(afDeviceEnabled))
  130. {
  131. afDeviceEnabled[index] = enabled;
  132. }
  133. #ifdef ZCL_USING_BASIC_CLUSTER_DEVICE_ENABLED_ATTRIBUTE
  134. emberAfWriteServerAttribute(endpoint, ZCL_BASIC_CLUSTER_ID, ZCL_DEVICE_ENABLED_ATTRIBUTE_ID, (uint8_t *) &enabled,
  135. ZCL_BOOLEAN_ATTRIBUTE_TYPE);
  136. #endif
  137. }
  138. // Is the device identifying?
  139. bool emberAfIsDeviceIdentifying(EndpointId endpoint)
  140. {
  141. #ifdef ZCL_USING_IDENTIFY_CLUSTER_SERVER
  142. uint16_t identifyTime;
  143. EmberAfStatus status = emberAfReadServerAttribute(endpoint, ZCL_IDENTIFY_CLUSTER_ID, ZCL_IDENTIFY_TIME_ATTRIBUTE_ID,
  144. (uint8_t *) &identifyTime, sizeof(identifyTime));
  145. return (status == EMBER_ZCL_STATUS_SUCCESS && 0 < identifyTime);
  146. #else
  147. return false;
  148. #endif
  149. }
  150. // Calculates difference. See EmberAfDifferenceType for the maximum data size
  151. // that this function will support.
  152. EmberAfDifferenceType emberAfGetDifference(uint8_t * pData, EmberAfDifferenceType value, uint8_t dataSize)
  153. {
  154. EmberAfDifferenceType value2 = 0, diff;
  155. uint8_t i;
  156. // only support data types up to 8 bytes
  157. if (dataSize > sizeof(EmberAfDifferenceType))
  158. {
  159. return 0;
  160. }
  161. // get the value
  162. for (i = 0; i < dataSize; i++)
  163. {
  164. value2 = value2 << 8;
  165. #if (BIGENDIAN_CPU)
  166. value2 += pData[i];
  167. #else // BIGENDIAN
  168. value2 += pData[dataSize - i - 1];
  169. #endif // BIGENDIAN
  170. }
  171. if (value > value2)
  172. {
  173. diff = value - value2;
  174. }
  175. else
  176. {
  177. diff = value2 - value;
  178. }
  179. return diff;
  180. }
  181. // --------------------------------------------------
  182. static void prepareForResponse(const EmberAfClusterCommand * cmd)
  183. {
  184. emberAfResponseApsFrame.clusterId = cmd->apsFrame->clusterId;
  185. emberAfResponseApsFrame.sourceEndpoint = cmd->apsFrame->destinationEndpoint;
  186. emberAfResponseApsFrame.destinationEndpoint = cmd->apsFrame->sourceEndpoint;
  187. // Use the default APS options for the response, but also use encryption and
  188. // retries if the incoming message used them. The rationale is that the
  189. // sender of the request cares about some aspects of the delivery, so we as
  190. // the receiver should make equal effort for the response.
  191. emberAfResponseApsFrame.options = EMBER_AF_DEFAULT_APS_OPTIONS;
  192. if ((cmd->apsFrame->options & EMBER_APS_OPTION_RETRY) != 0U)
  193. {
  194. emberAfResponseApsFrame.options |= EMBER_APS_OPTION_RETRY;
  195. }
  196. if (cmd->interPanHeader == NULL)
  197. {
  198. emberAfResponseDestination = cmd->source;
  199. emberAfResponseType = static_cast<uint8_t>(emberAfResponseType & ~ZCL_UTIL_RESP_INTERPAN);
  200. }
  201. else
  202. {
  203. emberAfResponseType |= ZCL_UTIL_RESP_INTERPAN;
  204. memmove(&interpanResponseHeader, cmd->interPanHeader, sizeof(EmberAfInterpanHeader));
  205. // Always send responses as unicast
  206. interpanResponseHeader.messageType = EMBER_AF_INTER_PAN_UNICAST;
  207. }
  208. }
  209. // ****************************************
  210. // Initialize Clusters
  211. // ****************************************
  212. void emberAfInit(chip::Messaging::ExchangeManager * exchangeMgr)
  213. {
  214. uint8_t i;
  215. #ifdef EMBER_AF_ENABLE_STATISTICS
  216. afNumPktsSent = 0;
  217. #endif
  218. emAfExchangeMgr = exchangeMgr;
  219. for (i = 0; i < EMBER_SUPPORTED_NETWORKS; i++)
  220. {
  221. // FIXME: Do we need to support more than one network?
  222. // emberAfPushNetworkIndex(i);
  223. emberAfInitializeAttributes(EMBER_BROADCAST_ENDPOINT);
  224. // emberAfPopNetworkIndex();
  225. }
  226. memset(afDeviceEnabled, true, emberAfEndpointCount());
  227. // Set up client API buffer.
  228. emberAfSetExternalBuffer(appResponseData, EMBER_AF_RESPONSE_BUFFER_LEN, &appResponseLength, &emberAfResponseApsFrame);
  229. // initialize event management system
  230. emAfInitEvents();
  231. MATTER_PLUGINS_INIT
  232. emAfCallInits();
  233. }
  234. void emberAfTick(void)
  235. {
  236. // Call the AFV2-specific per-endpoint callbacks
  237. // Anything that defines callbacks as void *TickCallback(void) is called in
  238. // emAfInit(), which is a generated file
  239. #ifdef EMBER_AF_GENERATED_PLUGIN_TICK_FUNCTION_CALLS
  240. EMBER_AF_GENERATED_PLUGIN_TICK_FUNCTION_CALLS
  241. #endif
  242. }
  243. // Cluster init functions that don't have a cluster implementation to define
  244. // them in.
  245. void MatterBooleanStatePluginServerInitCallback() {}
  246. void MatterBridgedDeviceBasicPluginServerInitCallback() {}
  247. void MatterElectricalMeasurementPluginServerInitCallback() {}
  248. void MatterRelativeHumidityMeasurementPluginServerInitCallback() {}
  249. void MatterIlluminanceMeasurementPluginServerInitCallback() {}
  250. void MatterBinaryInputBasicPluginServerInitCallback() {}
  251. void MatterPressureMeasurementPluginServerInitCallback() {}
  252. void MatterTemperatureMeasurementPluginServerInitCallback() {}
  253. void MatterFlowMeasurementPluginServerInitCallback() {}
  254. void MatterOnOffSwitchConfigurationPluginServerInitCallback() {}
  255. void MatterThermostatUserInterfaceConfigurationPluginServerInitCallback() {}
  256. void MatterBridgedDeviceBasicInformationPluginServerInitCallback() {}
  257. void MatterPowerConfigurationPluginServerInitCallback() {}
  258. void MatterPowerProfilePluginServerInitCallback() {}
  259. void MatterPulseWidthModulationPluginServerInitCallback() {}
  260. void MatterAlarmsPluginServerInitCallback() {}
  261. void MatterTimePluginServerInitCallback() {}
  262. void MatterAclPluginServerInitCallback() {}
  263. void MatterPollControlPluginServerInitCallback() {}
  264. void MatterUnitLocalizationPluginServerInitCallback() {}
  265. void MatterTimeSynchronizationPluginServerInitCallback() {}
  266. void MatterProxyValidPluginServerInitCallback() {}
  267. void MatterProxyDiscoveryPluginServerInitCallback() {}
  268. void MatterProxyConfigurationPluginServerInitCallback() {}
  269. // ****************************************
  270. // This function is called by the application when the stack goes down,
  271. // such as after a leave network. This allows zcl utils to clear state
  272. // that should not be kept when changing networks
  273. // ****************************************
  274. void emberAfStackDown(void)
  275. {
  276. emberAfRegistrationAbortCallback();
  277. }
  278. // ****************************************
  279. // Print out information about each cluster
  280. // ****************************************
  281. uint16_t emberAfFindClusterNameIndex(ClusterId cluster)
  282. {
  283. static_assert(sizeof(ClusterId) == 4, "May need to adjust our index type or somehow define it in terms of cluster id type");
  284. uint16_t index = 0;
  285. while (zclClusterNames[index].id != ZCL_NULL_CLUSTER_ID)
  286. {
  287. if (zclClusterNames[index].id == cluster)
  288. {
  289. return index;
  290. }
  291. index++;
  292. }
  293. return 0xFFFF;
  294. }
  295. // This function parses into the cluster name table, and tries to find
  296. // the index in the table that has the right cluster id.
  297. void emberAfDecodeAndPrintCluster(ClusterId cluster)
  298. {
  299. uint16_t index = emberAfFindClusterNameIndex(cluster);
  300. if (index == 0xFFFF)
  301. {
  302. static_assert(sizeof(ClusterId) == 4, "Adjust the print formatting");
  303. emberAfPrint(emberAfPrintActiveArea, "(Unknown clus. [" ChipLogFormatMEI "])", ChipLogValueMEI(cluster));
  304. }
  305. else
  306. {
  307. emberAfPrint(emberAfPrintActiveArea, "(%p)", zclClusterNames[index].name);
  308. }
  309. }
  310. // This function makes the assumption that
  311. // emberAfCurrentCommand will either be NULL
  312. // when invalid, or will have a valid mfgCode
  313. // when called.
  314. // If it is invalid, we just return the
  315. // EMBER_AF_NULL_MANUFACTURER_CODE, which we tend to use
  316. // for references to the standard library.
  317. uint16_t emberAfGetMfgCodeFromCurrentCommand(void)
  318. {
  319. if (emberAfCurrentCommand() != NULL)
  320. {
  321. return emberAfCurrentCommand()->mfgCode;
  322. }
  323. else
  324. {
  325. return EMBER_AF_NULL_MANUFACTURER_CODE;
  326. }
  327. }
  328. uint8_t emberAfNextSequence(void)
  329. {
  330. return ((++emberAfSequenceNumber) & EMBER_AF_ZCL_SEQUENCE_MASK);
  331. }
  332. uint8_t emberAfGetLastSequenceNumber(void)
  333. {
  334. return (emberAfSequenceNumber & EMBER_AF_ZCL_SEQUENCE_MASK);
  335. }
  336. // the caller to the library can set a flag to say do not respond to the
  337. // next ZCL message passed in to the library. Passing true means disable
  338. // the reply for the next ZCL message. Setting to false re-enables the
  339. // reply (in the case where the app disables it and then doesnt send a
  340. // message that gets parsed).
  341. void emberAfSetNoReplyForNextMessage(bool set)
  342. {
  343. if (set)
  344. {
  345. emberAfResponseType |= ZCL_UTIL_RESP_NONE;
  346. }
  347. else
  348. {
  349. emberAfResponseType = static_cast<uint8_t>(emberAfResponseType & ~ZCL_UTIL_RESP_NONE);
  350. }
  351. }
  352. void emberAfSetRetryOverride(EmberAfRetryOverride value)
  353. {
  354. emberAfApsRetryOverride = value;
  355. }
  356. EmberAfRetryOverride emberAfGetRetryOverride(void)
  357. {
  358. return (EmberAfRetryOverride) emberAfApsRetryOverride;
  359. }
  360. void emAfApplyRetryOverride(EmberApsOption * options)
  361. {
  362. if (options == NULL)
  363. {
  364. return;
  365. }
  366. else if (emberAfApsRetryOverride == EMBER_AF_RETRY_OVERRIDE_SET)
  367. {
  368. *options |= EMBER_APS_OPTION_RETRY;
  369. }
  370. else if (emberAfApsRetryOverride == EMBER_AF_RETRY_OVERRIDE_UNSET)
  371. {
  372. *options = static_cast<EmberApsOption>(*options & ~EMBER_APS_OPTION_RETRY);
  373. }
  374. else
  375. {
  376. // MISRA requires ..else if.. to have terminating else.
  377. }
  378. }
  379. void emberAfSetDisableDefaultResponse(EmberAfDisableDefaultResponse value)
  380. {
  381. emAfDisableDefaultResponse = value;
  382. if (value != EMBER_AF_DISABLE_DEFAULT_RESPONSE_ONE_SHOT)
  383. {
  384. emAfSavedDisableDefaultResponseVale = value;
  385. }
  386. }
  387. EmberAfDisableDefaultResponse emberAfGetDisableDefaultResponse(void)
  388. {
  389. return (EmberAfDisableDefaultResponse) emAfDisableDefaultResponse;
  390. }
  391. void emAfApplyDisableDefaultResponse(uint8_t * frame_control)
  392. {
  393. if (frame_control == NULL)
  394. {
  395. return;
  396. }
  397. else if (emAfDisableDefaultResponse == EMBER_AF_DISABLE_DEFAULT_RESPONSE_ONE_SHOT)
  398. {
  399. emAfDisableDefaultResponse = emAfSavedDisableDefaultResponseVale;
  400. *frame_control |= ZCL_DISABLE_DEFAULT_RESPONSE_MASK;
  401. }
  402. else if (emAfDisableDefaultResponse == EMBER_AF_DISABLE_DEFAULT_RESPONSE_PERMANENT)
  403. {
  404. *frame_control |= ZCL_DISABLE_DEFAULT_RESPONSE_MASK;
  405. }
  406. else
  407. {
  408. // MISRA requires ..else if.. to have terminating else.
  409. }
  410. }
  411. static bool isBroadcastDestination(Messaging::ExchangeContext * responseDestination)
  412. {
  413. // TODO: Will need to actually figure out how to test for this!
  414. return false;
  415. }
  416. EmberStatus emberAfSendResponseWithCallback(EmberAfMessageSentFunction callback)
  417. {
  418. EmberStatus status;
  419. uint8_t label;
  420. // If the no-response flag is set, don't send anything.
  421. if ((emberAfResponseType & ZCL_UTIL_RESP_NONE) != 0U)
  422. {
  423. emberAfDebugPrintln("ZCL Util: no response at user request");
  424. return EMBER_SUCCESS;
  425. }
  426. // Make sure we are respecting the request APS options
  427. // there are seemingly some calls to emberAfSendResponse
  428. // that occur outside of the emberAfProcessMessage context,
  429. // which leads to a bad memory reference - AHilton
  430. if (emberAfCurrentCommand() != NULL)
  431. {
  432. if ((emberAfCurrentCommand()->apsFrame->options & EMBER_APS_OPTION_RETRY) != 0U)
  433. {
  434. emberAfResponseApsFrame.options |= EMBER_APS_OPTION_RETRY;
  435. }
  436. }
  437. // Fill commands may increase the sequence. For responses, we want to make
  438. // sure the sequence is reset to that of the request.
  439. if ((appResponseData[0] & ZCL_MANUFACTURER_SPECIFIC_MASK) != 0U)
  440. {
  441. appResponseData[3] = emberAfIncomingZclSequenceNumber;
  442. }
  443. else
  444. {
  445. appResponseData[1] = emberAfIncomingZclSequenceNumber;
  446. }
  447. // The manner in which the message is sent depends on the response flags and
  448. // the destination of the message.
  449. if ((emberAfResponseType & ZCL_UTIL_RESP_INTERPAN) != 0U)
  450. {
  451. label = 'I';
  452. status = emberAfInterpanSendMessageCallback(&interpanResponseHeader, appResponseLength, appResponseData);
  453. emberAfResponseType = static_cast<uint8_t>(emberAfResponseType & ~ZCL_UTIL_RESP_INTERPAN);
  454. }
  455. else if (!isBroadcastDestination(emberAfResponseDestination))
  456. {
  457. label = 'U';
  458. status = emberAfSendUnicastWithCallback(MessageSendDestination::ViaExchange(emberAfResponseDestination),
  459. &emberAfResponseApsFrame, appResponseLength, appResponseData, callback);
  460. }
  461. else
  462. {
  463. label = 'B';
  464. #if 0
  465. status = emberAfSendBroadcastWithCallback(emberAfResponseDestination,
  466. &emberAfResponseApsFrame,
  467. appResponseLength,
  468. appResponseData,
  469. callback);
  470. #else
  471. status = EMBER_SUCCESS;
  472. #endif
  473. }
  474. UNUSED_VAR(label);
  475. emberAfDebugPrintln("T%4x:TX (%p) %ccast 0x%x%p", 0, "resp", label, status, "");
  476. emberAfDebugPrint("TX buffer: [");
  477. emberAfDebugFlush();
  478. emberAfDebugPrintBuffer(appResponseData, appResponseLength, true);
  479. emberAfDebugPrintln("]");
  480. emberAfDebugFlush();
  481. #ifdef EMBER_AF_ENABLE_STATISTICS
  482. if (status == EMBER_SUCCESS)
  483. {
  484. afNumPktsSent++;
  485. }
  486. #endif
  487. return status;
  488. }
  489. EmberStatus emberAfSendResponse(void)
  490. {
  491. return emberAfSendResponseWithCallback(NULL);
  492. }
  493. EmberStatus emberAfSendImmediateDefaultResponseWithCallback(EmberAfStatus status, EmberAfMessageSentFunction callback)
  494. {
  495. return emberAfSendDefaultResponseWithCallback(emberAfCurrentCommand(), status, callback);
  496. }
  497. EmberStatus emberAfSendImmediateDefaultResponse(EmberAfStatus status)
  498. {
  499. return emberAfSendImmediateDefaultResponseWithCallback(status, NULL);
  500. }
  501. EmberStatus emberAfSendDefaultResponseWithCallback(const EmberAfClusterCommand * cmd, EmberAfStatus status,
  502. EmberAfMessageSentFunction callback)
  503. {
  504. uint8_t frameControl;
  505. // Default Response commands are only sent in response to unicast commands.
  506. if (cmd->type != EMBER_INCOMING_UNICAST && cmd->type != EMBER_INCOMING_UNICAST_REPLY)
  507. {
  508. return EMBER_SUCCESS;
  509. }
  510. if (chip::app::Compatibility::IMEmberAfSendDefaultResponseWithCallback(status))
  511. {
  512. // If the compatibility can handle this response
  513. return EMBER_SUCCESS;
  514. }
  515. // If the Disable Default Response sub-field is set, Default Response commands
  516. // are only sent if there was an error.
  517. if ((cmd->buffer[0] & ZCL_DISABLE_DEFAULT_RESPONSE_MASK) && status == EMBER_ZCL_STATUS_SUCCESS)
  518. {
  519. return EMBER_SUCCESS;
  520. }
  521. // Default Response commands are never sent in response to other Default
  522. // Response commands.
  523. if (!cmd->clusterSpecific && cmd->commandId == ZCL_DEFAULT_RESPONSE_COMMAND_ID)
  524. {
  525. return EMBER_SUCCESS;
  526. }
  527. appResponseLength = 0;
  528. frameControl = static_cast<uint8_t>(ZCL_GLOBAL_COMMAND |
  529. (cmd->direction == ZCL_DIRECTION_CLIENT_TO_SERVER ? ZCL_FRAME_CONTROL_SERVER_TO_CLIENT
  530. : ZCL_FRAME_CONTROL_CLIENT_TO_SERVER));
  531. if (!cmd->mfgSpecific)
  532. {
  533. emberAfPutInt8uInResp(frameControl & (uint8_t) ~ZCL_MANUFACTURER_SPECIFIC_MASK);
  534. }
  535. else
  536. {
  537. emberAfPutInt8uInResp(frameControl | ZCL_MANUFACTURER_SPECIFIC_MASK);
  538. emberAfPutInt16uInResp(cmd->mfgCode);
  539. }
  540. emberAfPutInt8uInResp(cmd->seqNum);
  541. emberAfPutInt32uInResp(ZCL_DEFAULT_RESPONSE_COMMAND_ID);
  542. emberAfPutInt32uInResp(cmd->commandId);
  543. emberAfPutStatusInResp(status);
  544. prepareForResponse(cmd);
  545. return emberAfSendResponseWithCallback(callback);
  546. }
  547. EmberStatus emberAfSendDefaultResponse(const EmberAfClusterCommand * cmd, EmberAfStatus status)
  548. {
  549. return emberAfSendDefaultResponseWithCallback(cmd, status, NULL);
  550. }
  551. void emberAfCopyInt16u(uint8_t * data, uint16_t index, uint16_t x)
  552. {
  553. data[index] = (uint8_t)(((x)) & 0xFF);
  554. data[index + 1] = (uint8_t)(((x) >> 8) & 0xFF);
  555. }
  556. void emberAfCopyInt24u(uint8_t * data, uint16_t index, uint32_t x)
  557. {
  558. data[index] = (uint8_t)(((x)) & 0xFF);
  559. data[index + 1] = (uint8_t)(((x) >> 8) & 0xFF);
  560. data[index + 2] = (uint8_t)(((x) >> 16) & 0xFF);
  561. }
  562. void emberAfCopyInt32u(uint8_t * data, uint16_t index, uint32_t x)
  563. {
  564. data[index] = (uint8_t)(((x)) & 0xFF);
  565. data[index + 1] = (uint8_t)(((x) >> 8) & 0xFF);
  566. data[index + 2] = (uint8_t)(((x) >> 16) & 0xFF);
  567. data[index + 3] = (uint8_t)(((x) >> 24) & 0xFF);
  568. }
  569. void emberAfCopyString(uint8_t * dest, const uint8_t * src, size_t size)
  570. {
  571. if (src == NULL)
  572. {
  573. dest[0] = 0; // Zero out the length of string
  574. }
  575. else if (src[0] == 0xFF)
  576. {
  577. dest[0] = src[0];
  578. }
  579. else
  580. {
  581. uint8_t length = emberAfStringLength(src);
  582. if (size < length)
  583. {
  584. // Since we have checked that size < length, size must be able to fit into the type of length.
  585. length = static_cast<decltype(length)>(size);
  586. }
  587. memmove(dest + 1, src + 1, length);
  588. dest[0] = length;
  589. }
  590. }
  591. void emberAfCopyLongString(uint8_t * dest, const uint8_t * src, size_t size)
  592. {
  593. if (src == NULL)
  594. {
  595. dest[0] = dest[1] = 0; // Zero out the length of string
  596. }
  597. else if ((src[0] == 0xFF) && (src[1] == 0xFF))
  598. {
  599. dest[0] = 0xFF;
  600. dest[1] = 0xFF;
  601. }
  602. else
  603. {
  604. uint16_t length = emberAfLongStringLength(src);
  605. if (size < length)
  606. {
  607. // Since we have checked that size < length, size must be able to fit into the type of length.
  608. length = static_cast<decltype(length)>(size);
  609. }
  610. memmove(dest + 2, src + 2, length);
  611. dest[0] = EMBER_LOW_BYTE(length);
  612. dest[1] = EMBER_HIGH_BYTE(length);
  613. }
  614. }
  615. #if (BIGENDIAN_CPU)
  616. #define EM_BIG_ENDIAN true
  617. #else
  618. #define EM_BIG_ENDIAN false
  619. #endif
  620. // You can pass in val1 as NULL, which will assume that it is
  621. // pointing to an array of all zeroes. This is used so that
  622. // default value of NULL is treated as all zeroes.
  623. int8_t emberAfCompareValues(const uint8_t * val1, const uint8_t * val2, uint16_t len, bool signedNumber)
  624. {
  625. uint8_t i, j, k;
  626. if (signedNumber)
  627. { // signed number comparison
  628. if (len <= 4)
  629. { // only number with 32-bits or less is supported
  630. int32_t accum1 = 0x0;
  631. int32_t accum2 = 0x0;
  632. int32_t all1s = -1;
  633. for (i = 0; i < len; i++)
  634. {
  635. j = (val1 == NULL ? 0 : (EM_BIG_ENDIAN ? val1[i] : val1[(len - 1) - i]));
  636. accum1 |= j << (8 * (len - 1 - i));
  637. k = (EM_BIG_ENDIAN ? val2[i] : val2[(len - 1) - i]);
  638. accum2 |= k << (8 * (len - 1 - i));
  639. }
  640. // sign extending, no need for 32-bits numbers
  641. if (len < 4)
  642. {
  643. if ((accum1 & (1 << (8 * len - 1))) != 0)
  644. { // check sign
  645. accum1 |= all1s - ((1 << (len * 8)) - 1);
  646. }
  647. if ((accum2 & (1 << (8 * len - 1))) != 0)
  648. { // check sign
  649. accum2 |= all1s - ((1 << (len * 8)) - 1);
  650. }
  651. }
  652. if (accum1 > accum2)
  653. {
  654. return 1;
  655. }
  656. else if (accum1 < accum2)
  657. {
  658. return -1;
  659. }
  660. else
  661. {
  662. return 0;
  663. }
  664. }
  665. else
  666. { // not supported
  667. return 0;
  668. }
  669. }
  670. else
  671. { // regular unsigned number comparison
  672. for (i = 0; i < len; i++)
  673. {
  674. j = (val1 == NULL ? 0 : (EM_BIG_ENDIAN ? val1[i] : val1[(len - 1) - i]));
  675. k = (EM_BIG_ENDIAN ? val2[i] : val2[(len - 1) - i]);
  676. if (j > k)
  677. {
  678. return 1;
  679. }
  680. else if (k > j)
  681. {
  682. return -1;
  683. }
  684. else
  685. {
  686. // MISRA requires ..else if.. to have terminating else.
  687. }
  688. }
  689. return 0;
  690. }
  691. }
  692. #if 0
  693. // Moving to time-util.c
  694. int8_t emberAfCompareDates(EmberAfDate* date1, EmberAfDate* date2)
  695. {
  696. uint32_t val1 = emberAfEncodeDate(date1);
  697. uint32_t val2 = emberAfEncodeDate(date2);
  698. return (val1 == val2) ? 0 : ((val1 < val2) ? -1 : 1);
  699. }
  700. #endif
  701. // Zigbee spec says types between signed 8 bit and signed 64 bit
  702. bool emberAfIsTypeSigned(EmberAfAttributeType dataType)
  703. {
  704. return (dataType >= ZCL_INT8S_ATTRIBUTE_TYPE && dataType <= ZCL_INT64S_ATTRIBUTE_TYPE);
  705. }
  706. EmberStatus emberAfEndpointEventControlSetInactive(EmberEventControl * controls, EndpointId endpoint)
  707. {
  708. uint16_t index = emberAfIndexFromEndpoint(endpoint);
  709. if (index == 0xFFFF)
  710. {
  711. return EMBER_INVALID_ENDPOINT;
  712. }
  713. emberEventControlSetInactive(&controls[index]);
  714. return EMBER_SUCCESS;
  715. }
  716. bool emberAfEndpointEventControlGetActive(EmberEventControl * controls, EndpointId endpoint)
  717. {
  718. uint16_t index = emberAfIndexFromEndpoint(endpoint);
  719. return (index != 0xFFFF && emberEventControlGetActive(&controls[index]));
  720. }
  721. EmberStatus emberAfEndpointEventControlSetActive(EmberEventControl * controls, EndpointId endpoint)
  722. {
  723. uint16_t index = emberAfIndexFromEndpoint(endpoint);
  724. if (index == 0xFFFF)
  725. {
  726. return EMBER_INVALID_ENDPOINT;
  727. }
  728. emberEventControlSetActive(&controls[index]);
  729. return EMBER_SUCCESS;
  730. }
  731. uint8_t emberAfAppendCharacters(uint8_t * zclString, uint8_t zclStringMaxLen, const uint8_t * appendingChars,
  732. uint8_t appendingCharsLen)
  733. {
  734. uint8_t freeChars;
  735. uint8_t curLen;
  736. uint8_t charsToWrite;
  737. if ((zclString == NULL) || (zclStringMaxLen == 0) || (appendingChars == NULL) || (appendingCharsLen == 0))
  738. {
  739. return 0;
  740. }
  741. curLen = emberAfStringLength(zclString);
  742. if ((zclString[0] == 0xFF) || (curLen >= zclStringMaxLen))
  743. {
  744. return 0;
  745. }
  746. freeChars = static_cast<uint8_t>(zclStringMaxLen - curLen);
  747. charsToWrite = (freeChars > appendingCharsLen) ? appendingCharsLen : freeChars;
  748. memcpy(&zclString[1 + curLen], // 1 is to account for zcl's length byte
  749. appendingChars, charsToWrite);
  750. // Cast is safe, because the sum can't be bigger than zclStringMaxLen.
  751. zclString[0] = static_cast<uint8_t>(curLen + charsToWrite);
  752. return charsToWrite;
  753. }
  754. /*
  755. On each page, first channel maps to channel number zero and so on.
  756. Example:
  757. page Band Rage of 90 channels Per page channel mapping
  758. 28 863 MHz 0-26 0-26
  759. 29 863 MHz 27-34,62 0-8 (Here 7th channel maps to 34 and 8th to 62)
  760. 30 863 MHz 35 - 61 0-26
  761. 31 915 0-26 0-26
  762. */
  763. EmberStatus emAfValidateChannelPages(uint8_t page, uint8_t channel)
  764. {
  765. switch (page)
  766. {
  767. case 0:
  768. if (!((channel <= EMBER_MAX_802_15_4_CHANNEL_NUMBER) &&
  769. ((EMBER_MIN_802_15_4_CHANNEL_NUMBER == 0) || (channel >= EMBER_MIN_802_15_4_CHANNEL_NUMBER))))
  770. {
  771. return EMBER_PHY_INVALID_CHANNEL;
  772. }
  773. break;
  774. case 28:
  775. case 30:
  776. case 31:
  777. if (channel > EMBER_MAX_SUBGHZ_CHANNEL_NUMBER_ON_PAGES_28_30_31)
  778. {
  779. return EMBER_PHY_INVALID_CHANNEL;
  780. }
  781. break;
  782. case 29:
  783. if (channel > EMBER_MAX_SUBGHZ_CHANNEL_NUMBER_ON_PAGE_29)
  784. {
  785. return EMBER_PHY_INVALID_CHANNEL;
  786. }
  787. break;
  788. default:
  789. return EMBER_PHY_INVALID_CHANNEL;
  790. break;
  791. }
  792. return EMBER_SUCCESS;
  793. }
  794. void slabAssert(const char * file, int line)
  795. {
  796. (void) file; // Unused parameter
  797. (void) line; // Unused parameter
  798. // Wait forever until the watchdog fires
  799. while (true)
  800. {
  801. }
  802. }
  803. #define ENCODED_8BIT_CHANPG_PAGE_MASK 0xE0 // top 3 bits
  804. #define ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_0 0x00 // 0b000xxxxx
  805. #define ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_28 0x80 // 0b100xxxxx
  806. #define ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_29 0xA0 // 0b101xxxxx
  807. #define ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_30 0xC0 // 0b110xxxxx
  808. #define ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_31 0xE0 // 0b111xxxxx
  809. #define ENCODED_8BIT_CHANPG_CHANNEL_MASK 0x1F // bottom 5 bits
  810. uint8_t emberAfGetPageFrom8bitEncodedChanPg(uint8_t chanPg)
  811. {
  812. switch (chanPg & ENCODED_8BIT_CHANPG_PAGE_MASK)
  813. {
  814. case ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_0:
  815. return 0;
  816. case ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_28:
  817. return 28;
  818. case ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_29:
  819. return 29;
  820. case ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_30:
  821. return 30;
  822. case ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_31:
  823. return 31;
  824. default:
  825. return 0xFF;
  826. }
  827. }
  828. uint8_t emberAfGetChannelFrom8bitEncodedChanPg(uint8_t chanPg)
  829. {
  830. return chanPg & ENCODED_8BIT_CHANPG_CHANNEL_MASK;
  831. }
  832. uint8_t emberAfMake8bitEncodedChanPg(uint8_t page, uint8_t channel)
  833. {
  834. if (emAfValidateChannelPages(page, channel) != EMBER_SUCCESS)
  835. {
  836. return 0xFF;
  837. }
  838. switch (page)
  839. {
  840. case 28:
  841. return channel | ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_28;
  842. case 29:
  843. return channel | ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_29;
  844. case 30:
  845. return channel | ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_30;
  846. case 31:
  847. return channel | ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_31;
  848. default:
  849. // Strictly speaking, we only need case 0 here, but MISRA in its infinite
  850. // wisdom requires a default case. Since we have validated the arguments
  851. // already, and 0 is the only remaining case, we simply treat the default
  852. // as case 0 to make MISRA happy.
  853. return channel | ENCODED_8BIT_CHANPG_PAGE_MASK_PAGE_0;
  854. }
  855. }
  856. bool emberAfContainsAttribute(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, bool asServer)
  857. {
  858. uint8_t mask = asServer ? CLUSTER_MASK_SERVER : CLUSTER_MASK_CLIENT;
  859. return (emberAfLocateAttributeMetadata(endpoint, clusterId, attributeId, mask) != nullptr);
  860. }
  861. bool emberAfIsNonVolatileAttribute(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId,
  862. bool asServer)
  863. {
  864. uint8_t mask = asServer ? CLUSTER_MASK_SERVER : CLUSTER_MASK_CLIENT;
  865. const EmberAfAttributeMetadata * metadata = emberAfLocateAttributeMetadata(endpoint, clusterId, attributeId, mask);
  866. if (metadata == nullptr)
  867. {
  868. return false;
  869. }
  870. return metadata->IsNonVolatile();
  871. }
  872. chip::Messaging::ExchangeManager * chip::ExchangeManager()
  873. {
  874. return emAfExchangeMgr;
  875. }