diff --git a/configure.ac b/configure.ac index a99d5f89c..8f9e58c97 100644 --- a/configure.ac +++ b/configure.ac @@ -841,6 +841,36 @@ AC_SUBST(OPENTHREAD_ENABLE_APPLICATION_COAP) AM_CONDITIONAL([OPENTHREAD_ENABLE_APPLICATION_COAP], [test "${enable_application_coap}" = "yes"]) AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_APPLICATION_COAP],[${OPENTHREAD_ENABLE_APPLICATION_COAP}],[Define to 1 if you want to enable CoAP to an application.]) +# +# otLinkRaw API +# + +AC_ARG_ENABLE(raw_link_api, + [AS_HELP_STRING([--enable-raw-link-api],[Enable raw link-layer API support @<:@default=yes@:>@.])], + [ + case "${enableval}" in + + no|yes) + enable_raw_link_api=${enableval} + ;; + + *) + AC_MSG_ERROR([Invalid value ${enable_raw_link_api} for --enable-raw-link-api]) + ;; + esac + ], + [enable_raw_link_api=yes]) + +if test "$enable_raw_link_api" = "yes"; then + OPENTHREAD_ENABLE_RAW_LINK_API=1 +else + OPENTHREAD_ENABLE_RAW_LINK_API=0 +fi + +AC_SUBST(OPENTHREAD_ENABLE_RAW_LINK_API) +AM_CONDITIONAL([OPENTHREAD_ENABLE_RAW_LINK_API], [test "${enable_raw_link_api}" = "yes"]) +AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_RAW_LINK_API],[${OPENTHREAD_ENABLE_RAW_LINK_API}],[Define to 1 if you want to enable raw link-layer API]) + # # Examples # @@ -1125,6 +1155,7 @@ AC_MSG_NOTICE([ OpenThread DHCPv6 Server support : ${enable_dhcp6_server} OpenThread DHCPv6 Client support : ${enable_dhcp6_client} Openthread Application CoAP support : ${enable_application_coap} + Openthread Raw Link-Layer support : ${enable_raw_link_api} OpenThread examples : ${OPENTHREAD_EXAMPLES} OpenThread platform information : ${PLATFORM_INFO} diff --git a/etc/visual-studio/libopenthread.vcxproj b/etc/visual-studio/libopenthread.vcxproj index 44f603d32..8fccebc21 100644 --- a/etc/visual-studio/libopenthread.vcxproj +++ b/etc/visual-studio/libopenthread.vcxproj @@ -54,6 +54,7 @@ + @@ -119,6 +120,10 @@ + + + + diff --git a/etc/visual-studio/libopenthread.vcxproj.filters b/etc/visual-studio/libopenthread.vcxproj.filters index 4b592cc1b..fe3856169 100644 --- a/etc/visual-studio/libopenthread.vcxproj.filters +++ b/etc/visual-studio/libopenthread.vcxproj.filters @@ -4,14 +4,8 @@ {c09c2d1c-85fb-4081-8235-925b45ed3c4b} - - {9a61353a-8613-4496-9ee8-c3d2800c5ac6} - - - {a49a9cc3-6a37-48a6-8049-b10c9cecd193} - - - {444ab8c6-6b83-4a5b-9059-67f469da1331} + + {CE77AA98-FC98-4FC6-BB52-8A886378AB5E} {a59636b8-d046-46b7-992b-76572ca72bd1} @@ -19,9 +13,24 @@ {7c989f53-480b-42d4-a2dc-454adafda818} + + {444ab8c6-6b83-4a5b-9059-67f469da1331} + + + {a49a9cc3-6a37-48a6-8049-b10c9cecd193} + + + {0e7f4f58-a115-4ce8-8e3b-1094fb79af52} + + + {9a61353a-8613-4496-9ee8-c3d2800c5ac6} + {c14a7a3f-089f-47ee-80db-1caf1b47ab6b} + + {A0D2E990-DC5E-4B56-A552-888F97214A17} + {b4905c15-9702-4ff0-8d57-e7926337d50f} @@ -43,20 +52,17 @@ {702145f9-0e66-4e45-b3d4-d43f2cf17e10} - - {0e7f4f58-a115-4ce8-8e3b-1094fb79af52} - {635aaabf-80f0-40e2-9218-22ff75bc0e32} - - {A0D2E990-DC5E-4B56-A552-888F97214A17} - {5ac96cb9-6257-4387-9238-27649915463a} + + Source Files\api + Source Files\coap diff --git a/etc/visual-studio/libopenthread_k.vcxproj b/etc/visual-studio/libopenthread_k.vcxproj index 678b8f8e3..73e2e7a23 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj +++ b/etc/visual-studio/libopenthread_k.vcxproj @@ -131,6 +131,7 @@ + diff --git a/etc/visual-studio/libopenthread_k.vcxproj.filters b/etc/visual-studio/libopenthread_k.vcxproj.filters index 078401546..7611e7f17 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj.filters +++ b/etc/visual-studio/libopenthread_k.vcxproj.filters @@ -4,14 +4,8 @@ {c09c2d1c-85fb-4081-8235-925b45ed3c4b} - - {9a61353a-8613-4496-9ee8-c3d2800c5ac6} - - - {a49a9cc3-6a37-48a6-8049-b10c9cecd193} - - - {444ab8c6-6b83-4a5b-9059-67f469da1331} + + {B78747A9-11C2-4784-B825-D48FD388FE2F} {a59636b8-d046-46b7-992b-76572ca72bd1} @@ -19,9 +13,24 @@ {7c989f53-480b-42d4-a2dc-454adafda818} + + {444ab8c6-6b83-4a5b-9059-67f469da1331} + + + {a49a9cc3-6a37-48a6-8049-b10c9cecd193} + + + {50a39acc-fab6-4e2a-85b7-d764be5299f5} + + + {9a61353a-8613-4496-9ee8-c3d2800c5ac6} + {c14a7a3f-089f-47ee-80db-1caf1b47ab6b} + + {A0D2E990-DC5E-4B56-A552-888F97214A17} + {b4905c15-9702-4ff0-8d57-e7926337d50f} @@ -37,26 +46,23 @@ {90294598-e94b-4c07-a531-93335a8955d9} + + {8f54e8b3-d8fb-4fed-88ce-42b39f171d0b} + {0c76d116-0b4d-4fec-a0d8-5ca127913124} {702145f9-0e66-4e45-b3d4-d43f2cf17e10} - - {50a39acc-fab6-4e2a-85b7-d764be5299f5} - - - {8f54e8b3-d8fb-4fed-88ce-42b39f171d0b} - - - {A0D2E990-DC5E-4B56-A552-888F97214A17} - {5ac96cb9-6257-4387-9238-27649915463a} + + Source Files\api + Source Files\coap @@ -501,4 +507,4 @@ Header Files - + \ No newline at end of file diff --git a/examples/drivers/windows/otLwf/radio.c b/examples/drivers/windows/otLwf/radio.c index 70217f550..d9ad431f1 100644 --- a/examples/drivers/windows/otLwf/radio.c +++ b/examples/drivers/windows/otLwf/radio.c @@ -271,6 +271,13 @@ void otPlatRadioSetPromiscuous(_In_ otInstance *otCtx, bool aEnable) } } +bool otPlatRadioIsEnabled(_In_ otInstance *otCtx) +{ + NT_ASSERT(otCtx); + PMS_FILTER pFilter = otCtxToFilter(otCtx); + return pFilter->otPhyState != kStateSleep; +} + ThreadError otPlatRadioEnable(_In_ otInstance *otCtx) { NT_ASSERT(otCtx); diff --git a/include/Makefile.am b/include/Makefile.am index b4c3a6932..aa4bd5fbf 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -59,6 +59,7 @@ PRETTY_SUBDIRS = \ $(NULL) include_HEADERS = \ + openthread/link_raw.h \ openthread.h \ openthread-coap.h \ openthread-crypto.h \ diff --git a/include/openthread-windows-config.h b/include/openthread-windows-config.h index dfdc2256d..676fc00c1 100644 --- a/include/openthread-windows-config.h +++ b/include/openthread-windows-config.h @@ -56,6 +56,13 @@ /* Define to 1 to enable MAC whitelist/blacklist feature. */ #define OPENTHREAD_ENABLE_MAC_WHITELIST 1 +/* Define to 1 to enable raw link-layer API. */ +#ifdef _KERNEL_MODE +#define OPENTHREAD_ENABLE_RAW_LINK_API 0 +#else +#define OPENTHREAD_ENABLE_RAW_LINK_API 1 +#endif + /* Name of package */ #define PACKAGE "openthread" diff --git a/include/openthread/link_raw.h b/include/openthread/link_raw.h new file mode 100644 index 000000000..f9d99b1d3 --- /dev/null +++ b/include/openthread/link_raw.h @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2016, 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 + * @brief + * This file defines the raw OpenThread IEEE 802.15.4 Link Layer API. + */ + +#ifndef LINK_RAW_H_ +#define LINK_RAW_H_ + +#include +//#include "openthread/types.h" +#include "platform/radio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup linkraw Link Raw + * + * @brief + * This module includes functions that control the raw link-layer configuration. + * + * @{ + * + */ + +/** + * This function enables/disables the raw link-layer. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aEnabled TRUE to enable raw link-layer, FALSE otherwise. + * + * @retval kThreadError_None If the enable state was successfully set. + * @retval kThreadError_InvalidState If the OpenThread Ip6 interface is already enabled. + * + */ +ThreadError otLinkRawSetEnable(otInstance *aInstance, bool aEnabled); + +/** + * This function indicates whether or not the raw link-layer is enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval true The raw link-layer is enabled. + * @retval false The raw link-layer is disabled. + * + */ +bool otLinkRawIsEnabled(otInstance *aInstance); + +/** + * This function set the IEEE 802.15.4 PAN ID. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPanId The IEEE 802.15.4 PAN ID. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSetPanId(otInstance *aInstance, uint16_t aPanId); + +/** + * This function sets the IEEE 802.15.4 Extended Address. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aExtendedAddress A pointer to the IEEE 802.15.4 Extended Address. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtendedAddress); + +/** + * Set the Short Address for address filtering. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aShortAddress The IEEE 802.15.4 Short Address. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSetShortAddress(otInstance *aInstance, uint16_t aShortAddress); + +/** + * This function gets the status of promiscuous mode. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval true Promiscuous mode is enabled. + * @retval false Promiscuous mode is disabled. + * + */ +bool otLinkRawGetPromiscuous(otInstance *aInstance); + +/** + * This function enables or disables promiscuous mode. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aEnable A value to enable or disable promiscuous mode. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSetPromiscuous(otInstance *aInstance, bool aEnable); + +/** + * Transition the radio from Receive to Sleep. + * Turn off the radio. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval kThreadError_None Successfully transitioned to Sleep. + * @retval kThreadError_Busy The radio was transmitting + * @retval kThreadError_InvalidState The radio was disabled + * + */ +ThreadError otLinkRawSleep(otInstance *aInstance); + +/** + * This function pointer on receipt of a IEEE 802.15.4 frame. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPacket A pointer to the received packet or NULL if the receive operation was aborted. + * @param[in] aaError kThreadError_None when successfully received a frame. + * kThreadError_Abort when reception was aborted and a frame was not received. + * + */ +typedef void (OTCALL *otLinkRawReceiveDone)(otInstance *aInstance, RadioPacket *aPacket, ThreadError aError); + +/** + * Transitioning the radio from Sleep to Receive. + * Turn on the radio. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aChannel The channel to use for receiving. + * @param[in] aCallback A pointer to a function called on receipt of a IEEE 802.15.4 frame. + * + * @retval kThreadError_None Successfully transitioned to Receive. + * @retval kThreadError_InvalidState The radio was disabled or transmitting. + * + */ +ThreadError otLinkRawReceive(otInstance *aInstance, uint8_t aChannel, otLinkRawReceiveDone aCallback); + +/** + * The radio transitions from Transmit to Receive. + * This method returns a pointer to the transmit buffer. + * + * The caller forms the IEEE 802.15.4 frame in this buffer then calls otLinkRawTransmit() + * to request transmission. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns A pointer to the transmit buffer or NULL if the raw link-layer isn't enabled. + * + */ +RadioPacket *otLinkRawGetTransmitBuffer(otInstance *aInstance); + +/** + * This function pointer on receipt of a IEEE 802.15.4 frame. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPacket A pointer to the packet that was transmitted. + * @param[in] aFramePending TRUE if an ACK frame was received and the Frame Pending bit was set. + * @param[in] aError kThreadError_None when the frame was transmitted. + * kThreadError_NoAck when the frame was transmitted but no ACK was received + * kThreadError_ChannelAccessFailure when the transmission could not take place + due to activity on the channel. + * kThreadError_Abort when transmission was aborted for other reasons. + * + */ +typedef void (*otLinkRawTransmitDone)(otInstance *aInstance, RadioPacket *aPacket, bool aFramePending, + ThreadError aError); + +/** + * This method begins the transmit sequence on the radio. + * + * The caller must form the IEEE 802.15.4 frame in the buffer provided by otLinkRawGetTransmitBuffer() before + * requesting transmission. The channel and transmit power are also included in the RadioPacket structure. + * + * The transmit sequence consists of: + * 1. Transitioning the radio to Transmit from Receive. + * 2. Transmits the psdu on the given channel and at the given transmit power. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPacket A pointer to the packet that was transmitted. + * @param[in] aCallback A pointer to a function called on completion of the transmission. + * + * @retval kThreadError_None Successfully transitioned to Transmit. + * @retval kThreadError_InvalidState The radio was not in the Receive state. + * + */ +ThreadError otLinkRawTransmit(otInstance *aInstance, RadioPacket *aPacket, otLinkRawTransmitDone aCallback); + +/** + * Get the most recent RSSI measurement. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns The RSSI in dBm when it is valid. 127 when RSSI is invalid. + * + */ +int8_t otLinkRawGetRssi(otInstance *aInstance); + +/** + * Get the radio capabilities. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns The radio capability bit vector. The stack enables or disables some functions based on this value. + * + */ +otRadioCaps otLinkRawGetCaps(otInstance *aInstance); + +/** + * This function pointer on receipt of a IEEE 802.15.4 frame. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aEnergyScanMaxRssi The maximum RSSI encountered on the scanned channel. + * + */ +typedef void (*otLinkRawEnergyScanDone)(otInstance *aInstance, int8_t aEnergyScanMaxRssi); + +/** + * This method begins the energy scan sequence on the radio. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aScanChannel The channel to perform the energy scan on. + * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. + * @param[in] aCallback A pointer to a function called on completion of a scanned channel. + * + * @retval kThreadError_None Successfully started scanning the channel. + * @retval kThreadError_NotImplemented The radio doesn't support energy scanning. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration, + otLinkRawEnergyScanDone aCallback); + +/** + * Enable/Disable source match for AutoPend. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aEnable Enable/disable source match for automatical pending. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchEnable(otInstance *aInstance, bool aEnable); + +/** + * Adding short address to the source match table. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aShortAddress The short address to be added. + * + * @retval kThreadError_None Successfully added short address to the source match table. + * @retval kThreadError_NoBufs No available entry in the source match table. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchAddShortEntry(otInstance *aInstance, const uint16_t aShortAddress); + +/** + * Adding extended address to the source match table. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aExtAddress The extended address to be added. + * + * @retval kThreadError_None Successfully added extended address to the source match table. + * @retval kThreadError_NoBufs No available entry in the source match table. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchAddExtEntry(otInstance *aInstance, const uint8_t *aExtAddress); + +/** + * Removing short address to the source match table. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aShortAddress The short address to be removed. + * + * @retval kThreadError_None Successfully removed short address from the source match table. + * @retval kThreadError_NoAddress The short address is not in source match table. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchClearShortEntry(otInstance *aInstance, const uint16_t aShortAddress); + +/** + * Removing extended address to the source match table of the radio. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aExtAddress The extended address to be removed. + * + * @retval kThreadError_None Successfully removed the extended address from the source match table. + * @retval kThreadError_NoAddress The extended address is not in source match table. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchClearExtEntry(otInstance *aInstance, const uint8_t *aExtAddress); + +/** + * Removing all the short addresses from the source match table. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchClearShortEntries(otInstance *aInstance); + +/** + * Removing all the extended addresses from the source match table. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval kThreadError_None If successful. + * @retval kThreadError_InvalidState If the raw link-layer isn't enabled. + * + */ +ThreadError otLinkRawSrcMatchClearExtEntries(otInstance *aInstance); + +/** + * @} + * + */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // LINK_RAW_H_ diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 1b3486354..456cab8a8 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -133,6 +133,12 @@ SOURCES_COMMON += \ $(NULL) endif # OPENTHREAD_ENABLE_JAM_DETECTION +if OPENTHREAD_ENABLE_RAW_LINK_API +SOURCES_COMMON += \ + api/link_raw_api.cpp \ + $(NULL) +endif # OPENTHREAD_ENABLE_RAW_LINK_API + libopenthread_ftd_a_CPPFLAGS = \ $(CPPFLAGS_COMMON) \ $(NULL) diff --git a/src/core/api/link_raw_api.cpp b/src/core/api/link_raw_api.cpp new file mode 100644 index 000000000..abd58bdbc --- /dev/null +++ b/src/core/api/link_raw_api.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2016, 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 implements blacklist IEEE 802.15.4 frame filtering based on MAC address. + */ + +#include "openthread-instance.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ThreadError otLinkRawSetEnable(otInstance *aInstance, bool aEnabled) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(!aInstance->mThreadNetif.IsUp(), error = kThreadError_InvalidState); + + aInstance->mLinkRawEnabled = aEnabled; + +exit: + return error; +} + +bool otLinkRawIsEnabled(otInstance *aInstance) +{ + return aInstance->mLinkRawEnabled; +} + +ThreadError otLinkRawSetPanId(otInstance *aInstance, uint16_t aPanId) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + otPlatRadioSetPanId(aInstance, aPanId); + +exit: + return error; +} + +ThreadError otLinkRawSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtendedAddress) +{ + ThreadError error = kThreadError_None; + uint8_t buf[sizeof(otExtAddress)]; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + for (size_t i = 0; i < sizeof(buf); i++) + { + buf[i] = aExtendedAddress->m8[7 - i]; + } + + otPlatRadioSetExtendedAddress(aInstance, buf); + +exit: + return error; +} + +ThreadError otLinkRawSetShortAddress(otInstance *aInstance, uint16_t aShortAddress) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + otPlatRadioSetShortAddress(aInstance, aShortAddress); + +exit: + return error; +} + +bool otLinkRawGetPromiscuous(otInstance *aInstance) +{ + return otPlatRadioGetPromiscuous(aInstance); +} + +ThreadError otLinkRawSetPromiscuous(otInstance *aInstance, bool aEnable) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + otPlatRadioSetPromiscuous(aInstance, aEnable); + +exit: + return error; +} + +ThreadError otLinkRawSleep(otInstance *aInstance) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + error = otPlatRadioSleep(aInstance); + +exit: + return error; +} + +ThreadError otLinkRawReceive(otInstance *aInstance, uint8_t aChannel, otLinkRawReceiveDone aCallback) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + aInstance->mLinkRawReceiveDoneCallback = aCallback; + + error = otPlatRadioReceive(aInstance, aChannel); + +exit: + return error; +} + +RadioPacket *otLinkRawGetTransmitBuffer(otInstance *aInstance) +{ + RadioPacket *buffer = NULL; + + VerifyOrExit(aInstance->mLinkRawEnabled,); + + buffer = otPlatRadioGetTransmitBuffer(aInstance); + +exit: + return buffer; +} + +ThreadError otLinkRawTransmit(otInstance *aInstance, RadioPacket *aPacket, otLinkRawTransmitDone aCallback) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + aInstance->mLinkRawTransmitDoneCallback = aCallback; + + error = otPlatRadioTransmit(aInstance, aPacket); + +exit: + return error; +} + +int8_t otLinkRawGetRssi(otInstance *aInstance) +{ + return otPlatRadioGetRssi(aInstance); +} + +otRadioCaps otLinkRawGetCaps(otInstance *aInstance) +{ + return otPlatRadioGetCaps(aInstance); +} + +ThreadError otLinkRawEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration, + otLinkRawEnergyScanDone aCallback) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + aInstance->mLinkRawEnergyScanDoneCallback = aCallback; + + error = otPlatRadioEnergyScan(aInstance, aScanChannel, aScanDuration); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchEnable(otInstance *aInstance, bool aEnable) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + otPlatRadioEnableSrcMatch(aInstance, aEnable); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchAddShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + error = otPlatRadioAddSrcMatchShortEntry(aInstance, aShortAddress); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchAddExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + error = otPlatRadioAddSrcMatchExtEntry(aInstance, aExtAddress); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchClearShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + error = otPlatRadioClearSrcMatchShortEntry(aInstance, aShortAddress); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchClearExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + error = otPlatRadioClearSrcMatchExtEntry(aInstance, aExtAddress); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchClearShortEntries(otInstance *aInstance) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + otPlatRadioClearSrcMatchShortEntries(aInstance); + +exit: + return error; +} + +ThreadError otLinkRawSrcMatchClearExtEntries(otInstance *aInstance) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); + + otPlatRadioClearSrcMatchExtEntries(aInstance); + +exit: + return error; +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index d34b6d758..3f52dd7a1 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -264,7 +264,21 @@ void Mac::StartEnergyScan(void) extern "C" void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi) { - aInstance->mThreadNetif.GetMac().EnergyScanDone(aEnergyScanMaxRssi); +#if OPENTHREAD_ENABLE_RAW_LINK_API + + if (aInstance->mLinkRawEnabled) + { + if (aInstance->mLinkRawEnergyScanDoneCallback) + { + aInstance->mLinkRawEnergyScanDoneCallback(aInstance, aEnergyScanMaxRssi); + aInstance->mLinkRawEnergyScanDoneCallback = NULL; + } + } + else +#endif // OPENTHREAD_ENABLE_RAW_LINK_API + { + aInstance->mThreadNetif.GetMac().EnergyScanDone(aEnergyScanMaxRssi); + } } void Mac::EnergyScanDone(int8_t aEnergyScanMaxRssi) @@ -791,7 +805,22 @@ extern "C" void otPlatRadioTransmitDone(otInstance *aInstance, RadioPacket *aPac { otLogFuncEntryMsg("%!otError!, aRxPending=%u", aError, aRxPending ? 1 : 0); - aInstance->mThreadNetif.GetMac().TransmitDoneTask(aPacket, aRxPending, aError); +#if OPENTHREAD_ENABLE_RAW_LINK_API + + if (aInstance->mLinkRawEnabled) + { + if (aInstance->mLinkRawTransmitDoneCallback) + { + aInstance->mLinkRawTransmitDoneCallback(aInstance, aPacket, aRxPending, aError); + aInstance->mLinkRawTransmitDoneCallback = NULL; + } + } + else +#endif // OPENTHREAD_ENABLE_RAW_LINK_API + { + aInstance->mThreadNetif.GetMac().TransmitDoneTask(aPacket, aRxPending, aError); + } + otLogFuncExit(); } @@ -1164,7 +1193,22 @@ exit: extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError) { otLogFuncEntryMsg("%!otError!", aError); - aInstance->mThreadNetif.GetMac().ReceiveDoneTask(static_cast(aFrame), aError); + +#if OPENTHREAD_ENABLE_RAW_LINK_API + + if (aInstance->mLinkRawEnabled) + { + if (aInstance->mLinkRawReceiveDoneCallback) + { + aInstance->mLinkRawReceiveDoneCallback(aInstance, aFrame, aError); + } + } + else +#endif // OPENTHREAD_ENABLE_RAW_LINK_API + { + aInstance->mThreadNetif.GetMac().ReceiveDoneTask(static_cast(aFrame), aError); + } + otLogFuncExit(); } diff --git a/src/core/openthread-instance.h b/src/core/openthread-instance.h index 46344f443..ef833b22b 100644 --- a/src/core/openthread-instance.h +++ b/src/core/openthread-instance.h @@ -44,6 +44,7 @@ #include #include #include +#include "openthread/link_raw.h" /** * This type represents all the static / global variables used by OpenThread allocated in one place. @@ -65,6 +66,13 @@ typedef struct otInstance otHandleEnergyScanResult mEnergyScanCallback; void *mEnergyScanCallbackContext; +#if OPENTHREAD_ENABLE_RAW_LINK_API + bool mLinkRawEnabled; + otLinkRawReceiveDone mLinkRawReceiveDoneCallback; + otLinkRawTransmitDone mLinkRawTransmitDoneCallback; + otLinkRawEnergyScanDone mLinkRawEnergyScanDoneCallback; +#endif // OPENTHREAD_ENABLE_RAW_LINK_API + // // State // diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index c6f9690fc..075076a44 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -81,6 +81,12 @@ otInstance::otInstance(void) : mActiveScanCallbackContext(NULL), mEnergyScanCallback(NULL), mEnergyScanCallbackContext(NULL), +#if OPENTHREAD_ENABLE_RAW_LINK_API + mLinkRawEnabled(false), + mLinkRawReceiveDoneCallback(NULL), + mLinkRawTransmitDoneCallback(NULL), + mLinkRawEnergyScanDoneCallback(NULL), +#endif // OPENTHREAD_ENABLE_RAW_LINK_API mThreadNetif(mIp6) #if OPENTHREAD_ENABLE_APPLICATION_COAP , mApplicationCoapServer(mIp6.mUdp, OT_DEFAULT_COAP_PORT) @@ -1252,8 +1258,15 @@ ThreadError otInterfaceUp(otInstance *aInstance) otLogFuncEntry(); +#if OPENTHREAD_ENABLE_RAW_LINK_API + VerifyOrExit(!aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); +#endif // OPENTHREAD_ENABLE_RAW_LINK_API + error = aInstance->mThreadNetif.Up(); +#if OPENTHREAD_ENABLE_RAW_LINK_API +exit: +#endif // OPENTHREAD_ENABLE_RAW_LINK_API otLogFuncExitErr(error); return error; } @@ -1264,8 +1277,15 @@ ThreadError otInterfaceDown(otInstance *aInstance) otLogFuncEntry(); +#if OPENTHREAD_ENABLE_RAW_LINK_API + VerifyOrExit(!aInstance->mLinkRawEnabled, error = kThreadError_InvalidState); +#endif // OPENTHREAD_ENABLE_RAW_LINK_API + error = aInstance->mThreadNetif.Down(); +#if OPENTHREAD_ENABLE_RAW_LINK_API +exit: +#endif // OPENTHREAD_ENABLE_RAW_LINK_API otLogFuncExitErr(error); return error; } diff --git a/tests/unit/test_fuzz.cpp b/tests/unit/test_fuzz.cpp index 169045759..e824b8857 100644 --- a/tests/unit/test_fuzz.cpp +++ b/tests/unit/test_fuzz.cpp @@ -37,6 +37,11 @@ uint8_t g_TransmitPsdu[128]; RadioPacket g_TransmitRadioPacket; bool g_fTransmit = false; +bool testFuzzRadioIsEnabled(otInstance *) +{ + return g_fRadioEnabled; +} + ThreadError testFuzzRadioEnable(otInstance *) { #ifdef DBG_FUZZ @@ -85,6 +90,7 @@ void TestFuzz(uint32_t aSeconds) // Set the platform function pointers g_TransmitRadioPacket.mPsdu = g_TransmitPsdu; + g_testPlatRadioIsEnabled = testFuzzRadioIsEnabled; g_testPlatRadioEnable = testFuzzRadioEnable; g_testPlatRadioDisable = testFuzzRadioDisable; g_testPlatRadioReceive = testFuzzRadioReceive; diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index 7517ce984..a3a042efc 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -49,6 +49,7 @@ testPlatAlarmGetNow g_testPlatAlarmGetNow = NULL; otRadioCaps g_testPlatRadioCaps = kRadioCapsNone; testPlatRadioSetPanId g_testPlatRadioSetPanId = NULL; testPlatRadioSetExtendedAddress g_testPlatRadioSetExtendedAddress = NULL; +testPlatRadioIsEnabled g_testPlatRadioIsEnabled = NULL; testPlatRadioEnable g_testPlatRadioEnable = NULL; testPlatRadioDisable g_testPlatRadioDisable = NULL; testPlatRadioSetShortAddress g_testPlatRadioSetShortAddress = NULL; @@ -68,6 +69,7 @@ void testPlatResetToDefaults(void) g_testPlatRadioSetPanId = NULL; g_testPlatRadioSetExtendedAddress = NULL; g_testPlatRadioSetShortAddress = NULL; + g_testPlatRadioIsEnabled = NULL; g_testPlatRadioEnable = NULL; g_testPlatRadioDisable = NULL; g_testPlatRadioReceive = NULL; @@ -162,6 +164,18 @@ extern "C" { { } + bool otPlatRadioIsEnabled(otInstance *aInstance) + { + if (g_testPlatRadioIsEnabled) + { + return g_testPlatRadioIsEnabled(aInstance); + } + else + { + return true; + } + } + ThreadError otPlatRadioEnable(otInstance *aInstance) { if (g_testPlatRadioEnable) diff --git a/tests/unit/test_platform.h b/tests/unit/test_platform.h index c6d7b8530..1483c8ac7 100644 --- a/tests/unit/test_platform.h +++ b/tests/unit/test_platform.h @@ -71,6 +71,7 @@ typedef void (*testPlatRadioSetPanId)(otInstance *, uint16_t); typedef void (*testPlatRadioSetExtendedAddress)(otInstance *, uint8_t *); typedef void (*testPlatRadioSetShortAddress)(otInstance *, uint16_t); +typedef bool(*testPlatRadioIsEnabled)(otInstance *); typedef ThreadError(*testPlatRadioEnable)(otInstance *); typedef ThreadError(*testPlatRadioDisable)(otInstance *); typedef ThreadError(*testPlatRadioReceive)(otInstance *, uint8_t); @@ -81,6 +82,7 @@ extern otRadioCaps g_testPlatRadioCaps; extern testPlatRadioSetPanId g_testPlatRadioSetPanId; extern testPlatRadioSetExtendedAddress g_testPlatRadioSetExtendedAddress; extern testPlatRadioSetShortAddress g_testPlatRadioSetShortAddress; +extern testPlatRadioIsEnabled g_testPlatRadioIsEnabled; extern testPlatRadioEnable g_testPlatRadioEnable; extern testPlatRadioDisable g_testPlatRadioDisable; extern testPlatRadioReceive g_testPlatRadioReceive;