1 /* 2 * Copyright (c) 2018, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for the spinel based radio transceiver. 32 */ 33 34 #ifndef RADIO_SPINEL_HPP_ 35 #define RADIO_SPINEL_HPP_ 36 37 #include <openthread/platform/radio.h> 38 39 #include "openthread-spinel-config.h" 40 #include "core/radio/max_power_table.hpp" 41 #include "lib/spinel/logger.hpp" 42 #include "lib/spinel/radio_spinel_metrics.h" 43 #include "lib/spinel/spinel.h" 44 #include "lib/spinel/spinel_driver.hpp" 45 #include "lib/spinel/spinel_interface.hpp" 46 #include "ncp/ncp_config.h" 47 48 namespace ot { 49 namespace Spinel { 50 51 struct RadioSpinelCallbacks 52 { 53 /** 54 * This callback notifies user of `RadioSpinel` of a received frame. 55 * 56 * @param[in] aInstance The OpenThread instance structure. 57 * @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed. 58 * @param[in] aError kErrorNone when successfully received a frame, 59 * kErrorAbort when reception was aborted and a frame was not received, 60 * kErrorNoBufs when a frame could not be received due to lack of rx buffer space. 61 * 62 */ 63 void (*mReceiveDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError); 64 65 /** 66 * The callback notifies user of `RadioSpinel` that the transmit operation has completed, providing, if 67 * applicable, the received ACK frame. 68 * 69 * @param[in] aInstance The OpenThread instance structure. 70 * @param[in] aFrame The transmitted frame. 71 * @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received. 72 * @param[in] aError kErrorNone when the frame was transmitted, 73 * kErrorNoAck when the frame was transmitted but no ACK was received, 74 * kErrorChannelAccessFailure tx failed due to activity on the channel, 75 * kErrorAbort when transmission was aborted for other reasons. 76 * 77 */ 78 void (*mTransmitDone)(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, Error aError); 79 80 /** 81 * This callback notifies user of `RadioSpinel` that energy scan is complete. 82 * 83 * @param[in] aInstance The OpenThread instance structure. 84 * @param[in] aMaxRssi Maximum RSSI seen on the channel, or `SubMac::kInvalidRssiValue` if failed. 85 * 86 */ 87 void (*mEnergyScanDone)(otInstance *aInstance, int8_t aMaxRssi); 88 89 /** 90 * This callback notifies user of `RadioSpinel` that the transmission has started. 91 * 92 * @param[in] aInstance A pointer to the OpenThread instance structure. 93 * @param[in] aFrame A pointer to the frame that is being transmitted. 94 * 95 */ 96 void (*mTxStarted)(otInstance *aInstance, otRadioFrame *aFrame); 97 98 /** 99 * This callback notifies user of `RadioSpinel` that the radio interface switchover has completed. 100 * 101 * @param[in] aInstance A pointer to the OpenThread instance structure. 102 * @param[in] aSuccess A value indicating if the switchover was successful or not. 103 * 104 */ 105 void (*mSwitchoverDone)(otInstance *aInstance, bool aSuccess); 106 107 #if OPENTHREAD_CONFIG_DIAG_ENABLE 108 /** 109 * This callback notifies diagnostics module using `RadioSpinel` of a received frame. 110 * 111 * This callback is used when diagnostics is enabled. 112 * 113 * @param[in] aInstance The OpenThread instance structure. 114 * @param[in] aFrame A pointer to the received frame or NULL if the receive operation failed. 115 * @param[in] aError OT_ERROR_NONE when successfully received a frame, 116 * OT_ERROR_ABORT when reception was aborted and a frame was not received, 117 * OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space. 118 * 119 */ 120 void (*mDiagReceiveDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError); 121 122 /** 123 * This callback notifies diagnostics module using `RadioSpinel` that the transmission has completed. 124 * 125 * This callback is used when diagnostics is enabled. 126 * 127 * @param[in] aInstance The OpenThread instance structure. 128 * @param[in] aFrame A pointer to the frame that was transmitted. 129 * @param[in] aError OT_ERROR_NONE when the frame was transmitted, 130 * OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on the 131 * channel, OT_ERROR_ABORT when transmission was aborted for other reasons. 132 * 133 */ 134 void (*mDiagTransmitDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError); 135 #endif // OPENTHREAD_CONFIG_DIAG_ENABLE 136 }; 137 138 /** 139 * The class for providing a OpenThread radio interface by talking with a radio-only 140 * co-processor(RCP). 141 * 142 */ 143 class RadioSpinel : private Logger 144 { 145 public: 146 /** 147 * Initializes the spinel based OpenThread transceiver. 148 * 149 */ 150 RadioSpinel(void); 151 152 /** 153 * Deinitializes the spinel based OpenThread transceiver. 154 * 155 */ ~RadioSpinel(void)156 ~RadioSpinel(void) { Deinit(); } 157 158 /** 159 * Initialize this radio transceiver. 160 * 161 * @param[in] aSkipRcpCompatibilityCheck TRUE to skip RCP compatibility check, FALSE to perform the check. 162 * @param[in] aSoftwareReset When doing RCP recovery, TRUE to try software reset first, FALSE to 163 * directly do a hardware reset. 164 * @param[in] aSpinelDriver A pointer to the spinel driver instance that this object depends on. 165 * 166 */ 167 void Init(bool aSkipRcpCompatibilityCheck, bool aSoftwareReset, SpinelDriver *aSpinelDriver); 168 169 /** 170 * This method sets the notification callbacks. 171 * 172 * @param[in] aCallbacks A pointer to structure with notification callbacks. 173 * 174 */ 175 void SetCallbacks(const struct RadioSpinelCallbacks &aCallbacks); 176 177 /** 178 * Deinitialize this radio transceiver. 179 * 180 */ 181 void Deinit(void); 182 183 /** 184 * Gets the status of promiscuous mode. 185 * 186 * @retval true Promiscuous mode is enabled. 187 * @retval false Promiscuous mode is disabled. 188 * 189 */ IsPromiscuous(void) const190 bool IsPromiscuous(void) const { return mIsPromiscuous; } 191 192 /** 193 * Sets the status of promiscuous mode. 194 * 195 * @param[in] aEnable Whether to enable or disable promiscuous mode. 196 * 197 * @retval OT_ERROR_NONE Succeeded. 198 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 199 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 200 * 201 */ 202 otError SetPromiscuous(bool aEnable); 203 204 /** 205 * Sets the status of RxOnWhenIdle mode. 206 * 207 * @param[in] aEnable Whether to enable or disable RxOnWhenIdle mode. 208 * 209 * @retval OT_ERROR_NONE Succeeded. 210 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 211 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 212 * 213 */ 214 otError SetRxOnWhenIdle(bool aEnable); 215 216 /** 217 * Sets the Short Address for address filtering. 218 * 219 * @param[in] aShortAddress The IEEE 802.15.4 Short Address. 220 * 221 * @retval OT_ERROR_NONE Succeeded. 222 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 223 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 224 * 225 */ 226 otError SetShortAddress(uint16_t aAddress); 227 228 /** 229 * Gets the factory-assigned IEEE EUI-64 for this transceiver. 230 * 231 * @param[in] aInstance The OpenThread instance structure. 232 * @param[out] aIeeeEui64 A pointer to the factory-assigned IEEE EUI-64. 233 * 234 * @retval OT_ERROR_NONE Succeeded. 235 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 236 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 237 * 238 */ 239 otError GetIeeeEui64(uint8_t *aIeeeEui64); 240 241 /** 242 * Sets the Extended Address for address filtering. 243 * 244 * @param[in] aExtAddress A pointer to the IEEE 802.15.4 Extended Address stored in little-endian byte order. 245 * 246 * @retval OT_ERROR_NONE Succeeded. 247 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 248 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 249 * 250 */ 251 otError SetExtendedAddress(const otExtAddress &aExtAddress); 252 253 /** 254 * Sets the PAN ID for address filtering. 255 * 256 * @param[in] aPanId The IEEE 802.15.4 PAN ID. 257 * 258 * @retval OT_ERROR_NONE Succeeded. 259 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 260 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 261 * 262 */ 263 otError SetPanId(uint16_t aPanId); 264 265 /** 266 * Gets the radio's transmit power in dBm. 267 * 268 * @param[out] aPower The transmit power in dBm. 269 * 270 * @retval OT_ERROR_NONE Succeeded. 271 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 272 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 273 * 274 */ 275 otError GetTransmitPower(int8_t &aPower); 276 277 /** 278 * Sets the radio's transmit power in dBm. 279 * 280 * @param[in] aPower The transmit power in dBm. 281 * 282 * @retval OT_ERROR_NONE Succeeded. 283 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 284 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 285 * 286 */ 287 otError SetTransmitPower(int8_t aPower); 288 289 /** 290 * Gets the radio's CCA ED threshold in dBm. 291 * 292 * @param[out] aThreshold The CCA ED threshold in dBm. 293 * 294 * @retval OT_ERROR_NONE Succeeded. 295 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 296 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 297 * 298 */ 299 otError GetCcaEnergyDetectThreshold(int8_t &aThreshold); 300 301 /** 302 * Sets the radio's CCA ED threshold in dBm. 303 * 304 * @param[in] aThreshold The CCA ED threshold in dBm. 305 * 306 * @retval OT_ERROR_NONE Succeeded. 307 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 308 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 309 * 310 */ 311 otError SetCcaEnergyDetectThreshold(int8_t aThreshold); 312 313 /** 314 * Gets the FEM's Rx LNA gain in dBm. 315 * 316 * @param[out] aGain The FEM's Rx LNA gain in dBm. 317 * 318 * @retval OT_ERROR_NONE Succeeded. 319 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 320 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 321 * 322 */ 323 otError GetFemLnaGain(int8_t &aGain); 324 325 /** 326 * Sets the FEM's Rx LNA gain in dBm. 327 * 328 * @param[in] aGain The FEM's Rx LNA gain in dBm. 329 * 330 * @retval OT_ERROR_NONE Succeeded. 331 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 332 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 333 * 334 */ 335 otError SetFemLnaGain(int8_t aGain); 336 337 /** 338 * Returns the radio capabilities. 339 * 340 * @returns The radio capability bit vector. 341 * 342 */ GetRadioCaps(void) const343 otRadioCaps GetRadioCaps(void) const { return sRadioCaps; } 344 345 /** 346 * Gets the most recent RSSI measurement. 347 * 348 * @returns The RSSI in dBm when it is valid. 127 when RSSI is invalid. 349 */ 350 int8_t GetRssi(void); 351 352 /** 353 * Returns the radio receive sensitivity value. 354 * 355 * @returns The radio receive sensitivity value in dBm. 356 * 357 * @retval OT_ERROR_NONE Succeeded. 358 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 359 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 360 * 361 */ GetReceiveSensitivity(void) const362 int8_t GetReceiveSensitivity(void) const { return mRxSensitivity; } 363 364 /** 365 * Gets current state of the radio. 366 * 367 * @return Current state of the radio. 368 * 369 */ 370 otRadioState GetState(void) const; 371 372 /** 373 * Gets the current receiving channel. 374 * 375 * @returns Current receiving channel. 376 * 377 */ GetChannel(void) const378 uint8_t GetChannel(void) const { return mChannel; } 379 380 #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE 381 /** 382 * Enable the radio coex. 383 * 384 * @param[in] aInstance The OpenThread instance structure. 385 * @param[in] aEnabled TRUE to enable the radio coex, FALSE otherwise. 386 * 387 * @retval OT_ERROR_NONE Successfully enabled. 388 * @retval OT_ERROR_FAILED The radio coex could not be enabled. 389 * 390 */ 391 otError SetCoexEnabled(bool aEnabled); 392 393 /** 394 * Check whether radio coex is enabled or not. 395 * 396 * @param[in] aInstance The OpenThread instance structure. 397 * 398 * @returns TRUE if the radio coex is enabled, FALSE otherwise. 399 * 400 */ 401 bool IsCoexEnabled(void); 402 403 /** 404 * Retrieves the radio coexistence metrics. 405 * 406 * @param[out] aCoexMetrics A reference to the coexistence metrics structure. 407 * 408 * @retval OT_ERROR_NONE Successfully retrieved the coex metrics. 409 * @retval OT_ERROR_INVALID_ARGS @p aCoexMetrics was nullptr. 410 * 411 */ 412 otError GetCoexMetrics(otRadioCoexMetrics &aCoexMetrics); 413 #endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE 414 415 /** 416 * Get currently active interface. 417 * 418 * @param[out] aIid IID of the interface that owns the radio. 419 * 420 * @retval OT_ERROR_NONE Successfully got the property. 421 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 422 * @retval OT_ERROR_NOT_IMPLEMENTED Failed due to lack of the support in radio 423 * @retval OT_ERROR_INVALID_COMMAND Platform supports all interfaces simultaneously. 424 * (i.e. no active/inactive interface concept in the platform level) 425 * 426 */ 427 otError GetMultipanActiveInterface(spinel_iid_t *aIid); 428 429 /** 430 * Sets specified radio interface active 431 * 432 * This function allows selecting currently active radio interface on platforms that do not support parallel 433 * communication on multiple interfaces. I.e. if more than one interface is in receive state calling 434 * SetMultipanActiveInterface guarantees that specified interface will not be losing frames. This function 435 * returns if the request was received properly. After interface switching is complete SwitchoverDone callback is 436 * Invoked. Switching interfaces may take longer if aCompletePending is set true. 437 * 438 * @param[in] aIid IID of the interface to set active. 439 * @param[in] aCompletePending Set true if pending radio operation should complete first(Soft switch) or false if 440 * ongoing operations should be interrupted (Force switch). 441 * 442 * @retval OT_ERROR_NONE Successfully requested interface switch. 443 * @retval OT_ERROR_BUSY Failed due to another operation on going. 444 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 445 * @retval OT_ERROR_NOT_IMPLEMENTED Failed due to lack of support in radio for the given interface id or 446 * @retval OT_ERROR_INVALID_COMMAND Platform supports all interfaces simultaneously 447 * (i.e. no active/inactive interface concept in the platform level) 448 * @retval OT_ERROR_ALREADY Given interface is already active. 449 * 450 */ 451 otError SetMultipanActiveInterface(spinel_iid_t aIid, bool aCompletePending); 452 453 /** 454 * Returns a reference to the transmit buffer. 455 * 456 * The caller forms the IEEE 802.15.4 frame in this buffer then calls otPlatRadioTransmit() to request transmission. 457 * 458 * @returns A reference to the transmit buffer. 459 * 460 */ GetTransmitFrame(void)461 otRadioFrame &GetTransmitFrame(void) { return mTxRadioFrame; } 462 463 /** 464 * Enables or disables source address match feature. 465 * 466 * @param[in] aEnable Enable/disable source address match feature. 467 * 468 * @retval OT_ERROR_NONE Succeeded. 469 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 470 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 471 * 472 */ 473 otError EnableSrcMatch(bool aEnable); 474 475 /** 476 * Adds a short address to the source address match table. 477 * 478 * @param[in] aInstance The OpenThread instance structure. 479 * @param[in] aShortAddress The short address to be added. 480 * 481 * @retval OT_ERROR_NONE Successfully added short address to the source match table. 482 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 483 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 484 * @retval OT_ERROR_NO_BUFS No available entry in the source match table. 485 */ 486 otError AddSrcMatchShortEntry(uint16_t aShortAddress); 487 488 /** 489 * Removes a short address from the source address match table. 490 * 491 * @param[in] aInstance The OpenThread instance structure. 492 * @param[in] aShortAddress The short address to be removed. 493 * 494 * @retval OT_ERROR_NONE Successfully removed short address from the source match table. 495 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 496 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 497 * @retval OT_ERROR_NO_ADDRESS The short address is not in source address match table. 498 */ 499 otError ClearSrcMatchShortEntry(uint16_t aShortAddress); 500 501 /** 502 * Clear all short addresses from the source address match table. 503 * 504 * @param[in] aInstance The OpenThread instance structure. 505 * 506 * @retval OT_ERROR_NONE Succeeded. 507 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 508 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 509 * 510 */ 511 otError ClearSrcMatchShortEntries(void); 512 513 /** 514 * Add an extended address to the source address match table. 515 * 516 * @param[in] aInstance The OpenThread instance structure. 517 * @param[in] aExtAddress The extended address to be added stored in little-endian byte order. 518 * 519 * @retval OT_ERROR_NONE Successfully added extended address to the source match table. 520 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 521 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 522 * @retval OT_ERROR_NO_BUFS No available entry in the source match table. 523 */ 524 otError AddSrcMatchExtEntry(const otExtAddress &aExtAddress); 525 526 /** 527 * Remove an extended address from the source address match table. 528 * 529 * @param[in] aInstance The OpenThread instance structure. 530 * @param[in] aExtAddress The extended address to be removed stored in little-endian byte order. 531 * 532 * @retval OT_ERROR_NONE Successfully removed the extended address from the source match table. 533 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 534 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 535 * @retval OT_ERROR_NO_ADDRESS The extended address is not in source address match table. 536 */ 537 otError ClearSrcMatchExtEntry(const otExtAddress &aExtAddress); 538 539 /** 540 * Clear all the extended/long addresses from source address match table. 541 * 542 * @param[in] aInstance The OpenThread instance structure. 543 * 544 * @retval OT_ERROR_NONE Succeeded. 545 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 546 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 547 * 548 */ 549 otError ClearSrcMatchExtEntries(void); 550 551 /** 552 * Begins the energy scan sequence on the radio. 553 * 554 * @param[in] aScanChannel The channel to perform the energy scan on. 555 * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. 556 * 557 * @retval OT_ERROR_NONE Succeeded. 558 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 559 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 560 * 561 */ 562 otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration); 563 564 /** 565 * Switches the radio state from Receive to Transmit. 566 * 567 * @param[in] aFrame A reference to the transmitted frame. 568 * 569 * @retval OT_ERROR_NONE Successfully transitioned to Transmit. 570 * @retval OT_ERROR_BUSY Failed due to another transmission is on going. 571 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 572 * @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state. 573 */ 574 otError Transmit(otRadioFrame &aFrame); 575 576 /** 577 * Switches the radio state from Sleep to Receive. 578 * 579 * @param[in] aChannel The channel to use for receiving. 580 * 581 * @retval OT_ERROR_NONE Successfully transitioned to Receive. 582 * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting. 583 * 584 */ 585 otError Receive(uint8_t aChannel); 586 587 /** 588 * Switches the radio state from Receive to Sleep. 589 * 590 * @retval OT_ERROR_NONE Successfully transitioned to Sleep. 591 * @retval OT_ERROR_BUSY The radio was transmitting 592 * @retval OT_ERROR_INVALID_STATE The radio was disabled 593 * 594 */ 595 otError Sleep(void); 596 597 /** 598 * Enable the radio. 599 * 600 * @param[in] aInstance A pointer to the OpenThread instance. 601 * 602 * @retval OT_ERROR_NONE Successfully enabled. 603 * @retval OT_ERROR_FAILED The radio could not be enabled. 604 * 605 */ 606 otError Enable(otInstance *aInstance); 607 608 /** 609 * Disable the radio. 610 * 611 * @retval OT_ERROR_NONE Successfully transitioned to Disabled. 612 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 613 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 614 * 615 */ 616 otError Disable(void); 617 618 /** 619 * Checks whether radio is enabled or not. 620 * 621 * @returns TRUE if the radio is enabled, FALSE otherwise. 622 * 623 */ IsEnabled(void) const624 bool IsEnabled(void) const { return mState != kStateDisabled; } 625 626 /** 627 * Indicates whether there is a pending transmission. 628 * 629 * @retval TRUE There is a pending transmission. 630 * @retval FALSE There is no pending transmission. 631 * 632 */ IsTransmitting(void) const633 bool IsTransmitting(void) const { return mState == kStateTransmitting; } 634 635 /** 636 * Indicates whether a transmit has just finished. 637 * 638 * @retval TRUE The transmission is done. 639 * @retval FALSE The transmission is not done. 640 * 641 */ IsTransmitDone(void) const642 bool IsTransmitDone(void) const { return mState == kStateTransmitDone; } 643 644 /** 645 * Returns the timeout timepoint for the pending transmission. 646 * 647 * @returns The timeout timepoint for the pending transmission. 648 * 649 */ GetTxRadioEndUs(void) const650 uint64_t GetTxRadioEndUs(void) const { return mTxRadioEndUs; } 651 652 /** 653 * Processes any pending the I/O data. 654 * 655 * @param[in] aContext The process context. 656 * 657 */ 658 void Process(const void *aContext); 659 660 #if OPENTHREAD_CONFIG_DIAG_ENABLE 661 /** 662 * Enables/disables the factory diagnostics mode. 663 * 664 * @param[in] aMode TRUE to enable diagnostics mode, FALSE otherwise. 665 * 666 */ SetDiagEnabled(bool aMode)667 void SetDiagEnabled(bool aMode) { mDiagMode = aMode; } 668 669 /** 670 * Indicates whether or not factory diagnostics mode is enabled. 671 * 672 * @returns TRUE if factory diagnostics mode is enabled, FALSE otherwise. 673 * 674 */ IsDiagEnabled(void) const675 bool IsDiagEnabled(void) const { return mDiagMode; } 676 677 /** 678 * Processes platform diagnostics commands. 679 * 680 * @param[in] aString A null-terminated input string. 681 * @param[out] aOutput The diagnostics execution result. 682 * @param[in] aOutputMaxLen The output buffer size. 683 * 684 * @retval OT_ERROR_NONE Succeeded. 685 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 686 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 687 * 688 */ 689 otError PlatDiagProcess(const char *aString, char *aOutput, size_t aOutputMaxLen); 690 #endif 691 692 /** 693 * Returns the radio channel mask. 694 * 695 * @param[in] aPreferred TRUE to get preferred channel mask, FALSE to get supported channel mask. 696 * 697 * @returns The radio channel mask according to @aPreferred: 698 * The radio supported channel mask that the device is allowed to be on. 699 * The radio preferred channel mask that the device prefers to form on. 700 * 701 */ 702 uint32_t GetRadioChannelMask(bool aPreferred); 703 704 /** 705 * Sets MAC key and key index to RCP. 706 * 707 * @param[in] aKeyIdMode The key ID mode. 708 * @param[in] aKeyId The key index. 709 * @param[in] aPrevKey Pointer to previous MAC key. 710 * @param[in] aCurrKey Pointer to current MAC key. 711 * @param[in] aNextKey Pointer to next MAC key. 712 * 713 * @retval OT_ERROR_NONE Succeeded. 714 * @retval OT_ERROR_INVALID_ARGS One of the keys passed is invalid.. 715 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 716 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 717 * 718 */ 719 otError SetMacKey(uint8_t aKeyIdMode, 720 uint8_t aKeyId, 721 const otMacKeyMaterial *aPrevKey, 722 const otMacKeyMaterial *aCurrKey, 723 const otMacKeyMaterial *aNextKey); 724 725 /** 726 * Sets the current MAC Frame Counter value. 727 * 728 * @param[in] aMacFrameCounter The MAC Frame Counter value. 729 * @param[in] aSetIfLarger If `true`, set only if the new value is larger than the current value. 730 * If `false`, set the new value independent of the current value. 731 * 732 */ 733 otError SetMacFrameCounter(uint32_t aMacFrameCounter, bool aSetIfLarger); 734 735 /** 736 * Sets the radio region code. 737 * 738 * @param[in] aRegionCode The radio region code. 739 * 740 * @retval OT_ERROR_NONE Successfully set region code. 741 * @retval OT_ERROR_FAILED Other platform specific errors. 742 * 743 */ 744 otError SetRadioRegion(uint16_t aRegionCode); 745 746 /** 747 * Gets the radio region code. 748 * 749 * @param[out] aRegionCode The radio region code. 750 * 751 * @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr. 752 * @retval OT_ERROR_NONE Successfully got region code. 753 * @retval OT_ERROR_FAILED Other platform specific errors. 754 * 755 */ 756 otError GetRadioRegion(uint16_t *aRegionCode); 757 758 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 759 /** 760 * Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator. 761 * 762 * After Enhanced-ACK Based Probing is configured by a specific Probing Initiator, the Enhanced-ACK sent to that 763 * node should include Vendor-Specific IE containing Link Metrics data. This method informs the radio to start/stop 764 * to collect Link Metrics data and include Vendor-Specific IE that containing the data in Enhanced-ACK sent to that 765 * Probing Initiator. 766 * 767 * @param[in] aLinkMetrics This parameter specifies what metrics to query. Per spec 4.11.3.4.4.6, at most 2 768 * metrics can be specified. The probing would be disabled if @p aLinkMetrics is 769 * bitwise 0. 770 * @param[in] aShortAddress The short address of the Probing Initiator. 771 * @param[in] aExtAddress The extended source address of the Probing Initiator. @p aExtAddress MUST NOT be 772 * nullptr. 773 * 774 * @retval OT_ERROR_NONE Successfully configured the Enhanced-ACK Based Probing. 775 * @retval OT_ERROR_INVALID_ARGS @p aExtAddress is nullptr. 776 * @retval OT_ERROR_NOT_FOUND The Initiator indicated by @p aShortAddress is not found when trying to clear. 777 * @retval OT_ERROR_NO_BUFS No more Initiator can be supported. 778 */ 779 otError ConfigureEnhAckProbing(otLinkMetrics aLinkMetrics, 780 const otShortAddress &aShortAddress, 781 const otExtAddress &aExtAddress); 782 #endif 783 784 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 785 /** 786 * Get the current accuracy, in units of ± ppm, of the clock used for scheduling CSL operations. 787 * 788 * @note Platforms may optimize this value based on operational conditions (i.e.: temperature). 789 * 790 * @retval The current CSL rx/tx scheduling drift, in units of ± ppm. 791 * 792 */ 793 uint8_t GetCslAccuracy(void); 794 #endif 795 796 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 797 /** 798 * Get the current uncertainty, in units of 10 us, of the clock used for scheduling CSL operations. 799 * 800 * @retval The current CSL Clock Uncertainty in units of 10 us. 801 * 802 */ 803 uint8_t GetCslUncertainty(void); 804 #endif 805 806 /** 807 * Checks whether there is pending frame in the buffer. 808 * 809 * @returns Whether there is pending frame in the buffer. 810 * 811 */ HasPendingFrame(void) const812 bool HasPendingFrame(void) const { return mSpinelDriver->HasPendingFrame(); } 813 814 /** 815 * Returns the next timepoint to recalculate RCP time offset. 816 * 817 * @returns The timepoint to start the recalculation of RCP time offset. 818 * 819 */ GetNextRadioTimeRecalcStart(void) const820 uint64_t GetNextRadioTimeRecalcStart(void) const { return mRadioTimeRecalcStart; } 821 822 /** 823 * Gets the current estimated time on RCP. 824 * 825 * @returns The current estimated RCP time in microseconds. 826 * 827 */ 828 uint64_t GetNow(void); 829 830 /** 831 * Returns the bus speed between the host and the radio. 832 * 833 * @returns bus speed in bits/second. 834 * 835 */ 836 uint32_t GetBusSpeed(void) const; 837 838 /** 839 * Returns the co-processor sw version string. 840 * 841 * @returns A pointer to the co-processor version string. 842 * 843 */ GetVersion(void) const844 const char *GetVersion(void) const { return mSpinelDriver->GetVersion(); } 845 846 /** 847 * Sets the max transmit power. 848 * 849 * @param[in] aChannel The radio channel. 850 * @param[in] aMaxPower The max transmit power in dBm. 851 * 852 * @retval OT_ERROR_NONE Successfully set the max transmit power. 853 * @retval OT_ERROR_INVALID_ARGS Channel is not in valid range. 854 * 855 */ 856 otError SetChannelMaxTransmitPower(uint8_t aChannel, int8_t aMaxPower); 857 858 /** 859 * Tries to retrieve a spinel property from OpenThread transceiver. 860 * 861 * @param[in] aKey Spinel property key. 862 * @param[in] aFormat Spinel formatter to unpack property value. 863 * @param[out] ... Variable arguments list. 864 * 865 * @retval OT_ERROR_NONE Successfully got the property. 866 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 867 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 868 * 869 */ 870 otError Get(spinel_prop_key_t aKey, const char *aFormat, ...); 871 872 /** 873 * Tries to retrieve a spinel property from OpenThread transceiver with parameter appended. 874 * 875 * @param[in] aKey Spinel property key. 876 * @param[in] aParam Parameter appended to spinel command. 877 * @param[in] aParamSize Size of parameter appended to spinel command 878 * @param[in] aFormat Spinel formatter to unpack property value. 879 * @param[out] ... Variable arguments list. 880 * 881 * @retval OT_ERROR_NONE Successfully got the property. 882 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 883 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 884 * 885 */ 886 otError GetWithParam(spinel_prop_key_t aKey, 887 const uint8_t *aParam, 888 spinel_size_t aParamSize, 889 const char *aFormat, 890 ...); 891 892 /** 893 * Tries to update a spinel property of OpenThread transceiver. 894 * 895 * @param[in] aKey Spinel property key. 896 * @param[in] aFormat Spinel formatter to pack property value. 897 * @param[in] ... Variable arguments list. 898 * 899 * @retval OT_ERROR_NONE Successfully set the property. 900 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 901 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 902 * 903 */ 904 otError Set(spinel_prop_key_t aKey, const char *aFormat, ...); 905 906 /** 907 * Tries to insert a item into a spinel list property of OpenThread transceiver. 908 * 909 * @param[in] aKey Spinel property key. 910 * @param[in] aFormat Spinel formatter to pack the item. 911 * @param[in] ... Variable arguments list. 912 * 913 * @retval OT_ERROR_NONE Successfully insert item into the property. 914 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 915 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 916 * 917 */ 918 otError Insert(spinel_prop_key_t aKey, const char *aFormat, ...); 919 920 /** 921 * Tries to remove a item from a spinel list property of OpenThread transceiver. 922 * 923 * @param[in] aKey Spinel property key. 924 * @param[in] aFormat Spinel formatter to pack the item. 925 * @param[in] ... Variable arguments list. 926 * 927 * @retval OT_ERROR_NONE Successfully removed item from the property. 928 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 929 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 930 * 931 */ 932 otError Remove(spinel_prop_key_t aKey, const char *aFormat, ...); 933 934 /** 935 * Sends a reset command to the RCP. 936 * 937 * @param[in] aResetType The reset type, SPINEL_RESET_PLATFORM, SPINEL_RESET_STACK, or SPINEL_RESET_BOOTLOADER. 938 * 939 * @retval OT_ERROR_NONE Successfully sent the reset command. 940 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 941 * @retval OT_ERROR_NOT_CAPABLE Requested reset type is not supported by the co-processor. 942 * 943 */ 944 otError SendReset(uint8_t aResetType); 945 946 /** 947 * Returns the radio Spinel metrics. 948 * 949 * @returns The radio Spinel metrics. 950 * 951 */ GetRadioSpinelMetrics(void) const952 const otRadioSpinelMetrics *GetRadioSpinelMetrics(void) const { return &mRadioSpinelMetrics; } 953 954 #if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE 955 /** 956 * Add a calibrated power of the specified channel to the power calibration table. 957 * 958 * @param[in] aChannel The radio channel. 959 * @param[in] aActualPower The actual power in 0.01dBm. 960 * @param[in] aRawPowerSetting A pointer to the raw power setting byte array. 961 * @param[in] aRawPowerSettingLength The length of the @p aRawPowerSetting. 962 * 963 * @retval OT_ERROR_NONE Successfully added the calibrated power to the power calibration table. 964 * @retval OT_ERROR_NO_BUFS No available entry in the power calibration table. 965 * @retval OT_ERROR_INVALID_ARGS The @p aChannel, @p aActualPower or @p aRawPowerSetting is invalid. 966 * @retval OT_ERROR_NOT_IMPLEMENTED This feature is not implemented. 967 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 968 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 969 * 970 */ 971 otError AddCalibratedPower(uint8_t aChannel, 972 int16_t aActualPower, 973 const uint8_t *aRawPowerSetting, 974 uint16_t aRawPowerSettingLength); 975 976 /** 977 * Clear all calibrated powers from the power calibration table. 978 * 979 * @retval OT_ERROR_NONE Successfully cleared all calibrated powers from the power calibration table. 980 * @retval OT_ERROR_NOT_IMPLEMENTED This feature is not implemented. 981 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 982 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 983 * 984 */ 985 otError ClearCalibratedPowers(void); 986 987 /** 988 * Set the target power for the given channel. 989 * 990 * @param[in] aChannel The radio channel. 991 * @param[in] aTargetPower The target power in 0.01dBm. Passing `INT16_MAX` will disable this channel. 992 * 993 * @retval OT_ERROR_NONE Successfully set the target power. 994 * @retval OT_ERROR_INVALID_ARGS The @p aChannel or @p aTargetPower is invalid.. 995 * @retval OT_ERROR_NOT_IMPLEMENTED The feature is not implemented. 996 * @retval OT_ERROR_BUSY Failed due to another operation is on going. 997 * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. 998 * 999 */ 1000 otError SetChannelTargetPower(uint8_t aChannel, int16_t aTargetPower); 1001 #endif 1002 1003 /** 1004 * Convert the Spinel status code to OpenThread error code. 1005 * 1006 * @param[in] aStatus The Spinel status code. 1007 * 1008 * @retval OT_ERROR_NONE The operation has completed successfully. 1009 * @retval OT_ERROR_DROP The packet was dropped. 1010 * @retval OT_ERROR_NO_BUFS The operation has been prevented due to memory pressure. 1011 * @retval OT_ERROR_BUSY The device is currently performing a mutuallyexclusive operation. 1012 * @retval OT_ERROR_PARSE An error has occurred while parsing the command. 1013 * @retval OT_ERROR_INVALID_ARGS An argument to the given operation is invalid. 1014 * @retval OT_ERROR_NOT_IMPLEMENTED The given operation has not been implemented. 1015 * @retval OT_ERROR_INVALID_STATE The given operation is invalid for the current state of the device. 1016 * @retval OT_ERROR_NO_ACK The packet was not acknowledged. 1017 * @retval OT_ERROR_NOT_FOUND The given property is not recognized. 1018 * @retval OT_ERROR_FAILED The given operation has failed for some undefined reason. 1019 * @retval OT_ERROR_CHANNEL_ACCESS_FAILURE The packet was not sent due to a CCA failure. 1020 * @retval OT_ERROR_ALREADY The operation is already in progress or the property was already set 1021 * to the given value. 1022 */ 1023 static otError SpinelStatusToOtError(spinel_status_t aStatus); 1024 1025 #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 1026 /** 1027 * Restore the properties of Radio Co-processor (RCP). 1028 * 1029 */ 1030 void RestoreProperties(void); 1031 #endif 1032 #if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE 1033 /** 1034 * Defines a vendor "set property handler" hook to process vendor spinel properties. 1035 * 1036 * The vendor handler should return `OT_ERROR_NOT_FOUND` status if it does not support "set" operation for the 1037 * given property key. Otherwise, the vendor handler should behave like other property set handlers, i.e., it 1038 * should first decode the value from the input spinel frame and then perform the corresponding set operation. The 1039 * handler should not prepare the spinel response and therefore should not write anything to the NCP buffer. The 1040 * `otError` returned from handler (other than `OT_ERROR_NOT_FOUND`) indicates the error in either parsing of the 1041 * input or the error of the set operation. In case of a successful "set", `NcpBase` set command handler will call 1042 * the `VendorGetPropertyHandler()` for the same property key to prepare the response. 1043 * 1044 * @param[in] aPropKey The spinel property key. 1045 * 1046 * @returns OT_ERROR_NOT_FOUND if it does not support the given property key, otherwise the error in either parsing 1047 * of the input or the "set" operation. 1048 * 1049 */ 1050 otError VendorHandleValueIs(spinel_prop_key_t aPropKey); 1051 1052 /** 1053 * A callback type for restoring vendor properties. 1054 * 1055 */ 1056 typedef void (*otRadioSpinelVendorRestorePropertiesCallback)(void *context); 1057 1058 /** 1059 * Registers a callback to restore vendor properties. 1060 * 1061 * This function is used to register a callback for vendor properties recovery. When an event which needs to restore 1062 * properties occurs (such as an unexpected RCP reset), the user can restore the vendor properties via the callback. 1063 * 1064 * @param[in] aCallback The callback. 1065 * @param[in] aContext The context. 1066 * 1067 */ 1068 void SetVendorRestorePropertiesCallback(otRadioSpinelVendorRestorePropertiesCallback aCallback, void *aContext); 1069 #endif // OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE 1070 1071 private: 1072 enum 1073 { 1074 kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds. 1075 kVersionStringSize = 128, ///< Max size of version string. 1076 kCapsBufferSize = 100, ///< Max buffer size used to store `SPINEL_PROP_CAPS` value. 1077 kChannelMaskBufferSize = 32, ///< Max buffer size used to store `SPINEL_PROP_PHY_CHAN_SUPPORTED` value. 1078 }; 1079 1080 enum State 1081 { 1082 kStateDisabled, ///< Radio is disabled. 1083 kStateSleep, ///< Radio is sleep. 1084 kStateReceive, ///< Radio is in receive mode. 1085 kStateTransmitting, ///< Frame passed to radio for transmission, waiting for done event from radio. 1086 kStateTransmitDone, ///< Radio indicated frame transmission is done. 1087 }; 1088 1089 static constexpr uint32_t kUsPerMs = 1000; ///< Microseconds per millisecond. 1090 static constexpr uint32_t kMsPerSec = 1000; ///< Milliseconds per second. 1091 static constexpr uint32_t kUsPerSec = kUsPerMs * kMsPerSec; ///< Microseconds per second. 1092 static constexpr uint64_t kTxWaitUs = 1093 OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS * 1094 kUsPerSec; ///< Maximum time of waiting for `TransmitDone` event, in microseconds. 1095 1096 typedef otError (RadioSpinel::*ResponseHandler)(const uint8_t *aBuffer, uint16_t aLength); 1097 1098 SpinelDriver &GetSpinelDriver(void) const; 1099 1100 otError CheckSpinelVersion(void); 1101 otError CheckRadioCapabilities(void); 1102 otError CheckRcpApiVersion(bool aSupportsRcpApiVersion, bool aSupportsRcpMinHostApiVersion); 1103 void InitializeCaps(bool &aSupportsRcpApiVersion, bool &aSupportsRcpMinHostApiVersion); 1104 1105 /** 1106 * Triggers a state transfer of the state machine. 1107 * 1108 */ 1109 void ProcessRadioStateMachine(void); 1110 1111 /** 1112 * Processes the frame queue. 1113 * 1114 */ 1115 void ProcessFrameQueue(void); 1116 1117 spinel_tid_t GetNextTid(void); FreeTid(spinel_tid_t tid)1118 void FreeTid(spinel_tid_t tid) { mCmdTidsInUse &= ~(1 << tid); } 1119 1120 otError RequestV(uint32_t aCommand, spinel_prop_key_t aKey, const char *aFormat, va_list aArgs); 1121 otError Request(uint32_t aCommand, spinel_prop_key_t aKey, const char *aFormat, ...); 1122 otError RequestWithPropertyFormat(const char *aPropertyFormat, 1123 uint32_t aCommand, 1124 spinel_prop_key_t aKey, 1125 const char *aFormat, 1126 ...); 1127 otError RequestWithPropertyFormatV(const char *aPropertyFormat, 1128 uint32_t aCommand, 1129 spinel_prop_key_t aKey, 1130 const char *aFormat, 1131 va_list aArgs); 1132 otError RequestWithExpectedCommandV(uint32_t aExpectedCommand, 1133 uint32_t aCommand, 1134 spinel_prop_key_t aKey, 1135 const char *aFormat, 1136 va_list aArgs); 1137 otError WaitResponse(bool aHandleRcpTimeout = true); 1138 otError ParseRadioFrame(otRadioFrame &aFrame, const uint8_t *aBuffer, uint16_t aLength, spinel_ssize_t &aUnpacked); 1139 1140 /** 1141 * Returns if the property changed event is safe to be handled now. 1142 * 1143 * If a property handler will go up to core stack, it may cause reentrant issue of `Hdlc::Decode()` and 1144 * `WaitResponse()`. 1145 * 1146 * @param[in] aKey The identifier of the property. 1147 * 1148 * @returns Whether this property is safe to be handled now. 1149 * 1150 */ IsSafeToHandleNow(spinel_prop_key_t aKey) const1151 bool IsSafeToHandleNow(spinel_prop_key_t aKey) const 1152 { 1153 return !(aKey == SPINEL_PROP_STREAM_RAW || aKey == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT); 1154 } 1155 1156 void HandleNotification(const uint8_t *aFrame, uint16_t aLength, bool &aShouldSaveFrame); 1157 void HandleNotification(const uint8_t *aFrame, uint16_t aLength); 1158 void HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer, uint16_t aLength); 1159 1160 void HandleResponse(const uint8_t *aBuffer, uint16_t aLength); 1161 void HandleTransmitDone(uint32_t aCommand, spinel_prop_key_t aKey, const uint8_t *aBuffer, uint16_t aLength); 1162 void HandleWaitingResponse(uint32_t aCommand, spinel_prop_key_t aKey, const uint8_t *aBuffer, uint16_t aLength); 1163 1164 void RadioReceive(void); 1165 1166 void TransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError); 1167 1168 void CalcRcpTimeOffset(void); 1169 1170 void HandleRcpUnexpectedReset(spinel_status_t aStatus); 1171 void HandleRcpTimeout(void); 1172 void RecoverFromRcpFailure(void); 1173 1174 static void HandleReceivedFrame(const uint8_t *aFrame, 1175 uint16_t aLength, 1176 uint8_t aHeader, 1177 bool &aSave, 1178 void *aContext); 1179 void HandleReceivedFrame(const uint8_t *aFrame, uint16_t aLength, uint8_t aHeader, bool &aShouldSaveFrame); 1180 static void HandleSavedFrame(const uint8_t *aFrame, uint16_t aLength, void *aContext); 1181 void HandleSavedFrame(const uint8_t *aFrame, uint16_t aLength); 1182 UpdateParseErrorCount(otError aError)1183 void UpdateParseErrorCount(otError aError) 1184 { 1185 mRadioSpinelMetrics.mSpinelParseErrorCount += (aError == OT_ERROR_PARSE) ? 1 : 0; 1186 } 1187 1188 otError SetMacKey(uint8_t aKeyIdMode, 1189 uint8_t aKeyId, 1190 const otMacKey &aPrevKey, 1191 const otMacKey &aCurrKey, 1192 const otMacKey &NextKey); 1193 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 1194 static otError ReadMacKey(const otMacKeyMaterial &aKeyMaterial, otMacKey &aKey); 1195 #endif 1196 1197 otInstance *mInstance; 1198 1199 RadioSpinelCallbacks mCallbacks; ///< Callbacks for notifications of higher layer. 1200 1201 uint16_t mCmdTidsInUse; ///< Used transaction ids. 1202 spinel_tid_t mCmdNextTid; ///< Next available transaction id. 1203 spinel_tid_t mTxRadioTid; ///< The transaction id used to send a radio frame. 1204 spinel_tid_t mWaitingTid; ///< The transaction id of current transaction. 1205 spinel_prop_key_t mWaitingKey; ///< The property key of current transaction. 1206 const char *mPropertyFormat; ///< The spinel property format of current transaction. 1207 va_list mPropertyArgs; ///< The arguments pack or unpack spinel property of current transaction. 1208 uint32_t mExpectedCommand; ///< Expected response command of current transaction. 1209 otError mError; ///< The result of current transaction. 1210 uint8_t mRxPsdu[OT_RADIO_FRAME_MAX_SIZE]; 1211 uint8_t mTxPsdu[OT_RADIO_FRAME_MAX_SIZE]; 1212 uint8_t mAckPsdu[OT_RADIO_FRAME_MAX_SIZE]; 1213 otRadioFrame mRxRadioFrame; 1214 otRadioFrame mTxRadioFrame; 1215 otRadioFrame mAckRadioFrame; 1216 otRadioFrame *mTransmitFrame; ///< Points to the frame to send 1217 1218 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1219 otRadioIeInfo mTxIeInfo; 1220 #endif 1221 1222 otExtAddress mExtendedAddress; 1223 uint16_t mShortAddress; 1224 uint16_t mPanId; 1225 uint8_t mChannel; 1226 int8_t mRxSensitivity; 1227 otError mTxError; 1228 static otExtAddress sIeeeEui64; 1229 static otRadioCaps sRadioCaps; 1230 1231 State mState; 1232 bool mIsPromiscuous : 1; ///< Promiscuous mode. 1233 bool mRxOnWhenIdle : 1; ///< RxOnWhenIdle mode. 1234 bool mIsTimeSynced : 1; ///< Host has calculated the time difference between host and RCP. 1235 1236 static bool sSupportsLogStream; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format. 1237 static bool sSupportsResetToBootloader; ///< RCP supports resetting into bootloader mode. 1238 static bool sSupportsLogCrashDump; ///< RCP supports logging a crash dump. 1239 1240 #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 1241 1242 enum 1243 { 1244 kRcpFailureNone, 1245 kRcpFailureTimeout, 1246 kRcpFailureUnexpectedReset, 1247 }; 1248 1249 bool mResetRadioOnStartup : 1; ///< Whether should send reset command when init. 1250 int16_t mRcpFailureCount; ///< Count of consecutive RCP failures. 1251 uint8_t mRcpFailure : 2; ///< RCP failure reason, should recover and retry operation. 1252 1253 // Properties set by core. 1254 uint8_t mKeyIdMode; 1255 uint8_t mKeyId; 1256 otMacKey mPrevKey; 1257 otMacKey mCurrKey; 1258 otMacKey mNextKey; 1259 uint16_t mSrcMatchShortEntries[OPENTHREAD_CONFIG_MLE_MAX_CHILDREN]; 1260 int16_t mSrcMatchShortEntryCount; 1261 otExtAddress mSrcMatchExtEntries[OPENTHREAD_CONFIG_MLE_MAX_CHILDREN]; 1262 int16_t mSrcMatchExtEntryCount; 1263 uint8_t mScanChannel; 1264 uint16_t mScanDuration; 1265 int8_t mCcaEnergyDetectThreshold; 1266 int8_t mTransmitPower; 1267 int8_t mFemLnaGain; 1268 uint32_t mMacFrameCounter; 1269 bool mCoexEnabled : 1; 1270 bool mSrcMatchEnabled : 1; 1271 1272 bool mMacKeySet : 1; ///< Whether MAC key has been set. 1273 bool mCcaEnergyDetectThresholdSet : 1; ///< Whether CCA energy detect threshold has been set. 1274 bool mTransmitPowerSet : 1; ///< Whether transmit power has been set. 1275 bool mCoexEnabledSet : 1; ///< Whether coex enabled has been set. 1276 bool mFemLnaGainSet : 1; ///< Whether FEM LNA gain has been set. 1277 bool mEnergyScanning : 1; ///< If fails while scanning, restarts scanning. 1278 bool mMacFrameCounterSet : 1; ///< Whether the MAC frame counter has been set. 1279 bool mSrcMatchSet : 1; ///< Whether the source match feature has been set. 1280 1281 #endif // OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 1282 1283 #if OPENTHREAD_CONFIG_DIAG_ENABLE 1284 bool mDiagMode; 1285 char *mDiagOutput; 1286 size_t mDiagOutputMaxLen; 1287 #endif 1288 1289 uint64_t mTxRadioEndUs; 1290 uint64_t mRadioTimeRecalcStart; ///< When to recalculate RCP time offset. 1291 uint64_t mRadioTimeOffset; ///< Time difference with estimated RCP time minus host time. 1292 1293 MaxPowerTable mMaxPowerTable; 1294 1295 otRadioSpinelMetrics mRadioSpinelMetrics; 1296 1297 #if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE 1298 otRadioSpinelVendorRestorePropertiesCallback mVendorRestorePropertiesCallback; 1299 void *mVendorRestorePropertiesContext; 1300 #endif 1301 1302 SpinelDriver *mSpinelDriver; 1303 }; 1304 1305 } // namespace Spinel 1306 } // namespace ot 1307 1308 #endif // RADIO_SPINEL_HPP_ 1309