Skip to content

Commit

Permalink
[mac] enable wake-up frame periodic sniffing
Browse files Browse the repository at this point in the history
When `OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is enabled:

- APIs are available to configure and enable wake-up frames sniffing.
- `SubMac::HandleWedTimer` periodically schedules receive slots on
  wake-up channel.
- Conflicts between WUL and CSL slots are handled.
- Wake-up frames are processed.
- Upon reception of a wake-up frame, WUL is stopped.
  • Loading branch information
edmont committed Sep 24, 2024
1 parent a43abea commit 862335b
Show file tree
Hide file tree
Showing 21 changed files with 735 additions and 33 deletions.
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (447)
#define OPENTHREAD_API_VERSION (448)

/**
* @addtogroup api-instance
Expand Down
67 changes: 67 additions & 0 deletions include/openthread/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,73 @@ uint8_t otLinkGetWakeupChannel(otInstance *aInstance);
*/
otError otLinkSetWakeupChannel(otInstance *aInstance, uint8_t aChannel);

/**
* Enables or disables listening for wake-up frames.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnable true to enable listening for wake-up frames, or false otherwise.
*
* @retval OT_ERROR_NONE Successfully enabled / disabled the listening for wake-up frames.
* @retval OT_ERROR_INVALID_STATE Could enable listening for wake-up frames due to bad configuration.
*
*/
otError otLinkWedListenEnable(otInstance *aInstance, bool aEnable);

/**
* Returns whether listening for wake-up frames is enabled.
*
* @retval TRUE If listening for wake-up frames is enabled.
* @retval FALSE If listening for wake-up frames is not enabled.
*/
bool otLinkIsWedListenEnabled(otInstance *aInstance);

/**
* Gets the WED listen interval in microseconds.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns The WED listen interval in microseconds.
*
*/
uint32_t otLinkGetWedListenInterval(otInstance *aInstance);

/**
* Sets the WED listen interval in microseconds.
*
* The WED listen interval must be a multiple of `OT_LINK_CSL_PERIOD_TEN_SYMBOLS_UNIT_IN_USEC`, otherwise
* `OT_ERROR_INVALID_ARGS` is returned.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aInterval The WED listen interval in microseconds.
*
* @retval OT_ERROR_NONE Successfully set the WED listen interval.
* @retval OT_ERROR_INVALID_ARGS Invalid WED listen interval.
*
*/
otError otLinkSetWedListenInterval(otInstance *aInstance, uint32_t aInterval);

/**
* Gets the WED listen duration.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns The WED listen duration in microseconds.
*
*/
uint16_t otLinkGetWedListenDuration(otInstance *aInstance);

/**
* Sets the WED listen duration in microseconds.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aDuration The WED listen duration in microseconds.
*
* @retval OT_ERROR_NONE Successfully set the WED listen duration.
* @retval OT_ERROR_INVALID_ARGS Invalid WED listen duration.
*
*/
otError otLinkSetWedListenDuration(otInstance *aInstance, uint16_t aDuration);

/**
* @}
*
Expand Down
7 changes: 6 additions & 1 deletion include/openthread/platform/radio.h
Original file line number Diff line number Diff line change
Expand Up @@ -877,11 +877,16 @@ otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel);
* still actively receiving a frame. In the latter case
* the radio SHALL be kept in reception mode until frame
* reception has either succeeded or failed.
* @param[in] aSlotId The receive window slot ID.
*
* @retval OT_ERROR_NONE Successfully scheduled receive window.
* @retval OT_ERROR_FAILED The receive window could not be scheduled.
*/
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration);
otError otPlatRadioReceiveAt(otInstance *aInstance,
uint8_t aChannel,
uint32_t aStart,
uint32_t aDuration,
uint8_t aSlotId);

/**
* The radio driver calls this method to notify OpenThread of a received frame.
Expand Down
3 changes: 3 additions & 0 deletions src/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4395,3 +4395,6 @@ Requires `OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE` or `OPENTHREAD_CONFIG_WAK
> wakeupchannel 12
Done
```
### wakeup
<!-- TODO -->
109 changes: 109 additions & 0 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8227,6 +8227,115 @@ template <> otError Interpreter::Process<Cmd("wakeupchannel")>(Arg aArgs[])
{
return ProcessGetSet(aArgs, otLinkGetWakeupChannel, otLinkSetWakeupChannel);
}

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
template <> otError Interpreter::Process<Cmd("wakeup")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
bool enable;

/**
* @cli wakeup
* @code
* wakeup
* channel: 12
* interval: 1000000us
* duration: 8000us
* Done
* @endcode
* @par
* Gets the wake-up listening configuration.
* @sa otLinkGetWakeupChannel
* @sa otLinkGetWedListenInterval
* @sa otLinkGetWedListenDuration
*/
if (aArgs[0].IsEmpty())
{
OutputLine("channel: %u", otLinkGetWakeupChannel(GetInstancePtr()));
OutputLine("interval: %luus", ToUlong(otLinkGetWedListenInterval(GetInstancePtr())));
OutputLine("duration: %lus", ToUlong(otLinkGetWedListenDuration(GetInstancePtr())));
}
/**
* @cli wakeup (enable,disable)
* @code
* wakeup enable
* Done
* @endcode
* @code
* wakeup disable
* Done
* @endcode
* @par api_copy
* #otLinkWedListenEnable
*/
else if (ParseEnableOrDisable(aArgs[0], enable) == OT_ERROR_NONE)
{
error = otLinkWedListenEnable(GetInstancePtr(), enable);
}
/**
* @cli wakeup interval
* @code
* wakeup interval 1000000
* Done
* @endcode
* @cparam wakeup interval @ca{interval}
* @par api_copy
* #otLinkSetWedListenInterval
*/
else if (aArgs[0] == "interval")
{
error = ProcessSet(aArgs + 1, otLinkSetWedListenInterval);
}
/**
* @cli wakeup duration
* @code
* wakeup duration 8000
* Done
* @endcode
* @cparam wakeup duration @ca{duration}
* @par api_copy
* #otLinkSetWedListenDuration
*/
else if (aArgs[0] == "duration")
{
error = ProcessSet(aArgs + 1, otLinkSetWedListenDuration);
}
/**
* @cli wakeup state
* @code
* wakeup state
* disabled
* Done
* @endcode
* @code
* wakeup state
* enabled
* Done
* @endcode
* @par
* Prints current wake-up listening link state.
* #otLinkIsWedListenEnabled
*/
if (aArgs[0] == "state")
{
if (otLinkIsWedListenEnabled(GetInstancePtr()))
{
OutputLine("enabled");
}
else
{
OutputLine("disabled");
}
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}

exit:
return error;
}
#endif // OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE

#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
Expand Down
1 change: 1 addition & 0 deletions src/core/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ openthread_core_files = [
"mac/sub_mac.hpp",
"mac/sub_mac_callbacks.cpp",
"mac/sub_mac_csl_receiver.cpp",
"mac/sub_mac_wed.cpp",
"meshcop/announce_begin_client.cpp",
"meshcop/announce_begin_client.hpp",
"meshcop/border_agent.cpp",
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ set(COMMON_SOURCES
mac/sub_mac.cpp
mac/sub_mac_callbacks.cpp
mac/sub_mac_csl_receiver.cpp
mac/sub_mac_wed.cpp
meshcop/announce_begin_client.cpp
meshcop/border_agent.cpp
meshcop/commissioner.cpp
Expand Down Expand Up @@ -295,6 +296,7 @@ set(RADIO_COMMON_SOURCES
mac/sub_mac.cpp
mac/sub_mac_callbacks.cpp
mac/sub_mac_csl_receiver.cpp
mac/sub_mac_wed.cpp
radio/radio.cpp
radio/radio_callbacks.cpp
radio/radio_platform.cpp
Expand Down
61 changes: 61 additions & 0 deletions src/core/api/link_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,3 +504,64 @@ otError otLinkGetRegion(otInstance *aInstance, uint16_t *aRegionCode)

return error;
}

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
otError otLinkWedListenEnable(otInstance *aInstance, bool aEnable)
{
Error error = kErrorInvalidState;

VerifyOrExit(otLinkGetWedListenInterval(aInstance) > otLinkGetWedListenInterval(aInstance));

error = AsCoreType(aInstance).Get<Mac::Mac>().WedListenEnable(aEnable);

exit:
return error;
}

bool otLinkIsWedListenEnabled(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Mac::Mac>().IsWedListenEnabled();
}

uint32_t otLinkGetWedListenInterval(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Mac::Mac>().GetWedListenInterval();
}

otError otLinkSetWedListenInterval(otInstance *aInstance, uint32_t aInterval)
{
Error error = kErrorNone;
uint16_t intervalInTenSymbolsUnit;

if (aInterval == 0)
{
intervalInTenSymbolsUnit = 0;
}
else
{
VerifyOrExit((aInterval % kUsPerTenSymbols) == 0, error = kErrorInvalidArgs);
intervalInTenSymbolsUnit = ClampToUint16(aInterval / kUsPerTenSymbols);
}

AsCoreType(aInstance).Get<Mac::Mac>().SetWedListenInterval(intervalInTenSymbolsUnit);

exit:
return error;
}

uint16_t otLinkGetWedListenDuration(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Mac::Mac>().GetWedListenDuration();
}

otError otLinkSetWedListenDuration(otInstance *aInstance, uint16_t aDuration)
{
Error error = kErrorNone;

VerifyOrExit(aDuration >= kMinWedListenDuration, error = kErrorInvalidArgs);
AsCoreType(aInstance).Get<Mac::Mac>().SetWedListenDuration(aDuration);

exit:
return error;
}
#endif // OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
20 changes: 20 additions & 0 deletions src/core/config/mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,26 @@
#define OPENTHREAD_CONFIG_MAC_DATA_POLL_TIMEOUT 100
#endif

/**
* @def OPENTHREAD_CONFIG_WED_LISTEN_INTERVAL
*
* The default WED listen interval in units of 10 symbols.
*
*/
#ifndef OPENTHREAD_CONFIG_WED_LISTEN_INTERVAL
#define OPENTHREAD_CONFIG_WED_LISTEN_INTERVAL 6250
#endif

/**
* @def OPENTHREAD_CONFIG_WED_LISTEN_DURATION
*
* The default WED listen duration in us.
*
*/
#ifndef OPENTHREAD_CONFIG_WED_LISTEN_DURATION
#define OPENTHREAD_CONFIG_WED_LISTEN_DURATION 8000
#endif

/**
* @}
*
Expand Down
Loading

0 comments on commit 862335b

Please sign in to comment.