Skip to content

Commit

Permalink
[spinel] add vendor hook for the spinel host side (openthread#9560)
Browse files Browse the repository at this point in the history
Allow out-of-tree compilation of vendor specific changes to the host
side of spinel.  By setting `OT_SPINEL_VENDOR_HOOK_SOURCE_DIR`,
`OT_SPINEL_VENDOR_HOOK_SOURCE` and `OT_SPINEL_VENDOR_HOOK_HEADER`, the
corresponding compile flags
`OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK` and
`OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER` get set which force the
use of the `VendorRadioSpinel` class instead of the regular
`RadioSpinel` in `src/Posix/platform/radio`.
  • Loading branch information
thcu-gp authored Dec 4, 2023
1 parent 2d030c4 commit 3d01ffa
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/lib/spinel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ set(COMMON_SOURCES
spinel_encoder.cpp
)

set(OT_SPINEL_VENDOR_HOOK_SOURCE "" CACHE STRING "set vendor hook source file for Spinel")
set(OT_SPINEL_VENDOR_HOOK_HEADER "" CACHE STRING "set vendor hook header file for Spinel")
if(OT_SPINEL_VENDOR_HOOK_SOURCE)
target_compile_definitions(openthread-spinel-rcp PUBLIC "OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK=1")
target_compile_definitions(openthread-spinel-ncp PUBLIC "OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK=1")
target_compile_definitions(openthread-spinel-rcp PUBLIC "OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER=\"${OT_SPINEL_VENDOR_HOOK_HEADER}\"")
target_compile_definitions(openthread-spinel-ncp PUBLIC "OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER=\"${OT_SPINEL_VENDOR_HOOK_HEADER}\"")
list(APPEND COMMON_SOURCES ${OT_SPINEL_VENDOR_HOOK_SOURCE_DIR}${OT_SPINEL_VENDOR_HOOK_SOURCE})
list(APPEND COMMON_INCLUDES ${OT_SPINEL_VENDOR_HOOK_SOURCE_DIR})
endif()

target_include_directories(openthread-radio-spinel PUBLIC ${OT_PUBLIC_INCLUDES} PRIVATE ${COMMON_INCLUDES})
target_include_directories(openthread-spinel-ncp PUBLIC ${OT_PUBLIC_INCLUDES} PRIVATE ${COMMON_INCLUDES})
target_include_directories(openthread-spinel-rcp PUBLIC ${OT_PUBLIC_INCLUDES} PRIVATE ${COMMON_INCLUDES})
Expand Down
67 changes: 67 additions & 0 deletions src/lib/spinel/example_vendor_hook.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2023, 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.
*/

/**
* @file
* This file shows how to implement the Radio Spinel vendor hook.
*/

#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK

#include OPENTRHEAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#include "common/log.hpp"
#include "lib/platform/exit_code.h"

namespace ot {
namespace Spinel {

otError RadioSpinel::VendorHandleValueIs(spinel_prop_key_t aPropKey)
{
otError error = OT_ERROR_NONE;

switch (aPropKey)
{
// TODO: Implement your property get handlers here.
//
// Get handler should retrieve the property value and then encode and write the
// value into the NCP buffer. If the "get" operation itself fails, handler should
// write a `LAST_STATUS` with the error status into the NCP buffer. `OT_ERROR_NO_BUFS`
// should be returned if NCP buffer is full and response cannot be written.
default:
error = OT_ERROR_NOT_FOUND;
break;
}
exit:
return error;
}

} // namespace Spinel
} // namespace ot

extern ot::Spinel::RadioSpinel &GetRadioSpinel(void);

#endif // OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
59 changes: 59 additions & 0 deletions src/lib/spinel/example_vendor_hook.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2023, 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.
*/

/**
* @file
* This file shows how to implement the Radio Spinel vendor hook.
*/

#ifndef SPINEL_EXTENSION_H
#define SPINEL_EXTENSION_H

#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK

#include <openthread/thread_ftd.h>
#include "lib/spinel/radio_spinel.hpp"

namespace ot {
namespace Spinel {

class VendorRadioSpinel : public ot::Spinel::RadioSpinel
{
public:
VendorRadioSpinel(void)
: ot::Spinel::RadioSpinel()
{
}

// Add public/private methods or member variables
};

} // namespace Spinel
} // namespace ot

#endif // OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
#endif // SPINEL_EXTENSION_H
20 changes: 20 additions & 0 deletions src/lib/spinel/openthread-spinel-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,24 @@
#define OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID SPINEL_HEADER_IID_3
#endif

/**
* @def OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
*
* Enables compilation of vendor specific code for Spinel
*
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
#define OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK 0
#endif

/**
* @def OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
*
* Header file defining class VendorRadioSpinel
*
*/
#ifndef OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#define OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER "lib/spinel/example_vendor_hook.hpp"
#endif

#endif // OPENTHREAD_SPINEL_CONFIG_H_
6 changes: 6 additions & 0 deletions src/lib/spinel/radio_spinel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,12 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
break;
}
}
#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
else if (aKey >= SPINEL_PROP_VENDOR__BEGIN && aKey < SPINEL_PROP_VENDOR__END)
{
error = VendorHandleValueIs(aKey);
}
#endif

exit:
UpdateParseErrorCount(error);
Expand Down
20 changes: 20 additions & 0 deletions src/lib/spinel/radio_spinel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,26 @@ class RadioSpinel
*/
void RestoreProperties(void);
#endif
#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
/**
* Defines a vendor "set property handler" hook to process vendor spinel properties.
*
* The vendor handler should return `OT_ERROR_NOT_FOUND` status if it does not support "set" operation for the
* given property key. Otherwise, the vendor handler should behave like other property set handlers, i.e., it
* should first decode the value from the input spinel frame and then perform the corresponding set operation. The
* handler should not prepare the spinel response and therefore should not write anything to the NCP buffer. The
* `otError` returned from handler (other than `OT_ERROR_NOT_FOUND`) indicates the error in either parsing of the
* input or the error of the set operation. In case of a successful "set", `NcpBase` set command handler will call
* the `VendorGetPropertyHandler()` for the same property key to prepare the response.
*
* @param[in] aPropKey The spinel property key.
*
* @returns OT_ERROR_NOT_FOUND if it does not support the given property key, otherwise the error in either parsing
* of the input or the "set" operation.
*
*/
otError VendorHandleValueIs(spinel_prop_key_t aPropKey);
#endif

private:
enum
Expand Down
1 change: 1 addition & 0 deletions src/posix/platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ target_include_directories(openthread-posix PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/core
${PROJECT_SOURCE_DIR}/third_party/mbedtls/repo/include
${OT_SPINEL_VENDOR_HOOK_SOURCE_DIR}
PUBLIC
${PROJECT_SOURCE_DIR}/src/posix/platform/include
)
Expand Down
2 changes: 1 addition & 1 deletion src/posix/platform/radio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void Radio::GetIidListFromRadioUrl(spinel_iid_t (&aIidList)[Spinel::kSpinelHeade
} // namespace Posix
} // namespace ot

static ot::Spinel::RadioSpinel &GetRadioSpinel(void) { return sRadio.GetRadioSpinel(); }
ot::Spinel::RadioSpinel &GetRadioSpinel(void) { return sRadio.GetRadioSpinel(); }

void platformRadioDeinit(void) { GetRadioSpinel().Deinit(); }

Expand Down
13 changes: 11 additions & 2 deletions src/posix/platform/radio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
#include "posix/platform/radio_url.hpp"
#include "posix/platform/spi_interface.hpp"
#include "posix/platform/vendor_interface.hpp"
#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
#ifdef OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#include OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#endif
#endif

namespace ot {
namespace Posix {
Expand Down Expand Up @@ -104,8 +109,12 @@ class Radio
#error "No Spinel interface is specified!"
#endif

RadioUrl mRadioUrl;
Spinel::RadioSpinel mRadioSpinel;
RadioUrl mRadioUrl;
#if OPENTHREAD_ENABLE_SPINEL_VENDOR_HOOK
Spinel::VendorRadioSpinel mRadioSpinel;
#else
Spinel::RadioSpinel mRadioSpinel;
#endif
Spinel::SpinelInterface *mSpinelInterface;

OT_DEFINE_ALIGNED_VAR(mSpinelInterfaceRaw, kSpinelInterfaceRawSize, uint64_t);
Expand Down

0 comments on commit 3d01ffa

Please sign in to comment.