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.
- Wake-up frames are processed.
- Upon reception of a wake-up frame, WUL is stopped.
  • Loading branch information
edmont committed Oct 1, 2024
1 parent 3a28b7b commit d2fa779
Show file tree
Hide file tree
Showing 18 changed files with 733 additions and 28 deletions.
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (451)
#define OPENTHREAD_API_VERSION (452)

/**
* @addtogroup api-instance
Expand Down
62 changes: 62 additions & 0 deletions include/openthread/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,68 @@ 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 not enable listening for wake-up frames due to bad configuration.
*/
otError otLinkWedListenSetEnabled(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
69 changes: 64 additions & 5 deletions src/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ Done
- [vendor](#vendor-name)
- [verhoeff](#verhoeff-calculate)
- [version](#version)
- [wakeup](#wakeup)
- [wakeupchannel](#wakeupchannel)

## OpenThread Command Details
Expand Down Expand Up @@ -4393,15 +4394,73 @@ Factory Diagnostics module is enabled only when building OpenThread with `OPENTH
[diag]: ../../src/core/diags/README.md
### wakeupchannel
### wakeup
Get the wake-up channel.
Get the Wake-up End Device listen configuration.
Requires `OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE` or `OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE`.
`OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is required.
```bash
> wakeup
channel: 12
interval: 1000000us
duration: 8000us
Done
```
### wakeup enable
Enable the WED listening feature.
`OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is required.
```bash
> wakeup enable
Done
```
### wakeup disable
Disable the WED listening feature.
`OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is required.
```bash
> wakeup disable
Done
```
### wakeup state
Shows the WED listening state, among `disabled` and `enabled`.
`OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is required.
```bash
> wakeup state
enabled
Done
```
### wakeup interval \<interval\>
Set the WED listen interval in microseconds. Disable WED listening by setting this parameter to `0`.
`OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is required.
```bash
> wakeup interval 1000000
Done
```
### wakeup duration \<duration\>
Set the WED listen duration in microseconds.
`OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE` is required.
```bash
> wakeupchannel
12
> wakeup duration 8000
Done
```
Expand Down
115 changes: 115 additions & 0 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8219,6 +8219,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: %luus", ToUlong(otLinkGetWedListenDuration(GetInstancePtr())));
}
/**
* @cli wakeup (enable,disable)
* @code
* wakeup enable
* Done
* @endcode
* @code
* wakeup disable
* Done
* @endcode
* @par api_copy
* #otLinkWedListenSetEnabled
*/
else if (ParseEnableOrDisable(aArgs[0], enable) == OT_ERROR_NONE)
{
error = otLinkWedListenSetEnabled(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
*/
else 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 Expand Up @@ -8530,6 +8639,12 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
#endif
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
CmdEntry("version"),
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_PERIPHERAL_ENABLE
CmdEntry("wakeup"),
CmdEntry("wakeupchannel"),
#endif
#endif
};

#undef CmdEntry
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 otLinkWedListenSetEnabled(otInstance *aInstance, bool aEnable)
{
Error error = kErrorInvalidState;

VerifyOrExit(otLinkGetWedListenInterval(aInstance) > otLinkGetWedListenDuration(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
Loading

0 comments on commit d2fa779

Please sign in to comment.