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;