[radio] send radio command to the region (#5999)

Some radio region has further limit over max power table. We need to
send the region code the radio driver as well.
This commit is contained in:
Jiacheng Guo
2020-12-23 14:51:03 +08:00
committed by GitHub
parent 677e2f01ec
commit b306cb0bbe
18 changed files with 295 additions and 6 deletions
@@ -199,4 +199,10 @@ void nrf5SdSocFlashProcess(uint32_t aEvtId);
int8_t nrf5GetChannelMaxTransmitPower(uint8_t aChannel);
/**
* Callback function for region changed.
*
*/
void nrf5HandleRegionChanged(uint16_t aRegionCode);
#endif // PLATFORM_NRF5_H_
+30 -3
View File
@@ -108,9 +108,10 @@ static otInstance * sInstance = NULL;
static otRadioFrame sAckFrame;
static bool sAckedWithFramePending;
static int8_t sMaxTxPowerTable[OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1];
static int8_t sDefaultTxPower;
static int8_t sLnaGain = 0;
static int8_t sMaxTxPowerTable[OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1];
static int8_t sDefaultTxPower;
static int8_t sLnaGain = 0;
static uint16_t sRegionCode = 0;
static uint32_t sEnergyDetectionTime;
static uint8_t sEnergyDetectionChannel;
@@ -1362,3 +1363,29 @@ int8_t nrf5GetChannelMaxTransmitPower(uint8_t aChannel)
return power;
}
otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
sRegionCode = aRegionCode;
nrf5HandleRegionChanged(aRegionCode);
return OT_ERROR_NONE;
}
otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
otError error = OT_ERROR_NONE;
VerifyOrExit(aRegionCode != NULL, error = OT_ERROR_INVALID_ARGS);
*aRegionCode = sRegionCode;
exit:
return error;
}
OT_TOOL_WEAK void nrf5HandleRegionChanged(uint16_t aRegionCode)
{
OT_UNUSED_VARIABLE(aRegionCode);
}
+21
View File
@@ -117,6 +117,7 @@ static bool sTxWait = false;
static int8_t sTxPower = 0;
static int8_t sCcaEdThresh = -74;
static int8_t sLnaGain = 0;
static uint16_t sRegionCode = 0;
enum
{
@@ -1236,3 +1237,23 @@ otError otPlatRadioConfigureEnhAckProbing(otInstance * aInstance,
return otLinkMetricsConfigureEnhAckProbing(aShortAddress, aExtAddress, aLinkMetrics);
}
#endif
otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
sRegionCode = aRegionCode;
return OT_ERROR_NONE;
}
otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
otError error = OT_ERROR_NONE;
VerifyOrExit(aRegionCode != NULL, error = OT_ERROR_INVALID_ARGS);
*aRegionCode = sRegionCode;
exit:
return error;
}
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (57)
#define OPENTHREAD_API_VERSION (58)
/**
* @addtogroup api-instance
+31
View File
@@ -984,6 +984,37 @@ void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTi
*/
otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower);
/**
* Set the region code.
*
* The radio region format is the 2-bytes ascii representation of the
* ISO 3166 alpha-2 code.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aRegionCode The radio region.
*
* @retval OT_ERROR_FAILED Other platform specific errors.
* @retval OT_ERROR_NONE Successfully set region code.
*
*/
otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode);
/**
* Get the region code.
*
* The radio region format is the 2-bytes ascii representation of the
* ISO 3166 alpha-2 code.
* @param[in] aInstance The OpenThread instance structure.
* @param[out] aRegionCode The radio region.
*
* @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr.
* @retval OT_ERROR_FAILED Other platform specific errors.
* @retval OT_ERROR_NONE Successfully got region code.
*
*/
otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode);
/**
* Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator.
*
+4 -1
View File
@@ -83,7 +83,7 @@ check()
# Cover setting a valid network interface name.
readonly VALID_NETIF_NAME="wan$(date +%H%M%S)"
RADIO_URL="spinel+hdlc+uart://${CORE_PTY}?max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
RADIO_URL="spinel+hdlc+uart://${CORE_PTY}?region=US&max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
if [[ ${DAEMON} == 1 ]]; then
sudo "$PWD/output/posix/bin/ot-daemon" -I "${VALID_NETIF_NAME}" "${RADIO_URL}" &
@@ -113,6 +113,9 @@ spawn ${OT_CLI_CMD}
send "radiourl\r\n"
expect "${RADIO_URL}"
expect "Done"
send "region\r\n"
expect "US"
expect "Done"
send "panid 0xface\r\n"
expect "Done"
send "ifconfig up\r\n"
+13
View File
@@ -84,6 +84,7 @@ Done
- [promiscuous](#promiscuous)
- [pskc](#pskc--p-keypassphrase)
- [rcp](#rcp)
- [region](#region)
- [releaserouterid](#releaserouterid-routerid)
- [reset](#reset)
- [rloc16](#rloc16)
@@ -1709,6 +1710,18 @@ Done
RCP-related commands.
### region
Set the radio region, this can affect the transmit power limit.
```bash
> region US
Done
> region
US
Done
```
### rcp version
Print RCP version string.
+24
View File
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openthread/diag.h>
#include <openthread/icmp6.h>
@@ -3316,6 +3317,29 @@ exit:
return error;
}
otError Interpreter::ProcessRegion(uint8_t aArgsLength, char *aArgs[])
{
otError error = OT_ERROR_NONE;
uint16_t regionCode;
if (aArgsLength == 0)
{
SuccessOrExit(error = otPlatRadioGetRegion(mInstance, &regionCode));
OutputLine("%c%c", regionCode >> 8, regionCode & 0xff);
}
else
{
VerifyOrExit(strlen(aArgs[0]) == 2, error = OT_ERROR_INVALID_ARGS);
regionCode =
static_cast<uint16_t>(static_cast<uint16_t>(aArgs[0][0]) << 8) + static_cast<uint16_t>(aArgs[0][1]);
error = otPlatRadioSetRegion(mInstance, regionCode);
}
exit:
return error;
}
#if OPENTHREAD_FTD
otError Interpreter::ProcessReleaseRouterId(uint8_t aArgsLength, char *aArgs[])
{
+2
View File
@@ -467,6 +467,7 @@ private:
otError ProcessPskc(uint8_t aArgsLength, char *aArgs[]);
#endif
otError ProcessRcp(uint8_t aArgsLength, char *aArgs[]);
otError ProcessRegion(uint8_t aArgsLength, char *aArgs[]);
#if OPENTHREAD_FTD
otError ProcessReleaseRouterId(uint8_t aArgsLength, char *aArgs[]);
#endif
@@ -724,6 +725,7 @@ private:
{"pskc", &Interpreter::ProcessPskc},
#endif
{"rcp", &Interpreter::ProcessRcp},
{"region", &Interpreter::ProcessRegion},
#if OPENTHREAD_FTD
{"releaserouterid", &Interpreter::ProcessReleaseRouterId},
#endif
+16
View File
@@ -266,3 +266,19 @@ OT_TOOL_WEAK otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aRegionCode);
return OT_ERROR_NOT_IMPLEMENTED;
}
OT_TOOL_WEAK otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aRegionCode);
return OT_ERROR_NOT_IMPLEMENTED;
}
+23
View File
@@ -650,6 +650,29 @@ public:
*/
otError SetMacFrameCounter(uint32_t aMacFrameCounter);
/**
* This method sets the radio region code.
*
* @param[in] aRegionCode The radio region code.
*
* @retval OT_ERROR_NONE Successfully set region code.
* @retval OT_ERROR_FAILED Other platform specific errors.
*
*/
otError SetRadioRegion(uint16_t aRegionCode);
/**
* This method gets the radio region code.
*
* @param[out] aRegionCode The radio region code.
*
* @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr.
* @retval OT_ERROR_NONE Successfully got region code.
* @retval OT_ERROR_FAILED Other platform specific errors.
*
*/
otError GetRadioRegion(uint16_t *aRegionCode);
/**
* This method checks whether the spinel interface is radio-only.
*
+18
View File
@@ -2329,5 +2329,23 @@ exit:
return error;
}
template <typename InterfaceType, typename ProcessContextType>
otError RadioSpinel<InterfaceType, ProcessContextType>::SetRadioRegion(uint16_t aRegionCode)
{
return Set(SPINEL_PROP_PHY_REGION_CODE, SPINEL_DATATYPE_UINT16_S, aRegionCode);
}
template <typename InterfaceType, typename ProcessContextType>
otError RadioSpinel<InterfaceType, ProcessContextType>::GetRadioRegion(uint16_t *aRegionCode)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(aRegionCode != nullptr, error = OT_ERROR_INVALID_ARGS);
error = Get(SPINEL_PROP_PHY_REGION_CODE, SPINEL_DATATYPE_UINT16_S, aRegionCode);
exit:
return error;
}
} // namespace Spinel
} // namespace ot
+8 -1
View File
@@ -377,7 +377,7 @@
* Please see section "Spinel definition compatibility guideline" for more details.
*
*/
#define SPINEL_RCP_API_VERSION 2
#define SPINEL_RCP_API_VERSION 3
/**
* @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION
@@ -1582,6 +1582,13 @@ enum
* First byte is the channel then the max transmit power, write-only.
*/
SPINEL_PROP_PHY_CHAN_MAX_POWER = SPINEL_PROP_PHY__BEGIN + 11,
/// Region code
/** Format: `S`
*
* The ascii representation of the ISO 3166 alpha-2 code.
*
*/
SPINEL_PROP_PHY_REGION_CODE = SPINEL_PROP_PHY__BEGIN + 12,
SPINEL_PROP_PHY__END = 0x30,
+30
View File
@@ -2262,6 +2262,36 @@ exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_REGION_CODE>(void)
{
uint16_t regionCode;
otError error = OT_ERROR_NONE;
error = otPlatRadioGetRegion(mInstance, &regionCode);
if (error == OT_ERROR_NONE)
{
error = mEncoder.WriteUint16(regionCode);
}
else
{
error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
}
return error;
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_REGION_CODE>(void)
{
uint16_t regionCode;
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mDecoder.ReadUint16(regionCode));
error = otPlatRadioSetRegion(mInstance, regionCode);
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_TEST_ASSERT>(void)
{
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+2
View File
@@ -75,6 +75,7 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
#endif
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_PHY_CHAN_PREFERRED),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_PHY_FEM_LNA_GAIN),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_PHY_REGION_CODE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_STATE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_MASK),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_PERIOD),
@@ -376,6 +377,7 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
#endif
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_PHY_FEM_LNA_GAIN),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_PHY_CHAN_MAX_POWER),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_PHY_REGION_CODE),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_STATE),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_MASK),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_PERIOD),
+25
View File
@@ -33,6 +33,8 @@
#include "platform-posix.h"
#include <string.h>
#include "lib/spinel/radio_spinel.hpp"
#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_UART
@@ -94,6 +96,7 @@ void platformRadioInit(otUrl *aRadioUrl)
bool resetRadio = (radioUrl.GetValue("no-reset") == nullptr);
bool restoreDataset = (radioUrl.GetValue("ncp-dataset") != nullptr);
const char * parameterValue;
const char * region;
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
const char *maxPowerTable;
#endif
@@ -119,6 +122,16 @@ void platformRadioInit(otUrl *aRadioUrl)
SuccessOrDie(sRadioSpinel.SetCcaEnergyDetectThreshold(static_cast<int8_t>(ccaThreshold)));
}
region = radioUrl.GetValue("region");
if (region != nullptr)
{
uint16_t regionCode;
VerifyOrDie(strnlen(region, 3) == 2, OT_EXIT_INVALID_ARGUMENTS);
regionCode = static_cast<uint16_t>(static_cast<uint16_t>(region[0]) << 8) + static_cast<uint16_t>(region[1]);
SuccessOrDie(sRadioSpinel.SetRadioRegion(regionCode));
}
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
maxPowerTable = radioUrl.GetValue("max-power-table");
if (maxPowerTable != nullptr)
@@ -546,3 +559,15 @@ otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aCh
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.SetChannelMaxTransmitPower(aChannel, aMaxPower);
}
otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.SetRadioRegion(aRegionCode);
}
otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
{
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.GetRadioRegion(aRegionCode);
}
+1
View File
@@ -88,6 +88,7 @@ const char *otSysGetRadioUrlHelpString(void)
#endif
return "RadioURL:\n" OT_RADIO_URL_HELP_BUS OT_RADIO_URL_HELP_MAX_POWER_TABLE
" region[=region-code] Set the radio's region code.\n"
" cca-threshold[=dbm] Set the radio's CCA ED threshold in dBm measured at antenna connector.\n"
" fem-lnagain[=dbm] Set the Rx LNA gain in dBm of the external FEM.\n"
" ncp-dataset Retrieve dataset from ncp.\n"
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2020, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
source "tests/scripts/expect/_common.exp"
spawn_node 1
send "region\n"
expect "Done"
send "region US\n"
expect "Done"
send "region\n"
expect "US"
expect "Done"