diff --git a/examples/all-clusters-app/nxp/mw320/BUILD.gn b/examples/all-clusters-app/nxp/mw320/BUILD.gn
index e93e919d6cf253..84d41622d7d8f1 100644
--- a/examples/all-clusters-app/nxp/mw320/BUILD.gn
+++ b/examples/all-clusters-app/nxp/mw320/BUILD.gn
@@ -37,13 +37,16 @@ mw320_sdk("sdk") {
"include/FreeRTOSConfig.h",
]
- defines = []
+ defines = [ "CHIP_CONFIG_MAX_FABRICS=5" ]
if (is_debug) {
defines += [ "BUILD_RELEASE=0" ]
} else {
defines += [ "BUILD_RELEASE=1" ]
}
+ if (wifi_conn_abort_support == true) {
+ defines += [ "WIFI_CONN_ABORT_SUPPORT" ]
+ }
}
mw320_executable("shell_mw320") {
diff --git a/examples/all-clusters-app/nxp/mw320/README.md b/examples/all-clusters-app/nxp/mw320/README.md
index 95905446be40e3..aad56b2fd17645 100755
--- a/examples/all-clusters-app/nxp/mw320/README.md
+++ b/examples/all-clusters-app/nxp/mw320/README.md
@@ -33,6 +33,7 @@ Building the example application is quite straightforward. It can be done via
following commands:
```
+$ cd examples/all-clusters-app/nxp/mw320/
$ git submodule update --init
$ source third_party/connectedhomeip/scripts/activate.sh
$ gn gen out/debug
@@ -56,7 +57,7 @@ Note: This solution is temporary.
In order to use the tinycrypt ecc operations, use the following build arguments:
```
-$ gn gen out/debug --args='treat_warnings_as_errors=false mbedtls_repo="//third_party/connectedhomeip/third_party/nxp/libs/mbedtls" mbedtls_use_tinycrypt=true'
+$ gn gen out/debug --args='treat_warnings_as_errors=false mbedtls_repo="//third_party/connectedhomeip/third_party/nxp/libs/mbedtls" chip_crypto="tinycrypt"'
```
diff --git a/examples/all-clusters-app/nxp/mw320/include/CHIPProjectConfig.h b/examples/all-clusters-app/nxp/mw320/include/CHIPProjectConfig.h
index f999353de5f521..ee38302054d87e 100644
--- a/examples/all-clusters-app/nxp/mw320/include/CHIPProjectConfig.h
+++ b/examples/all-clusters-app/nxp/mw320/include/CHIPProjectConfig.h
@@ -66,6 +66,49 @@
#endif // BUILD_RELEASE
+#if (defined(CONFIG_CHIP_MW320_REAL_FACTORY_DATA) && (CONFIG_CHIP_MW320_REAL_FACTORY_DATA == 1))
+
+// VID/PID for product => will be used by Basic Information Cluster
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220
+
+// set it to 0 for the moment
+#define CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER 0
+
+#ifndef CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION
+//-> format_version = 1
+//-> vendor_id = 0x1037
+//-> product_id_array = [ 0xA220 ]
+//-> device_type_id = 0x0015
+//-> certificate_id = "ZIG20142ZB330003-24"
+//-> security_level = 0
+//-> security_information = 0
+//-> version_number = 0x2694
+//-> certification_type = 1
+//-> dac_origin_vendor_id is not present
+//-> dac_origin_product_id is not present
+#define CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION \
+ { \
+ 0x30, 0x81, 0xe7, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x81, 0xd9, 0x30, 0x81, 0xd6, \
+ 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, \
+ 0x43, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x36, 0x04, 0x34, 0x15, 0x24, 0x00, \
+ 0x01, 0x25, 0x01, 0x37, 0x10, 0x36, 0x02, 0x05, 0x20, 0xa2, 0x18, 0x24, 0x03, 0x15, 0x2c, 0x04, 0x13, 0x5a, 0x49, \
+ 0x47, 0x32, 0x30, 0x31, 0x34, 0x31, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x31, 0x2d, 0x32, 0x34, 0x24, 0x05, \
+ 0x00, 0x24, 0x06, 0x00, 0x24, 0x07, 0x01, 0x24, 0x08, 0x01, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, 0x03, 0x80, \
+ 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, 0xf3, \
+ 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, \
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x11, 0x8c, 0x13, 0x63, 0x9a, \
+ 0xe7, 0x77, 0xaa, 0xc1, 0x52, 0x8c, 0x46, 0x40, 0x82, 0xcc, 0xdb, 0x6c, 0x43, 0x4d, 0xfc, 0xff, 0xe2, 0x5e, 0x1f, \
+ 0xda, 0xef, 0xdf, 0x0d, 0xf1, 0x7c, 0x2c, 0xcd, 0x02, 0x21, 0x00, 0xbf, 0xad, 0x91, 0xc3, 0x3b, 0xf5, 0xb9, 0x89, \
+ 0x2e, 0x5e, 0x15, 0x3c, 0x52, 0x61, 0xad, 0xb8, 0x53, 0x42, 0x46, 0xc6, 0x7d, 0xec, 0xc0, 0x93, 0x10, 0x1f, 0xc4, \
+ 0xd2, 0xc3, 0x8a, 0xd5, 0x16, \
+ }
+
+// All remaining data will be pulled from the provisioning region of flash.
+#endif
+
+#else // CONFIG_CHIP_MW320_REAL_FACTORY_DATA
+
// Use a default pairing code if one hasn't been provisioned in flash.
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
@@ -85,6 +128,8 @@
*/
#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8001
+#endif // CONFIG_CHIP_MW320_REAL_FACTORY_DATA
+
/**
* CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_REVISION
*
@@ -163,3 +208,5 @@
#else
#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug
#endif // BUILD_RELEASE
+
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 1
diff --git a/examples/all-clusters-app/nxp/mw320/main.cpp b/examples/all-clusters-app/nxp/mw320/main.cpp
index 94ed17d8f8200b..df0c1dfe6f4e73 100644
--- a/examples/all-clusters-app/nxp/mw320/main.cpp
+++ b/examples/all-clusters-app/nxp/mw320/main.cpp
@@ -46,8 +46,12 @@
#include
// cr++
+#if (defined(CONFIG_CHIP_MW320_REAL_FACTORY_DATA) && (CONFIG_CHIP_MW320_REAL_FACTORY_DATA == 1))
+#include "FactoryDataProvider.h"
+#else
#include
#include
+#endif // if CONFIG_CHIP_MW320_REAL_FACTORY_DATA
// cr--
// ota++
#include "app/clusters/ota-requestor/BDXDownloader.h"
@@ -93,6 +97,10 @@ extern "C" {
******************************************************************************/
#define APP_AES AES
#define CONNECTION_INFO_FILENAME "connection_info.dat"
+#define SSID_FNAME "ssid_fname"
+#define PSK_FNAME "psk_fname"
+
+#define VERSION_STR "mw320-2.9.10-005"
enum
{
MCUXPRESSO_WIFI_CLI,
@@ -101,6 +109,8 @@ enum
};
static int Matter_Selection = MAX_SELECTION;
#define RUN_RST_LT_DELAY 10
+static const char * TAG = "mw320";
+
/*******************************************************************************
* Variables
******************************************************************************/
@@ -113,6 +123,9 @@ const int TASK_MAIN_STACK_SIZE = 800;
portSTACK_TYPE * task_main_stack = NULL;
TaskHandle_t task_main_task_handler;
+uint8_t * __FACTORY_DATA_START;
+uint32_t __FACTORY_DATA_SIZE;
+
#if CHIP_ENABLE_OPENTHREAD
extern "C" {
#include
@@ -172,6 +185,31 @@ void InitOTARequestor(void)
// Initialize and interconnect the Requestor and Image Processor objects -- END
}
+const char * mw320_get_verstr(void)
+{
+ return VERSION_STR;
+}
+
+void save_network(char * ssid, char * pwd);
+void save_network(char * ssid, char * pwd)
+{
+ int ret;
+
+ ret = save_wifi_network((char *) SSID_FNAME, (uint8_t *) ssid, strlen(ssid) + 1);
+ if (ret != WM_SUCCESS)
+ {
+ PRINTF("Error: write ssid to flash failed\r\n");
+ }
+
+ ret = save_wifi_network((char *) PSK_FNAME, (uint8_t *) pwd, strlen(pwd) + 1);
+ if (ret != WM_SUCCESS)
+ {
+ PRINTF("Error: write psk to flash failed\r\n");
+ }
+
+ return;
+}
+
// ota --
namespace {
@@ -280,6 +318,8 @@ bool is_connected = false;
/*******************************************************************************
* Prototypes
******************************************************************************/
+static void load_network(char * ssid, char * pwd);
+
/*
static void saveProfile(int argc, char **argv);
static void loadProfile(int argc, char **argv);
@@ -328,6 +368,40 @@ static void APP_AES_Unlock(void)
xSemaphoreGiveRecursive(aesLock);
}
+static void load_network(char * ssid, char * pwd)
+{
+ int ret;
+ unsigned char ssid_buf[IEEEtypes_SSID_SIZE + 1];
+ unsigned char psk_buf[WLAN_PSK_MAX_LENGTH];
+ uint32_t len;
+
+ len = IEEEtypes_SSID_SIZE + 1;
+ ret = get_saved_wifi_network((char *) SSID_FNAME, ssid_buf, &len);
+ if (ret != WM_SUCCESS)
+ {
+ PRINTF("Error: Read saved SSID\r\n");
+ strcpy(ssid, "");
+ }
+ else
+ {
+ PRINTF("saved_ssid: [%s]\r\n", ssid_buf);
+ strcpy(ssid, (const char *) ssid_buf);
+ }
+
+ len = WLAN_PSK_MAX_LENGTH;
+ ret = get_saved_wifi_network((char *) PSK_FNAME, psk_buf, &len);
+ if (ret != WM_SUCCESS)
+ {
+ PRINTF("Error: Read saved PSK\r\n");
+ strcpy(pwd, "");
+ }
+ else
+ {
+ PRINTF("saved_psk: [%s]\r\n", psk_buf);
+ strcpy(pwd, (const char *) psk_buf);
+ }
+}
+
/*
static void saveProfile(int argc, char **argv)
{
@@ -527,7 +601,7 @@ int wlan_event_callback(enum wlan_event_reason reason, void * data)
switch (reason)
{
case WLAN_REASON_INITIALIZED:
-// PRINTF("app_cb: WLAN initialized\r\n");
+ // PRINTF("app_cb: WLAN initialized\r\n");
#ifdef MCUXPRESSO_WIFI_CLI
ret = wlan_basic_cli_init();
if (ret != WM_SUCCESS)
@@ -586,14 +660,14 @@ int wlan_event_callback(enum wlan_event_reason reason, void * data)
#endif
break;
case WLAN_REASON_INITIALIZATION_FAILED:
- // PRINTF("app_cb: WLAN: initialization failed\r\n");
+ // PRINTF("app_cb: WLAN: initialization failed\r\n");
break;
case WLAN_REASON_SUCCESS:
- // PRINTF("app_cb: WLAN: connected to network\r\n");
+ // PRINTF("app_cb: WLAN: connected to network\r\n");
ret = wlan_get_address(&addr);
if (ret != WM_SUCCESS)
{
- // PRINTF("failed to get IP address\r\n");
+ // PRINTF("failed to get IP address\r\n");
return 0;
}
@@ -602,12 +676,13 @@ int wlan_event_callback(enum wlan_event_reason reason, void * data)
ret = wlan_get_current_network(&sta_network);
if (ret != WM_SUCCESS)
{
- // PRINTF("Failed to get External AP network\r\n");
+ // PRINTF("Failed to get External AP network\r\n");
return 0;
}
PRINTF("Connected to following BSS:\r\n");
PRINTF("SSID = [%s], IP = [%s]\r\n", sta_network.ssid, ip);
+ save_network(sta_network.ssid, sta_network.security.psk);
#ifdef CONFIG_IPV6
{
@@ -966,7 +1041,16 @@ static void run_chip_srv(System::Layer * aSystemLayer, void * aAppState)
// Init ZCL Data Model and CHIP App Server
{
// Initialize device attestation config
+#if (defined(CONFIG_CHIP_MW320_REAL_FACTORY_DATA) && (CONFIG_CHIP_MW320_REAL_FACTORY_DATA == 1))
+ FactoryDataProvider::GetDefaultInstance().Init();
+#if (CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER == 1)
+ SetDeviceInstanceInfoProvider(&FactoryDataProvider::GetDefaultInstance());
+#endif // USE_LOCAL_DEVICEINSTANCEINFOPROVIDER
+ SetDeviceAttestationCredentialsProvider(&FactoryDataProvider::GetDefaultInstance());
+ SetCommissionableDataProvider(&FactoryDataProvider::GetDefaultInstance());
+#else
SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif // CONFIG_CHIP_MW320_REAL_FACTORY_DATA
}
{
// chip::Server::GetInstance().Init();
@@ -1062,6 +1146,12 @@ void task_test_main(void * param)
PRINTF("--> update ZCL_CURRENT_POSITION_ATTRIBUTE_ID [%d] \r\n", value);
emAfWriteAttribute(1, ZCL_SWITCH_CLUSTER_ID, ZCL_CURRENT_POSITION_ATTRIBUTE_ID, (uint8_t *) &value, sizeof(value), true,
false);
+#ifdef SUPPORT_MANUAL_CTRL
+ // sync-up the Light attribute (for test event, OO.M.ManuallyControlled)
+ PRINTF("--> update [ZCL_ON_OFF_CLUSTER_ID]: ZCL_ON_OFF_ATTRIBUTE_ID [%d] \r\n", value);
+ emAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, (uint8_t *) &value, sizeof(value), true, false);
+#endif // SUPPORT_MANUAL_CTRL
+
need2sync_sw_attr = false;
}
// =============================
@@ -1072,45 +1162,36 @@ void task_test_main(void * param)
return;
}
-void ShellCLIMain(void * pvParameter)
+void init_mw320_sdk()
{
flash_desc_t fl;
struct partition_entry *p, *f1, *f2;
short history = 0;
uint32_t * wififw;
struct partition_entry * psm;
+ struct partition_entry * manu_dat;
+ uint8_t * pmfdat;
- const int rc = streamer_init(streamer_get());
- if (rc != 0)
- {
- ChipLogError(Shell, "Streamer initialization failed: %d", rc);
- return;
- }
-
- ChipLogDetail(Shell, "Initializing CHIP shell commands: %d", rc);
-
- chip::Platform::MemoryInit();
- chip::DeviceLayer::PlatformMgr().InitChipStack();
- ConfigurationMgr().LogDeviceConfig();
- PrintOnboardingCodes(chip::RendezvousInformationFlag::kBLE);
- chip::DeviceLayer::PlatformMgr().StartEventLoopTask();
-#if CHIP_DEVICE_CONFIG_ENABLE_WPA
- chip::DeviceLayer::ConnectivityManagerImpl().StartWiFiManagement();
-#endif
-
- cmd_misc_init();
- // cmd_otcli_init();
-
- ChipLogDetail(Shell, "Run CHIP shell Task: %d", rc);
+ PRINTF("=> init mw320 sdk \r\n");
PRINTF("call mcuInitPower() \r\n");
mcuInitPower();
boot_init();
mflash_drv_init();
cli_init();
part_init();
+
psm = part_get_layout_by_id(FC_COMP_PSM, NULL);
part_to_flash_desc(psm, &fl);
init_flash_storage((char *) CONNECTION_INFO_FILENAME, &fl);
+ PRINTF("[PSM]: (start, len)=(0x%x, 0x%x)\r\n", fl.fl_start, fl.fl_size);
+
+ manu_dat = part_get_layout_by_id(FC_COMP_USER_APP, NULL);
+ part_to_flash_desc(manu_dat, &fl);
+ PRINTF("[Manufacture_Data]: (start, len)=(0x%x, 0x%x)\r\n", fl.fl_start, fl.fl_size);
+ pmfdat = (uint8_t *) mflash_drv_phys2log(fl.fl_start, fl.fl_size);
+ __FACTORY_DATA_START = pmfdat;
+ __FACTORY_DATA_SIZE = (uint32_t) fl.fl_size;
+
f1 = part_get_layout_by_id(FC_COMP_WLAN_FW, &history);
f2 = part_get_layout_by_id(FC_COMP_WLAN_FW, &history);
if (f1 && f2)
@@ -1127,27 +1208,72 @@ void ShellCLIMain(void * pvParameter)
}
else
{
- // PRINTF("[%s]: Wi-Fi Firmware not detected\r\n", __FUNCTION__);
+ // PRINTF("[%s]: Wi-Fi Firmware not detected\r\n", __FUNCTION__);
p = NULL;
}
if (p != NULL)
{
part_to_flash_desc(p, &fl);
wififw = (uint32_t *) mflash_drv_phys2log(fl.fl_start, fl.fl_size);
- // assert(wififw != NULL);
+ // assert(wififw != NULL);
/* First word in WIFI firmware is magic number. */
assert(*wififw == (('W' << 0) | ('L' << 8) | ('F' << 16) | ('W' << 24)));
wlan_init((const uint8_t *) (wififw + 2U), *(wififw + 1U));
- // PRINTF("[%s]: wlan_init success \r\n", __FUNCTION__);
+ // PRINTF("[%s]: wlan_init success \r\n", __FUNCTION__);
wlan_start(wlan_event_callback);
- // demo_init();
+ // demo_init();
os_thread_sleep(os_msec_to_ticks(5000));
}
+ PRINTF(" mw320 init complete! \r\n");
+
+ return;
+}
+
+void ShellCLIMain(void * pvParameter)
+{
+ const int rc = streamer_init(streamer_get());
+ if (rc != 0)
+ {
+ ChipLogError(Shell, "Streamer initialization failed: %d", rc);
+ return;
+ }
+
+ PRINTF("version: [%s] \r\n", VERSION_STR);
+
+ // Initialize the SDK components
+ init_mw320_sdk();
+
+ ChipLogDetail(Shell, "Initializing CHIP shell commands: %d", rc);
+
+ chip::Platform::MemoryInit();
+ chip::DeviceLayer::PlatformMgr().InitChipStack();
+ ConfigurationMgr().LogDeviceConfig();
+ PrintOnboardingCodes(chip::RendezvousInformationFlag::kOnNetwork);
+ chip::DeviceLayer::PlatformMgr().StartEventLoopTask();
+#if CHIP_DEVICE_CONFIG_ENABLE_WPA
+ chip::DeviceLayer::ConnectivityManagerImpl().StartWiFiManagement();
+#endif
+
+ cmd_misc_init();
+ // cmd_otcli_init();
+ ChipLogDetail(Shell, "Run CHIP shell Task: %d", rc);
// std::string qrCodeText = createSetupPayload();
// PRINTF("SetupQRCode: [%s]\r\n", qrCodeText.c_str());
+ {
+ char def_ssid[IEEEtypes_SSID_SIZE + 1];
+ char def_psk[WLAN_PSK_MAX_LENGTH];
+ load_network(def_ssid, def_psk);
- ConnectivityMgrImpl().ProvisionWiFiNetwork("nxp_matter", "nxp12345");
+ if ((strlen(def_ssid) <= 0) || (strlen(def_psk) <= 0))
+ {
+ // No saved connected_ap_info => Using the default ssid/password
+ strcpy(def_ssid, "nxp_matter");
+ strcpy(def_psk, "nxp12345");
+ }
+ PRINTF("Connecting to [%s, %s] \r\n", def_ssid, def_psk);
+ ConnectivityMgrImpl().ProvisionWiFiNetwork(def_ssid, def_psk);
+ }
// Run CHIP servers
run_update_chipsrv(chip_srv_all);
@@ -1408,6 +1534,46 @@ static void OnSwitchAttributeChangeCallback(EndpointId endpointId, AttributeId a
return;
}
+uint32_t identifyTimerCount;
+constexpr uint32_t kIdentifyTimerDelayMS = 250;
+typedef struct _Identify_Timer
+{
+ EndpointId ep;
+ uint32_t identifyTimerCount;
+} Identify_Time_t;
+Identify_Time_t id_time[MAX_ENDPOINT_COUNT];
+
+void IdentifyTimerHandler(System::Layer * systemLayer, void * appState)
+{
+ Identify_Time_t * pidt = (Identify_Time_t *) appState;
+ PRINTF(" -> %s(%u, %u) \r\n", __FUNCTION__, pidt->ep, pidt->identifyTimerCount);
+ if (pidt->identifyTimerCount)
+ {
+ pidt->identifyTimerCount--;
+ emAfWriteAttribute(pidt->ep, ZCL_IDENTIFY_CLUSTER_ID, ZCL_IDENTIFY_TIME_ATTRIBUTE_ID, (uint8_t *) &pidt->identifyTimerCount,
+ sizeof(identifyTimerCount), true, false);
+ DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(1), IdentifyTimerHandler, pidt);
+ }
+}
+
+static void OnIdentifyPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value)
+{
+ VerifyOrExit(attributeId == ZCL_IDENTIFY_TIME_ATTRIBUTE_ID,
+ ChipLogError(DeviceLayer, "[%s] Unhandled Attribute ID: '0x%04lx", TAG, attributeId));
+ VerifyOrExit((endpointId < MAX_ENDPOINT_COUNT),
+ ChipLogError(DeviceLayer, "[%s] EndPoint > max: [%u, %u]", TAG, endpointId, MAX_ENDPOINT_COUNT));
+ if (id_time[endpointId].identifyTimerCount != *value)
+ {
+ id_time[endpointId].ep = endpointId;
+ id_time[endpointId].identifyTimerCount = *value;
+ PRINTF("-> Identify: %u \r\n", id_time[endpointId].identifyTimerCount);
+ DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(1), IdentifyTimerHandler, &id_time[endpointId]);
+ }
+
+exit:
+ return;
+}
+
/*
Callback to receive the cluster modification event
*/
@@ -1426,6 +1592,9 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
// Trigger to send on/off/toggle command to the bound devices
chip::BindingManager::GetInstance().NotifyBoundClusterChanged(1, chip::app::Clusters::OnOff::Id, nullptr);
break;
+ case ZCL_IDENTIFY_CLUSTER_ID:
+ OnIdentifyPostAttributeChangeCallback(path.mEndpointId, path.mAttributeId, value);
+ break;
default:
break;
}
diff --git a/examples/build_overrides/mw320_sdk.gni b/examples/build_overrides/mw320_sdk.gni
index ea82634d810448..4aab931e39ffe3 100644
--- a/examples/build_overrides/mw320_sdk.gni
+++ b/examples/build_overrides/mw320_sdk.gni
@@ -16,4 +16,5 @@ declare_args() {
# Root directory for MW320 SDK.
mw320_sdk_build_root =
"//third_party/connectedhomeip/third_party/nxp/mw320_sdk"
+ wifi_conn_abort_support = true
}
diff --git a/examples/platform/nxp/mw320/app/ldscripts/88MW320_xx_xxxx_flash.ld b/examples/platform/nxp/mw320/app/ldscripts/88MW320_xx_xxxx_flash.ld
index 8b61eda6262a04..53bf0dc52cd4c8 100644
--- a/examples/platform/nxp/mw320/app/ldscripts/88MW320_xx_xxxx_flash.ld
+++ b/examples/platform/nxp/mw320/app/ldscripts/88MW320_xx_xxxx_flash.ld
@@ -38,7 +38,7 @@ _nvram_start = 0x480C0000;
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x1F000100, LENGTH = 0x00000180
- m_text (RX) : ORIGIN = 0x1F000280, LENGTH = 0x000EFD80
+ m_text (RX) : ORIGIN = 0x1F000280, LENGTH = 0x000FFD80
m_data0 (RW) : ORIGIN = 0x00100000, LENGTH = 0x0005EFC0
m_data1 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000
m_nvram (RW) : ORIGIN = 0x480C0044, LENGTH = 0x00000FBC
diff --git a/src/lib/shell/MainLoopMW320.cpp b/src/lib/shell/MainLoopMW320.cpp
index 1d12995542c44e..7dd9a987f013b6 100644
--- a/src/lib/shell/MainLoopMW320.cpp
+++ b/src/lib/shell/MainLoopMW320.cpp
@@ -16,14 +16,20 @@
*/
#include "streamer.h"
+#include
#include
#include
+#include
#include
#include
#include
#include
+extern "C" {
+#include "wlan.h"
+}
+
using chip::FormatCHIPError;
using chip::Shell::Engine;
using chip::Shell::streamer_get;
@@ -144,9 +150,115 @@ int TokenizeLine(char * buffer, char ** tokens, int max_tokens)
} // namespace
+extern const char * mw320_get_verstr(void);
+extern void save_network(char * ssid, char * pwd);
namespace chip {
namespace Shell {
+// ++++
+static void AtExitShell(void);
+
+static CHIP_ERROR ShutdownHandler(int argc, char ** argv)
+{
+ streamer_printf(streamer_get(), "Shutdown and Goodbye\r\n");
+ chip::Server::GetInstance().DispatchShutDownAndStopEventLoop();
+ AtExitShell();
+ exit(0);
+ return CHIP_NO_ERROR;
+}
+
+static void AtExitShell(void)
+{
+ PRINTF("%s(), PlatformMgr().Shutdown() \r\n", __FUNCTION__);
+ chip::DeviceLayer::PlatformMgr().Shutdown();
+}
+
+static CHIP_ERROR VersionHandler(int argc, char ** argv)
+{
+ // streamer_printf(streamer_get(), "CHIP %s\r\n", CHIP_VERSION_STRING);
+ streamer_printf(streamer_get(), "CHIP %s\r\n", mw320_get_verstr());
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR SetPinCodeHandler(int argc, char ** argv)
+{
+ VerifyOrReturnError(argc == 1, CHIP_ERROR_INVALID_ARGUMENT);
+ uint32_t setupPinCode = strtoull(argv[0], nullptr, 10);
+
+ ReturnErrorOnFailure(DeviceLayer::GetCommissionableDataProvider()->SetSetupPasscode(setupPinCode));
+
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR SetDefAPHandler(int argc, char ** argv)
+{
+ VerifyOrReturnError(argc == 2, CHIP_ERROR_INVALID_ARGUMENT);
+ PRINTF("[%s], [%s] \r\n", argv[0], argv[1]);
+ save_network(argv[0], argv[1]);
+
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR wlan_state_handler(int argc, char ** argv)
+{
+ enum wlan_connection_state state;
+ int result;
+ result = wlan_get_connection_state(&state);
+ if (result != WM_SUCCESS)
+ {
+ streamer_printf(streamer_get(), "Unknown WiFi State\r\n");
+ return CHIP_ERROR_INCORRECT_STATE;
+ }
+ switch (state)
+ {
+ case WLAN_DISCONNECTED:
+ streamer_printf(streamer_get(), "Wi-Fi: Disconnected\r\n");
+ break;
+ case WLAN_CONNECTING:
+ streamer_printf(streamer_get(), "Wi-Fi: connecting \r\n");
+ break;
+ case WLAN_ASSOCIATED:
+ streamer_printf(streamer_get(), "Wi-Fi: associated \r\n");
+ break;
+ case WLAN_CONNECTED:
+ streamer_printf(streamer_get(), "Wi-Fi: connected \r\n");
+ break;
+ case WLAN_SCANNING:
+ streamer_printf(streamer_get(), "Wi-Fi: scanning \r\n");
+ break;
+ default:
+ streamer_printf(streamer_get(), "Unknown WiFi State [%d] \r\n", (int) state);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR wlan_abort_handler(int argc, char ** argv)
+{
+#ifdef WIFI_CONN_ABORT_SUPPORT
+ wlan_abort_connect();
+#endif // WIFI_CONN_ABORT_SUPPORT
+ return CHIP_NO_ERROR;
+}
+
+static void RegisterMetaCommands(void)
+{
+ static shell_command_t sCmds[] = {
+ { &ShutdownHandler, "shutdown", "Exit the shell application" },
+ { &VersionHandler, "version", "Output the software version" },
+ { &SetPinCodeHandler, "pincode", "Set the pin code" },
+ { &SetDefAPHandler, "set_defap", "Set default AP SSID/PWD" },
+ { &wlan_state_handler, "wlan-stat", "Check the wifi status" },
+ { &wlan_abort_handler, "wlan-abort", "Abort the scan/reconnect" },
+ };
+
+ std::atexit(AtExitShell);
+
+ Engine::Root().RegisterCommands(sCmds, ArraySize(sCmds));
+}
+
+// ----
+
void Engine::RunMainLoop()
{
CHIP_ERROR retval;
@@ -155,6 +267,7 @@ void Engine::RunMainLoop()
char line[CHIP_SHELL_MAX_LINE_SIZE];
Engine::Root().RegisterDefaultCommands();
+ RegisterMetaCommands();
while (true)
{
diff --git a/src/platform/nxp/mw320/BUILD.gn b/src/platform/nxp/mw320/BUILD.gn
index ad8f60c6240815..c47fc3ba8d43a8 100644
--- a/src/platform/nxp/mw320/BUILD.gn
+++ b/src/platform/nxp/mw320/BUILD.gn
@@ -13,8 +13,9 @@
# limitations under the License.
import("//build_overrides/chip.gni")
-
+import("//build_overrides/mw320_sdk.gni")
import("${chip_root}/src/platform/device.gni")
+import("${mw320_sdk_build_root}/mw320_sdk.gni")
assert(chip_device_platform == "mw320")
@@ -34,6 +35,10 @@ static_library("mw320") {
"ConfigurationManagerImpl.h",
"ConnectivityManagerImpl.cpp",
"ConnectivityManagerImpl.h",
+ "ConnectivityUtils.cpp",
+ "ConnectivityUtils.h",
+ "DeviceInfoProviderImpl.cpp",
+ "DeviceInfoProviderImpl.h",
"DeviceNetworkProvisioningDelegateImpl.cpp",
"DeviceNetworkProvisioningDelegateImpl.h",
"DiagnosticDataProviderImpl.cpp",
@@ -43,6 +48,9 @@ static_library("mw320") {
"Logging.cpp",
"MW320Config.cpp",
"MW320Config.h",
+ "NetworkCommissioningDriver.h",
+ "NetworkCommissioningEthernetDriver.cpp",
+ "NetworkCommissioningWiFiDriver.cpp",
"NetworkProvisioningServerImpl.h",
"OTAImageProcessorImpl.cpp",
"OTAImageProcessorImpl.h",
@@ -53,8 +61,21 @@ static_library("mw320") {
"mw320_ota.h",
]
+ if (chip_with_factory_data == 1) {
+ sources += [
+ "FactoryDataProvider.cpp",
+ "FactoryDataProvider.h",
+ ]
+ }
+
defines = [ "MW320_LOG_ENABLED=1" ]
+ # Do Sync-connect/scan
+ defines += [ "MW320_CONNECT_SCAN_SYNC=1" ]
+
+ # Use ethernet/wifi interface for network commissioning. Default: WiFi
+ defines += [ "USE_ETHERNET_COMMISSION=0" ]
+
deps = []
public_deps = [ "${chip_root}/src/platform:platform_base" ]
diff --git a/src/platform/nxp/mw320/CHIPPlatformConfig.h b/src/platform/nxp/mw320/CHIPPlatformConfig.h
index 6c4c4c9583beae..81317c69eccaf2 100644
--- a/src/platform/nxp/mw320/CHIPPlatformConfig.h
+++ b/src/platform/nxp/mw320/CHIPPlatformConfig.h
@@ -37,15 +37,12 @@
#define ASN1_CONFIG_ERROR_TYPE int32_t
#define ASN1_CONFIG_NO_ERROR 0
-#define ASN1_CONFIG_ERROR_MIN 5000000
-#define ASN1_CONFIG_ERROR_MAX 5000999
#define ChipDie() abort()
-#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE uint16_t
-#define CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID 1
-#define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 2
-#define CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY 0x01
+#ifndef CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE
+#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE const char *
+#endif
#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_GLOBAL_MESSAGE_COUNTER 0x2
#define CHIP_CONFIG_TIME_ENABLE_CLIENT 1
diff --git a/src/platform/nxp/mw320/ConfigurationManagerImpl.cpp b/src/platform/nxp/mw320/ConfigurationManagerImpl.cpp
index ce936e476cd716..1a15b60f2b0e8c 100644
--- a/src/platform/nxp/mw320/ConfigurationManagerImpl.cpp
+++ b/src/platform/nxp/mw320/ConfigurationManagerImpl.cpp
@@ -27,6 +27,7 @@
#include
#include
+#include
#include
#include
@@ -51,6 +52,7 @@ ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance()
CHIP_ERROR ConfigurationManagerImpl::Init()
{
CHIP_ERROR err;
+ uint32_t rebootCount = 0;
bool failSafeArmed;
// Initialize the generic implementation base class.
@@ -59,19 +61,48 @@ CHIP_ERROR ConfigurationManagerImpl::Init()
SuccessOrExit(err);
// TODO: Initialize the global GroupKeyStore object here
-
+ if (MW320Config::ConfigValueExists(MW320Config::kCounterKey_RebootCount))
+ {
+ err = GetRebootCount(rebootCount);
+ SuccessOrExit(err);
+ err = StoreRebootCount(rebootCount + 1);
+ SuccessOrExit(err);
+ }
+ else
+ {
+ // The first boot after factory reset of the Node.
+ err = StoreRebootCount(1);
+ SuccessOrExit(err);
+ }
// If the fail-safe was armed when the device last shutdown, initiate a factory reset.
if (GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed)
{
ChipLogProgress(DeviceLayer, "Detected fail-safe armed on reboot; initiating factory reset");
InitiateFactoryReset();
}
+
+ if (!MW320Config::ConfigValueExists(MW320Config::kCounterKey_BootReason))
+ {
+ err = StoreBootReason(to_underlying(BootReasonType::kUnspecified));
+ SuccessOrExit(err);
+ }
+
err = CHIP_NO_ERROR;
exit:
return err;
}
+CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason)
+{
+ return ReadConfigValue(MW320Config::kCounterKey_BootReason, bootReason);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreBootReason(uint32_t bootReason)
+{
+ return WriteConfigValue(MW320Config::kCounterKey_BootReason, bootReason);
+}
+
bool ConfigurationManagerImpl::CanFactoryReset()
{
// TODO: query the application to determine if factory reset is allowed.
@@ -118,6 +149,16 @@ CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform
return err;
}
+CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount)
+{
+ return ReadConfigValue(MW320Config::kCounterKey_RebootCount, rebootCount);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount)
+{
+ return WriteConfigValue(MW320Config::kCounterKey_RebootCount, rebootCount);
+}
+
CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val)
{
return MW320Config::ReadConfigValue(key, val);
diff --git a/src/platform/nxp/mw320/ConfigurationManagerImpl.h b/src/platform/nxp/mw320/ConfigurationManagerImpl.h
index fbfa1c5d1bb152..af1f75ef3cadd2 100644
--- a/src/platform/nxp/mw320/ConfigurationManagerImpl.h
+++ b/src/platform/nxp/mw320/ConfigurationManagerImpl.h
@@ -74,6 +74,10 @@ class ConfigurationManagerImpl final : public Internal::GenericConfigurationMana
void InitiateFactoryReset(void) override;
CHIP_ERROR ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) override;
CHIP_ERROR WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) override;
+ CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override;
+ CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override;
+ CHIP_ERROR GetBootReason(uint32_t & bootReasons) override;
+ CHIP_ERROR StoreBootReason(uint32_t bootReasons) override;
// NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>.
diff --git a/src/platform/nxp/mw320/ConnectivityManagerImpl.cpp b/src/platform/nxp/mw320/ConnectivityManagerImpl.cpp
index c165fd4fc89855..a91e6551b1e932 100644
--- a/src/platform/nxp/mw320/ConnectivityManagerImpl.cpp
+++ b/src/platform/nxp/mw320/ConnectivityManagerImpl.cpp
@@ -17,17 +17,23 @@
* limitations under the License.
*/
/* this file behaves like a config.h, comes first */
+#include
#include
+#include
#include
#include
#include
#include
+#include
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
#include
#endif
+#include
+#include
+
#include
#include
#include
@@ -37,30 +43,67 @@ extern "C" {
#include "wlan.h"
void test_wlan_scan(int argc, char ** argv);
void test_wlan_add(int argc, char ** argv);
+static struct wlan_network sta_network;
}
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
#include
#endif
+// NetworkCommission++
+#include
+// NetworkCommission--
using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::System;
using namespace ::chip::TLV;
using namespace ::chip::DeviceLayer::Internal;
+using namespace ::chip::app::Clusters::GeneralDiagnostics;
+using namespace ::chip::app::Clusters::WiFiNetworkDiagnostics;
+using namespace ::chip::app::Clusters::NetworkCommissioning;
+using namespace ::chip::DeviceLayer::NetworkCommissioning;
+
+// NetworkCommission++
+namespace {
+constexpr EndpointId kNetworkCommissioningEndpointMain = 0;
+constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE;
+
+#if (USE_ETHERNET_COMMISSION == 1)
+DeviceLayer::NetworkCommissioning::Mw320EthernetDriver sEthernetDriver;
+app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointMain,
+ &sEthernetDriver);
+#else
+Mw320WiFiDriver sWiFiDriver;
+Instance sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointMain, &sWiFiDriver);
+#endif // USE_ETHERNET_COMMISSION
+} // namespace
+// NetworkCommission--
namespace chip {
namespace DeviceLayer {
ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
+uint8_t ConnectivityManagerImpl::sInterestedSSID[Internal::kMaxWiFiSSIDLength];
+uint8_t ConnectivityManagerImpl::sInterestedSSIDLen;
+// Configured SSID
+uint8_t ConnectivityManagerImpl::sCfgSSID[Internal::kMaxWiFiSSIDLength];
+uint8_t ConnectivityManagerImpl::sCfgSSIDLen;
+
+NetworkCommissioning::WiFiDriver::ScanCallback * ConnectivityManagerImpl::mpScanCallback;
+NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * ConnectivityManagerImpl::mpConnectCallback;
+
CHIP_ERROR ConnectivityManagerImpl::_Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;
+ mpConnectCallback = nullptr;
+ mpScanCallback = nullptr;
+
mWiFiStationMode = kWiFiStationMode_Disabled;
mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL;
+ sWiFiNetworkCommissioningInstance.Init();
// Initialize the generic base classes that require it.
SuccessOrExit(err);
@@ -128,7 +171,8 @@ bool ConnectivityManagerImpl::_IsWiFiStationEnabled()
bool ConnectivityManagerImpl::_IsWiFiStationConnected()
{
- bool ret = false;
+ // ToDo: Change the status to response the WiFi status honestly
+ bool ret = true;
return ret;
}
@@ -139,11 +183,171 @@ bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled()
}
void ConnectivityManagerImpl::StartWiFiManagement() {}
+
+CHIP_ERROR ConnectivityManagerImpl::CommitConfig()
+{
+ ChipLogProgress(DeviceLayer, "[mw320] save config, connected network (ToDo)");
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConnectivityManagerImpl::GetWiFiBssId(ByteSpan & value)
+{
+ int ret = wlan_get_current_network(&sta_network);
+ uint8_t macAddress[6];
+
+ if (ret == WM_SUCCESS)
+ {
+ memcpy(macAddress, sta_network.bssid, 6);
+ }
+ else
+ {
+ memset(macAddress, 0, 6);
+ }
+ ChipLogProgress(DeviceLayer, "GetWiFiBssId: %02x:%02x:%02x:%02x:%02x:%02x", macAddress[0], macAddress[1], macAddress[2],
+ macAddress[3], macAddress[4], macAddress[5]);
+ value = ByteSpan(macAddress, 6);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConnectivityManagerImpl::GetWiFiSecurityType(uint8_t & securityType)
+{
+ int ret = wlan_get_current_network(&sta_network);
+ if (ret != WM_SUCCESS)
+ {
+ // Set as no security by default
+ securityType = EMBER_ZCL_SECURITY_TYPE_NONE;
+ return CHIP_NO_ERROR;
+ }
+ switch (sta_network.security.type)
+ {
+ case WLAN_SECURITY_WEP_OPEN:
+ case WLAN_SECURITY_WEP_SHARED:
+ securityType = EMBER_ZCL_SECURITY_TYPE_WEP;
+ break;
+ case WLAN_SECURITY_WPA:
+ securityType = EMBER_ZCL_SECURITY_TYPE_WPA;
+ break;
+ case WLAN_SECURITY_WPA2:
+ securityType = EMBER_ZCL_SECURITY_TYPE_WPA2;
+ break;
+ case WLAN_SECURITY_WPA3_SAE:
+ securityType = EMBER_ZCL_SECURITY_TYPE_WPA3;
+ break;
+ case WLAN_SECURITY_NONE:
+ default: // Default: No_security
+ securityType = EMBER_ZCL_SECURITY_TYPE_NONE;
+ }
+
+ ChipLogProgress(DeviceLayer, "GetWiFiSecurityType: %u", securityType);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConnectivityManagerImpl::GetWiFiVersion(uint8_t & wiFiVersion)
+{
+ wiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11N;
+ ChipLogProgress(DeviceLayer, "GetWiFiVersion: %u", wiFiVersion);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConnectivityManagerImpl::GetConfiguredNetwork(NetworkCommissioning::Network & network)
+{
+ network.connected = true;
+ memcpy(network.networkID, sCfgSSID, sCfgSSIDLen);
+ network.networkIDLen = sCfgSSIDLen;
+
+ ChipLogDetail(DeviceLayer, "[mw320] Current connected network: (ToDo)");
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConnectivityManagerImpl::StartWiFiScan(ByteSpan ssid, NetworkCommissioning::WiFiDriver::ScanCallback * callback)
+{
+ // There is another ongoing scan request, reject the new one.
+ // ====> Do it after scan is implemented (ToDo)
+ VerifyOrReturnError(mpScanCallback == nullptr, CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrReturnError(ssid.size() <= sizeof(sInterestedSSID), CHIP_ERROR_INVALID_ARGUMENT);
+
+ CHIP_ERROR ret = CHIP_NO_ERROR;
+ memset(sInterestedSSID, 0, sizeof(sInterestedSSID));
+ memcpy(sInterestedSSID, ssid.data(), ssid.size());
+ sInterestedSSIDLen = ssid.size();
+
+ ChipLogProgress(DeviceLayer, "[mw320] initialized network scan. %u, [%s]", sInterestedSSIDLen, sInterestedSSID);
+ mpScanCallback = callback;
+
+ // Do Scan
+ if (wlan_scan(_OnWpaInterfaceScanDone))
+ {
+ ChipLogProgress(DeviceLayer, "Error: scan request failed");
+ }
+ else
+ {
+ ChipLogProgress(DeviceLayer, "Scan scheduled now...");
+ }
+
+ ChipLogProgress(DeviceLayer, "[mw320]: initialized network scan. ");
+ return ret;
+}
+
+void ConnectivityManagerImpl::UpdateNetworkStatus()
+{
+ Network configuredNetwork;
+
+ VerifyOrReturn(IsWiFiStationEnabled() && mpStatusChangeCallback != nullptr);
+
+ CHIP_ERROR err = GetConfiguredNetwork(configuredNetwork);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "Failed to get configured network when updating network status: %s", err.AsString());
+ return;
+ }
+
+ // If we have already connected to the WiFi AP, then return null to indicate a success state.
+ if (IsWiFiStationConnected())
+ {
+ mpStatusChangeCallback->OnNetworkingStatusChange(
+ Status::kSuccess, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), NullOptional);
+ return;
+ }
+
+ mpStatusChangeCallback->OnNetworkingStatusChange(
+ Status::kUnknownError, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), NullOptional);
+}
+
#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
+CHIP_ERROR
+ConnectivityManagerImpl::ConnectWiFiNetworkAsync(ByteSpan ssid, ByteSpan credentials,
+ NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * apCallback)
+{
+ CHIP_ERROR ret = CHIP_NO_ERROR;
+ char ssidStr[kMaxWiFiSSIDLength + 1u] = { 0 };
+ char keyStr[kMaxWiFiKeyLength + 1u] = { 0 };
+
+ VerifyOrReturnError(ssid.size() <= kMaxWiFiSSIDLength, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(credentials.size() <= kMaxWiFiKeyLength, CHIP_ERROR_INVALID_ARGUMENT);
+
+ // There is another ongoing connect request, reject the new one.
+ VerifyOrReturnError(mpConnectCallback == nullptr, CHIP_ERROR_INCORRECT_STATE);
+ memcpy(ssidStr, ssid.data(), ssid.size());
+ memcpy(keyStr, credentials.data(), credentials.size());
+ //
+ memcpy(sCfgSSID, ssidStr, ssid.size());
+ sCfgSSIDLen = ssid.size();
+ //
+ mpConnectCallback = apCallback;
+#if (MW320_CONNECT_SCAN_SYNC == 1)
+ if (mpConnectCallback != nullptr)
+ {
+ mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0);
+ mpConnectCallback = nullptr;
+ }
+#endif // MW320_CONNECT_SCAN_SYNC
+
+ return ret;
+}
+
CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, const char * key)
{
-#if CHIP_DEVICE_CONFIG_ENABLE_WPA
CHIP_ERROR ret = CHIP_NO_ERROR;
int ret_mcuXpresso;
char arg0[] = "wlan-add";
@@ -177,9 +381,123 @@ CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, cons
"current connection status.");
}
return ret;
-#else
- return CHIP_ERROR_NOT_IMPLEMENTED;
-#endif
+}
+
+bool ConnectivityManagerImpl::_GetBssInfo(const uint8_t sid, NetworkCommissioning::WiFiScanResponse & result)
+{
+ struct wlan_scan_result res;
+ int err;
+ err = wlan_get_scan_result(sid, &res);
+ if (err)
+ {
+ ChipLogProgress(DeviceLayer, "Error: can't get scan res %d", sid);
+ return false;
+ }
+ // => ssid
+ memset(result.ssid, 0, sizeof(result.ssid));
+ result.ssidLen = strlen(res.ssid);
+ memcpy(result.ssid, res.ssid, result.ssidLen);
+ // => bssid
+ memcpy(result.bssid, res.bssid, kWiFiBSSIDLength);
+ // => rssi
+ result.rssi = static_cast(0 - res.rssi);
+ // => band, mw320 only works in 2.4G
+ result.wiFiBand = app::Clusters::NetworkCommissioning::WiFiBand::k2g4;
+ // => channel
+ result.channel = res.channel;
+ // => security
+ if (res.wep)
+ {
+ result.security.SetRaw(EMBER_ZCL_SECURITY_TYPE_WEP);
+ }
+ else if (res.wpa)
+ {
+ result.security.SetRaw(EMBER_ZCL_SECURITY_TYPE_WPA);
+ }
+ else if ((res.wpa2) || (res.wpa2_entp))
+ {
+ result.security.SetRaw(EMBER_ZCL_SECURITY_TYPE_WPA2);
+ }
+ else if (res.wpa3_sae)
+ {
+ result.security.SetRaw(EMBER_ZCL_SECURITY_TYPE_WPA3);
+ }
+ else
+ {
+ result.security.SetRaw(EMBER_ZCL_SECURITY_TYPE_NONE);
+ }
+
+ return true;
+}
+
+/*
+ Convert the ascii string to hex string with upper case
+*/
+std::string ConnectivityManagerImpl::to_hex_string(const std::string & input)
+{
+ std::stringstream hex_stream;
+ std::string hex_upstr;
+ hex_stream << std::hex << std::internal << std::setfill('0');
+ for (auto & byte : input)
+ hex_stream << std::setw(2) << static_cast(static_cast(byte));
+ hex_upstr = hex_stream.str();
+ transform(hex_upstr.begin(), hex_upstr.end(), hex_upstr.begin(), [](unsigned char c) { return toupper(c); });
+ return hex_upstr;
+}
+
+int ConnectivityManagerImpl::_OnWpaInterfaceScanDone(unsigned int count)
+{
+ ChipLogProgress(DeviceLayer, "network scan done (%d)", count);
+ // No ap reported
+ if (count == 0)
+ {
+ ChipLogProgress(DeviceLayer, "=> no network found");
+ DeviceLayer::SystemLayer().ScheduleLambda([]() {
+ if (mpScanCallback != nullptr)
+ {
+ mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), nullptr);
+ mpScanCallback = nullptr;
+ }
+ });
+ return 0;
+ }
+
+ // Get the scan result from SDK and push to the list
+ std::vector * networkScanned = new std::vector();
+ for (uint8_t id = 0; id < count; id++)
+ {
+ WiFiScanResponse network;
+ if (_GetBssInfo(id, network))
+ {
+ std::string ascii_ssid((char *) (network.ssid));
+ std::string hex_ssid = to_hex_string(ascii_ssid);
+ if (sInterestedSSIDLen == 0)
+ {
+ networkScanned->push_back(network);
+ }
+ else if (network.ssidLen == sInterestedSSIDLen && memcmp(network.ssid, sInterestedSSID, sInterestedSSIDLen) == 0)
+ // else if ((network.ssidLen<<1) == sInterestedSSIDLen && memcmp(hex_ssid.c_str(), sInterestedSSID, sInterestedSSIDLen)
+ // == 0)
+ {
+ networkScanned->push_back(network);
+ }
+ }
+ }
+
+ DeviceLayer::SystemLayer().ScheduleLambda([networkScanned]() {
+ // Note: We cannot post a event in ScheduleLambda since std::vector is not trivial copiable. This results in the use of
+ // const_cast but should be fine for almost all cases, since we actually handled the ownership of this element to this
+ // lambda.
+ if (mpScanCallback != nullptr)
+ {
+ Mw320ScanResponseIterator iter(const_cast *>(networkScanned));
+ mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter);
+ mpScanCallback = nullptr;
+ }
+
+ delete const_cast *>(networkScanned);
+ });
+ return 0;
}
} // namespace DeviceLayer
diff --git a/src/platform/nxp/mw320/ConnectivityManagerImpl.h b/src/platform/nxp/mw320/ConnectivityManagerImpl.h
index 3966e8821a3864..2d898f7321bdfb 100644
--- a/src/platform/nxp/mw320/ConnectivityManagerImpl.h
+++ b/src/platform/nxp/mw320/ConnectivityManagerImpl.h
@@ -39,6 +39,8 @@
#else
#include
#endif
+#include
+#include
namespace chip {
namespace DeviceLayer {
@@ -72,10 +74,27 @@ class ConnectivityManagerImpl final : public ConnectivityManager,
public:
CHIP_ERROR ProvisionWiFiNetwork(const char * ssid, const char * key);
+ void
+ SetNetworkStatusChangeCallback(NetworkCommissioning::Internal::BaseDriver::NetworkStatusChangeCallback * statusChangeCallback)
+ {
+ mpStatusChangeCallback = statusChangeCallback;
+ }
+ CHIP_ERROR ConnectWiFiNetworkAsync(ByteSpan ssid, ByteSpan credentials,
+ NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * connectCallback);
+ CHIP_ERROR CommitConfig();
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
void StartWiFiManagement();
+ CHIP_ERROR GetWiFiBssId(ByteSpan & value);
+ CHIP_ERROR GetWiFiSecurityType(uint8_t & securityType);
+ CHIP_ERROR GetWiFiVersion(uint8_t & wiFiVersion);
#endif
+ CHIP_ERROR GetConfiguredNetwork(NetworkCommissioning::Network & network);
+ CHIP_ERROR StartWiFiScan(ByteSpan ssid, NetworkCommissioning::WiFiDriver::ScanCallback * callback);
+
+ static const char * GetWiFiIfName() { return "mlan0"; }
+
+ void UpdateNetworkStatus();
private:
// ===== Members that implement the ConnectivityManager abstract interface.
@@ -94,6 +113,10 @@ class ConnectivityManagerImpl final : public ConnectivityManager,
bool _IsWiFiStationConnected();
bool _IsWiFiStationApplicationControlled();
#endif
+ static std::string to_hex_string(const std::string & input);
+ static int _OnWpaInterfaceScanDone(unsigned int count);
+ static bool _GetBssInfo(const uint8_t sid, NetworkCommissioning::WiFiScanResponse & result);
+ NetworkCommissioning::Internal::BaseDriver::NetworkStatusChangeCallback * mpStatusChangeCallback = nullptr;
// ===== Members for internal use by the following friends.
@@ -106,6 +129,15 @@ class ConnectivityManagerImpl final : public ConnectivityManager,
ConnectivityManager::WiFiStationMode mWiFiStationMode;
ConnectivityManager::WiFiAPMode mWiFiAPMode;
uint32_t mWiFiStationReconnectIntervalMS;
+
+ static uint8_t sInterestedSSID[Internal::kMaxWiFiSSIDLength];
+ static uint8_t sInterestedSSIDLen;
+ // Configured SSID
+ static uint8_t sCfgSSID[Internal::kMaxWiFiSSIDLength];
+ static uint8_t sCfgSSIDLen;
+
+ static NetworkCommissioning::WiFiDriver::ScanCallback * mpScanCallback;
+ static NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * mpConnectCallback;
};
inline bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity(void)
diff --git a/src/platform/nxp/mw320/ConnectivityUtils.cpp b/src/platform/nxp/mw320/ConnectivityUtils.cpp
new file mode 100644
index 00000000000000..c6ca3a175c64e1
--- /dev/null
+++ b/src/platform/nxp/mw320/ConnectivityUtils.cpp
@@ -0,0 +1,399 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Utilities for accessing parameters of the network interface and the wireless
+ * statistics(extracted from /proc/net/wireless) on Linux platforms.
+ */
+
+#include "ConnectivityUtils.h"
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+extern "C" {
+#include "wlan.h"
+#include "wm_net.h"
+static struct wlan_network sta_network;
+}
+
+using namespace ::chip::app::Clusters::GeneralDiagnostics;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+uint16_t ConnectivityUtils::Map2400MHz(const uint8_t inChannel)
+{
+ uint16_t frequency = 0;
+
+ if (inChannel >= 1 && inChannel <= 13)
+ {
+ frequency = static_cast(2412 + ((inChannel - 1) * 5));
+ }
+ else if (inChannel == 14)
+ {
+ frequency = 2484;
+ }
+
+ return frequency;
+}
+
+uint16_t ConnectivityUtils::Map5000MHz(const uint8_t inChannel)
+{
+ uint16_t frequency = 0;
+
+ switch (inChannel)
+ {
+ case 183:
+ frequency = 4915;
+ break;
+ case 184:
+ frequency = 4920;
+ break;
+ case 185:
+ frequency = 4925;
+ break;
+ case 187:
+ frequency = 4935;
+ break;
+ case 188:
+ frequency = 4940;
+ break;
+ case 189:
+ frequency = 4945;
+ break;
+ case 192:
+ frequency = 4960;
+ break;
+ case 196:
+ frequency = 4980;
+ break;
+ case 7:
+ frequency = 5035;
+ break;
+ case 8:
+ frequency = 5040;
+ break;
+ case 9:
+ frequency = 5045;
+ break;
+ case 11:
+ frequency = 5055;
+ break;
+ case 12:
+ frequency = 5060;
+ break;
+ case 16:
+ frequency = 5080;
+ break;
+ case 34:
+ frequency = 5170;
+ break;
+ case 36:
+ frequency = 5180;
+ break;
+ case 38:
+ frequency = 5190;
+ break;
+ case 40:
+ frequency = 5200;
+ break;
+ case 42:
+ frequency = 5210;
+ break;
+ case 44:
+ frequency = 5220;
+ break;
+ case 46:
+ frequency = 5230;
+ break;
+ case 48:
+ frequency = 5240;
+ break;
+ case 52:
+ frequency = 5260;
+ break;
+ case 56:
+ frequency = 5280;
+ break;
+ case 60:
+ frequency = 5300;
+ break;
+ case 64:
+ frequency = 5320;
+ break;
+ case 100:
+ frequency = 5500;
+ break;
+ case 104:
+ frequency = 5520;
+ break;
+ case 108:
+ frequency = 5540;
+ break;
+ case 112:
+ frequency = 5560;
+ break;
+ case 116:
+ frequency = 5580;
+ break;
+ case 120:
+ frequency = 5600;
+ break;
+ case 124:
+ frequency = 5620;
+ break;
+ case 128:
+ frequency = 5640;
+ break;
+ case 132:
+ frequency = 5660;
+ break;
+ case 136:
+ frequency = 5680;
+ break;
+ case 140:
+ frequency = 5700;
+ break;
+ case 149:
+ frequency = 5745;
+ break;
+ case 153:
+ frequency = 5765;
+ break;
+ case 157:
+ frequency = 5785;
+ break;
+ case 161:
+ frequency = 5805;
+ break;
+ case 165:
+ frequency = 5825;
+ break;
+ }
+
+ return frequency;
+}
+
+uint16_t ConnectivityUtils::MapChannelToFrequency(const uint16_t inBand, const uint8_t inChannel)
+{
+ uint16_t frequency = 0;
+
+ if (inBand == kWiFi_BAND_2_4_GHZ)
+ {
+ frequency = Map2400MHz(inChannel);
+ }
+ else if (inBand == kWiFi_BAND_5_0_GHZ)
+ {
+ frequency = Map5000MHz(inChannel);
+ }
+
+ return frequency;
+}
+
+uint8_t ConnectivityUtils::MapFrequencyToChannel(const uint16_t frequency)
+{
+ if (frequency < 2412)
+ return 0;
+
+ if (frequency < 2484)
+ return (frequency - 2407) / 5;
+
+ if (frequency == 2484)
+ return 14;
+
+ return frequency / 5 - 1000;
+}
+
+/*
+double ConnectivityUtils::ConvertFrequenceToFloat(const iw_freq * in)
+{
+ double result = (double) in->m;
+
+ for (int i = 0; i < in->e; i++)
+ result *= 10;
+
+ return result;
+}
+*/
+InterfaceType ConnectivityUtils::GetInterfaceConnectionType(const char * ifname)
+{
+ // MW320 only has the wifi interface
+ InterfaceType ret = InterfaceType::EMBER_ZCL_INTERFACE_TYPE_WI_FI;
+ return ret;
+}
+
+CHIP_ERROR ConnectivityUtils::GetInterfaceHardwareAddrs(const char * ifname, uint8_t * buf, size_t bufSize)
+{
+ CHIP_ERROR err;
+ wifi_mac_addr_t mac_addr;
+
+ VerifyOrReturnError(bufSize >= 6, CHIP_ERROR_BUFFER_TOO_SMALL);
+ wifi_get_device_mac_addr(&mac_addr);
+ memcpy(buf, mac_addr.mac, 6);
+ ChipLogProgress(DeviceLayer, "GetInterfaceHardwareAddrs: [%02x:%02x:%02x:%02x:%02x:%02x]", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5]);
+ err = CHIP_NO_ERROR;
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetInterfaceIPv4Addrs(const char * ifname, uint8_t & size, NetworkInterface * ifp)
+{
+ CHIP_ERROR err;
+ uint8_t index = 0;
+ struct wlan_ip_config addr;
+ uint8_t * pipv4;
+
+ wlan_get_address(&addr);
+ memcpy(ifp->Ipv4AddressesBuffer[index], &addr.ipv4.address, kMaxIPv4AddrSize);
+ ifp->Ipv4AddressSpans[index] = ByteSpan(ifp->Ipv4AddressesBuffer[index], kMaxIPv4AddrSize);
+
+ pipv4 = (uint8_t *) &addr.ipv4.address;
+ ChipLogProgress(DeviceLayer, "GetInterfaceIPv4Addrs: [%u.%u.%u.%u]", pipv4[0], pipv4[1], pipv4[2], pipv4[3]);
+
+ index++;
+ err = CHIP_NO_ERROR;
+ size = index;
+
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetInterfaceIPv6Addrs(const char * ifname, uint8_t & size, NetworkInterface * ifp)
+{
+ CHIP_ERROR err;
+ uint8_t i;
+ uint8_t index = 0;
+ int ret;
+
+ ret = wlan_get_current_network(&sta_network);
+ if (ret != WM_SUCCESS)
+ {
+ return CHIP_NO_ERROR;
+ }
+
+ for (i = 0; i < MAX_IPV6_ADDRESSES; i++)
+ {
+ if (sta_network.ip.ipv6[i].addr_state == IP6_ADDR_INVALID)
+ {
+ continue;
+ }
+ ChipLogProgress(DeviceLayer, "\t%-13s:\t%s (%s)", ipv6_addr_type_to_desc(&(sta_network.ip.ipv6[i])),
+ inet6_ntoa(sta_network.ip.ipv6[i].address), ipv6_addr_state_to_desc(sta_network.ip.ipv6[i].addr_state));
+ memcpy(ifp->Ipv6AddressesBuffer[index], &sta_network.ip.ipv6[index].address, kMaxIPv6AddrSize);
+ ifp->Ipv6AddressSpans[index] = ByteSpan(ifp->Ipv6AddressesBuffer[index], kMaxIPv6AddrSize);
+ index++;
+ }
+
+ err = CHIP_NO_ERROR;
+ size = index;
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetWiFiInterfaceName(char * ifname, size_t bufSize)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ strncpy(ifname, "mlan0", bufSize);
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetWiFiChannelNumber(const char * ifname, uint16_t & channelNumber)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ channelNumber = wlan_get_current_channel();
+ ChipLogProgress(DeviceLayer, "GetWiFiChannelNumber: [%u]", channelNumber);
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetWiFiRssi(const char * ifname, int8_t & rssi)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ short dblevel;
+
+ wlan_get_current_rssi(&dblevel);
+
+ VerifyOrReturnError(dblevel <= INT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
+ rssi = static_cast(dblevel);
+ ChipLogProgress(DeviceLayer, "GetWiFiRssi: [%d]", rssi);
+ err = CHIP_NO_ERROR;
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetWiFiBeaconRxCount(const char * ifname, uint32_t & beaconRxCount)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ int ret;
+ wifi_pkt_stats_t stats;
+
+ ret = wifi_get_log(&stats);
+ if (ret != WM_SUCCESS)
+ {
+ ChipLogError(DeviceLayer, "wifi_get_log failed ");
+ }
+
+ beaconRxCount = stats.bcn_rcv_cnt;
+ ChipLogProgress(DeviceLayer, "GetWiFiBeaconRxCount [%ld] -> working in sdk", beaconRxCount);
+
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetWiFiBeaconLostCount(const char * ifname, uint32_t & beaconLostCount)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ int ret;
+ wifi_pkt_stats_t stats;
+
+ ret = wifi_get_log(&stats);
+ if (ret != WM_SUCCESS)
+ {
+ ChipLogError(DeviceLayer, "wifi_get_log failed ");
+ }
+
+ beaconLostCount = stats.bcn_miss_cnt;
+ ChipLogProgress(DeviceLayer, "GetWiFiBeaconLostCount [%ld] -> working in sdk", beaconLostCount);
+
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetWiFiCurrentMaxRate(const char * ifname, uint64_t & currentMaxRate)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ currentMaxRate = 24000000;
+ ChipLogProgress(DeviceLayer, "GetWiFiCurrentMaxRate: %llu", currentMaxRate);
+
+ return err;
+}
+
+CHIP_ERROR ConnectivityUtils::GetEthInterfaceName(char * ifname, size_t bufSize)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ strncpy(ifname, "mlan0", bufSize);
+ return err;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/ConnectivityUtils.h b/src/platform/nxp/mw320/ConnectivityUtils.h
new file mode 100644
index 00000000000000..24925bb2b63b08
--- /dev/null
+++ b/src/platform/nxp/mw320/ConnectivityUtils.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Utilities for accessing parameters of the network interface and the wireless
+ * statistics(extracted from /proc/net/wireless) on Linux platforms.
+ */
+
+#pragma once
+
+#include
+#include
+
+//#include /* for "caddr_t" et al */
+//#include
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+static constexpr uint16_t kWiFi_BAND_2_4_GHZ = 2400;
+static constexpr uint16_t kWiFi_BAND_5_0_GHZ = 5000;
+static constexpr char kWpaSupplicantServiceName[] = "fi.w1.wpa_supplicant1";
+static constexpr char kWpaSupplicantObjectPath[] = "/fi/w1/wpa_supplicant1";
+
+class ConnectivityUtils
+{
+public:
+ static uint16_t MapChannelToFrequency(const uint16_t inBand, const uint8_t inChannel);
+ static uint8_t MapFrequencyToChannel(const uint16_t frequency);
+ static app::Clusters::GeneralDiagnostics::InterfaceType GetInterfaceConnectionType(const char * ifname);
+ static CHIP_ERROR GetInterfaceHardwareAddrs(const char * ifname, uint8_t * buf, size_t bufSize);
+ static CHIP_ERROR GetInterfaceIPv4Addrs(const char * ifname, uint8_t & size, NetworkInterface * ifp);
+ static CHIP_ERROR GetInterfaceIPv6Addrs(const char * ifname, uint8_t & size, NetworkInterface * ifp);
+ static CHIP_ERROR GetWiFiInterfaceName(char * ifname, size_t bufSize);
+ static CHIP_ERROR GetWiFiChannelNumber(const char * ifname, uint16_t & channelNumber);
+ static CHIP_ERROR GetWiFiRssi(const char * ifname, int8_t & rssi);
+ static CHIP_ERROR GetWiFiBeaconRxCount(const char * ifname, uint32_t & beaconRxCount);
+ static CHIP_ERROR GetWiFiBeaconLostCount(const char * ifname, uint32_t & beaconLostCount);
+ static CHIP_ERROR GetWiFiCurrentMaxRate(const char * ifname, uint64_t & currentMaxRate);
+ static CHIP_ERROR GetEthInterfaceName(char * ifname, size_t bufSize);
+ // static CHIP_ERROR GetEthPHYRate(const char * ifname, app::Clusters::EthernetNetworkDiagnostics::PHYRateType & pHYRate);
+ // static CHIP_ERROR GetEthFullDuplex(const char * ifname, bool & fullDuplex);
+
+private:
+ static uint16_t Map2400MHz(const uint8_t inChannel);
+ static uint16_t Map5000MHz(const uint8_t inChannel);
+ // static double ConvertFrequenceToFloat(const iw_freq * in);
+ // static CHIP_ERROR GetWiFiParameter(int skfd, const char * ifname, int request, struct iwreq * pwrq);
+ // static CHIP_ERROR GetWiFiStats(int skfd, const char * ifname, struct iw_statistics * stats);
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/DeviceInfoProviderImpl.cpp b/src/platform/nxp/mw320/DeviceInfoProviderImpl.cpp
new file mode 100644
index 00000000000000..92be9bd5842da3
--- /dev/null
+++ b/src/platform/nxp/mw320/DeviceInfoProviderImpl.cpp
@@ -0,0 +1,383 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace chip {
+namespace DeviceLayer {
+
+namespace {
+constexpr TLV::Tag kLabelNameTag = TLV::ContextTag(0);
+constexpr TLV::Tag kLabelValueTag = TLV::ContextTag(1);
+} // anonymous namespace
+
+DeviceInfoProviderImpl & DeviceInfoProviderImpl::GetDefaultInstance()
+{
+ static DeviceInfoProviderImpl sInstance;
+ return sInstance;
+}
+
+DeviceInfoProvider::FixedLabelIterator * DeviceInfoProviderImpl::IterateFixedLabel(EndpointId endpoint)
+{
+ return new FixedLabelIteratorImpl(endpoint);
+}
+
+DeviceInfoProviderImpl::FixedLabelIteratorImpl::FixedLabelIteratorImpl(EndpointId endpoint) : mEndpoint(endpoint)
+{
+ mIndex = 0;
+}
+
+size_t DeviceInfoProviderImpl::FixedLabelIteratorImpl::Count()
+{
+ // TODO: Need to provide a script which can generate a binary file which contains device information and
+ // update the DeviceInfoProvider which can read the information from it.
+ // Now we use the hardcoded labellist.
+ return 4;
+}
+
+bool DeviceInfoProviderImpl::FixedLabelIteratorImpl::Next(FixedLabelType & output)
+{
+ bool retval = true;
+
+ // TODO: Need to provide a script which can generate a binary file which contains device information and
+ // update the DeviceInfoProvider which can read the information from it.
+ // Now we use the hardcoded labellist.
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ const char * labelPtr = nullptr;
+ const char * valuePtr = nullptr;
+
+ VerifyOrReturnError(mIndex < 4, false);
+
+ ChipLogProgress(DeviceLayer, "Get the fixed label with index:%d at endpoint:%d", mIndex, mEndpoint);
+
+ switch (mIndex)
+ {
+ case 0:
+ labelPtr = "room";
+ valuePtr = "bedroom 2";
+ break;
+ case 1:
+ labelPtr = "orientation";
+ valuePtr = "North";
+ break;
+ case 2:
+ labelPtr = "floor";
+ valuePtr = "2";
+ break;
+ case 3:
+ labelPtr = "direction";
+ valuePtr = "up";
+ break;
+ default:
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ break;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(strlen(labelPtr) <= kMaxLabelNameLength, false);
+ VerifyOrReturnError(strlen(valuePtr) <= kMaxLabelValueLength, false);
+
+ Platform::CopyString(mFixedLabelNameBuf, kMaxLabelNameLength + 1, labelPtr);
+ Platform::CopyString(mFixedLabelValueBuf, kMaxLabelValueLength + 1, valuePtr);
+
+ output.label = CharSpan::fromCharString(mFixedLabelNameBuf);
+ output.value = CharSpan::fromCharString(mFixedLabelValueBuf);
+
+ mIndex++;
+
+ retval = true;
+ }
+ else
+ {
+ retval = false;
+ }
+
+ return retval;
+}
+
+CHIP_ERROR DeviceInfoProviderImpl::SetUserLabelLength(EndpointId endpoint, size_t val)
+{
+ DefaultStorageKeyAllocator keyAlloc;
+
+ return mStorage->SyncSetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, static_cast(sizeof(val)));
+}
+
+CHIP_ERROR DeviceInfoProviderImpl::GetUserLabelLength(EndpointId endpoint, size_t & val)
+{
+ DefaultStorageKeyAllocator keyAlloc;
+ uint16_t len = static_cast(sizeof(val));
+
+ return mStorage->SyncGetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, len);
+}
+
+CHIP_ERROR DeviceInfoProviderImpl::SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel)
+{
+ DefaultStorageKeyAllocator keyAlloc;
+ uint8_t buf[UserLabelTLVMaxSize()];
+ TLV::TLVWriter writer;
+ writer.Init(buf);
+
+ TLV::TLVType outerType;
+ ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));
+ ReturnErrorOnFailure(writer.PutString(kLabelNameTag, userLabel.label));
+ ReturnErrorOnFailure(writer.PutString(kLabelValueTag, userLabel.value));
+ ReturnErrorOnFailure(writer.EndContainer(outerType));
+
+ return mStorage->SyncSetKeyValue(keyAlloc.UserLabelIndexKey(endpoint, index), buf,
+ static_cast(writer.GetLengthWritten()));
+}
+
+CHIP_ERROR DeviceInfoProviderImpl::DeleteUserLabelAt(EndpointId endpoint, size_t index)
+{
+ VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ DefaultStorageKeyAllocator keyAlloc;
+ return mStorage->SyncDeleteKeyValue(keyAlloc.UserLabelIndexKey(endpoint, index));
+}
+
+DeviceInfoProvider::UserLabelIterator * DeviceInfoProviderImpl::IterateUserLabel(EndpointId endpoint)
+{
+ return new UserLabelIteratorImpl(*this, endpoint);
+}
+
+DeviceInfoProviderImpl::UserLabelIteratorImpl::UserLabelIteratorImpl(DeviceInfoProviderImpl & provider, EndpointId endpoint) :
+ mProvider(provider), mEndpoint(endpoint)
+{
+ size_t total = 0;
+
+ ReturnOnFailure(mProvider.GetUserLabelLength(mEndpoint, total));
+ mTotal = total;
+ mIndex = 0;
+}
+
+bool DeviceInfoProviderImpl::UserLabelIteratorImpl::Next(UserLabelType & output)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrReturnError(mIndex < mTotal, false);
+
+ DefaultStorageKeyAllocator keyAlloc;
+ uint8_t buf[UserLabelTLVMaxSize()];
+ uint16_t len = static_cast(sizeof(buf));
+
+ err = mProvider.mStorage->SyncGetKeyValue(keyAlloc.UserLabelIndexKey(mEndpoint, mIndex), buf, len);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, false);
+
+ TLV::ContiguousBufferTLVReader reader;
+ reader.Init(buf);
+ err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag());
+ VerifyOrReturnError(err == CHIP_NO_ERROR, false);
+
+ TLV::TLVType containerType;
+ VerifyOrReturnError(reader.EnterContainer(containerType) == CHIP_NO_ERROR, false);
+
+ chip::CharSpan label;
+ chip::CharSpan value;
+
+ VerifyOrReturnError(reader.Next(kLabelNameTag) == CHIP_NO_ERROR, false);
+ VerifyOrReturnError(reader.Get(label) == CHIP_NO_ERROR, false);
+
+ VerifyOrReturnError(reader.Next(kLabelValueTag) == CHIP_NO_ERROR, false);
+ VerifyOrReturnError(reader.Get(value) == CHIP_NO_ERROR, false);
+
+ VerifyOrReturnError(reader.VerifyEndOfContainer() == CHIP_NO_ERROR, false);
+ VerifyOrReturnError(reader.ExitContainer(containerType) == CHIP_NO_ERROR, false);
+
+ Platform::CopyString(mUserLabelNameBuf, label);
+ Platform::CopyString(mUserLabelValueBuf, value);
+
+ output.label = CharSpan::fromCharString(mUserLabelNameBuf);
+ output.value = CharSpan::fromCharString(mUserLabelValueBuf);
+
+ mIndex++;
+
+ return true;
+}
+
+DeviceInfoProvider::SupportedLocalesIterator * DeviceInfoProviderImpl::IterateSupportedLocales()
+{
+ return new SupportedLocalesIteratorImpl();
+}
+
+size_t DeviceInfoProviderImpl::SupportedLocalesIteratorImpl::Count()
+{
+ // TODO: Need to provide a script which can generate a binary file which contains device information and
+ // update the DeviceInfoProvider which can read the information from it.
+ // Now we use the hardcoded SupportedLocales.
+ // {("en-US"), ("de-DE"), ("fr-FR"), ("en-GB"), ("es-ES"), ("zh-CN"), ("it-IT"), ("ja-JP")}
+
+ return 8;
+}
+
+bool DeviceInfoProviderImpl::SupportedLocalesIteratorImpl::Next(CharSpan & output)
+{
+ bool retval = true;
+
+ // TODO: Need to provide a script which can generate a binary file which contains device information and
+ // update the DeviceInfoProvider which can read the information from it.
+ // Now we use the hardcoded SupportedLocales.
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ const char * activeLocalePtr = nullptr;
+
+ VerifyOrReturnError(mIndex < 8, false);
+
+ switch (mIndex)
+ {
+ case 0:
+ activeLocalePtr = "en-US";
+ break;
+ case 1:
+ activeLocalePtr = "de-DE";
+ break;
+ case 2:
+ activeLocalePtr = "fr-FR";
+ break;
+ case 3:
+ activeLocalePtr = "en-GB";
+ break;
+ case 4:
+ activeLocalePtr = "es-ES";
+ break;
+ case 5:
+ activeLocalePtr = "zh-CN";
+ break;
+ case 6:
+ activeLocalePtr = "it-IT";
+ break;
+ case 7:
+ activeLocalePtr = "ja-JP";
+ break;
+ default:
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ break;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(strlen(activeLocalePtr) <= kMaxActiveLocaleLength, false);
+
+ Platform::CopyString(mActiveLocaleBuf, kMaxActiveLocaleLength + 1, activeLocalePtr);
+
+ output = CharSpan::fromCharString(mActiveLocaleBuf);
+
+ mIndex++;
+
+ retval = true;
+ }
+ else
+ {
+ retval = false;
+ }
+
+ return retval;
+}
+
+DeviceInfoProvider::SupportedCalendarTypesIterator * DeviceInfoProviderImpl::IterateSupportedCalendarTypes()
+{
+ return new SupportedCalendarTypesIteratorImpl();
+}
+
+size_t DeviceInfoProviderImpl::SupportedCalendarTypesIteratorImpl::Count()
+{
+ // TODO: Need to provide a script which can generate a binary file which contains device information and
+ // update the DeviceInfoProvider which can read the information from it.
+ // Now we use the hardcoded SupportedCalendarTypes.
+ // {("kBuddhist"), ("kChinese"), ("kCoptic"), ("kEthiopian"), ("kGregorian"), ("kHebrew"), ("kIndian"), ("kJapanese"),
+ // ("kKorean"), ("kPersian"), ("kTaiwanese"), ("kIslamic")}
+
+ return 12;
+}
+
+bool DeviceInfoProviderImpl::SupportedCalendarTypesIteratorImpl::Next(CalendarType & output)
+{
+ bool retval = true;
+
+ // TODO: Need to provide a script which can generate a binary file which contains device information and
+ // update the DeviceInfoProvider which can read the information from it.
+ // Now we use the hardcoded SupportedCalendarTypes.
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrReturnError(mIndex < 12, false);
+
+ switch (mIndex)
+ {
+ case 0:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kBuddhist;
+ break;
+ case 1:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kChinese;
+ break;
+ case 2:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kCoptic;
+ break;
+ case 3:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kEthiopian;
+ break;
+ case 4:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kGregorian;
+ break;
+ case 5:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kHebrew;
+ break;
+ case 6:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kIndian;
+ break;
+ case 7:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kJapanese;
+ break;
+ case 8:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kKorean;
+ break;
+ case 9:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kPersian;
+ break;
+ case 10:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kTaiwanese;
+ break;
+ case 11:
+ output = app::Clusters::TimeFormatLocalization::CalendarType::kIslamic;
+ break;
+ default:
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ break;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ mIndex++;
+ retval = true;
+ }
+ else
+ {
+ retval = false;
+ }
+
+ return retval;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/DeviceInfoProviderImpl.h b/src/platform/nxp/mw320/DeviceInfoProviderImpl.h
new file mode 100644
index 00000000000000..d06582f16405d5
--- /dev/null
+++ b/src/platform/nxp/mw320/DeviceInfoProviderImpl.h
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include
+#include
+//#include
+
+namespace chip {
+namespace DeviceLayer {
+
+class DeviceInfoProviderImpl : public DeviceInfoProvider
+{
+public:
+ DeviceInfoProviderImpl() = default;
+ ~DeviceInfoProviderImpl() override {}
+
+ // Iterators
+ FixedLabelIterator * IterateFixedLabel(EndpointId endpoint) override;
+ UserLabelIterator * IterateUserLabel(EndpointId endpoint) override;
+ SupportedLocalesIterator * IterateSupportedLocales() override;
+ SupportedCalendarTypesIterator * IterateSupportedCalendarTypes() override;
+
+ static DeviceInfoProviderImpl & GetDefaultInstance();
+
+protected:
+ class FixedLabelIteratorImpl : public FixedLabelIterator
+ {
+ public:
+ FixedLabelIteratorImpl(EndpointId endpoint);
+ size_t Count() override;
+ bool Next(FixedLabelType & output) override;
+ void Release() override { delete this; }
+
+ private:
+ EndpointId mEndpoint = 0;
+ size_t mIndex = 0;
+ char mFixedLabelNameBuf[kMaxLabelNameLength + 1];
+ char mFixedLabelValueBuf[kMaxLabelValueLength + 1];
+ };
+
+ class UserLabelIteratorImpl : public UserLabelIterator
+ {
+ public:
+ UserLabelIteratorImpl(DeviceInfoProviderImpl & provider, EndpointId endpoint);
+ size_t Count() override { return mTotal; }
+ bool Next(UserLabelType & output) override;
+ void Release() override { delete this; }
+
+ private:
+ DeviceInfoProviderImpl & mProvider;
+ EndpointId mEndpoint = 0;
+ size_t mIndex = 0;
+ size_t mTotal = 0;
+ char mUserLabelNameBuf[kMaxLabelNameLength + 1];
+ char mUserLabelValueBuf[kMaxLabelValueLength + 1];
+ };
+
+ class SupportedLocalesIteratorImpl : public SupportedLocalesIterator
+ {
+ public:
+ SupportedLocalesIteratorImpl() = default;
+ size_t Count() override;
+ bool Next(CharSpan & output) override;
+ void Release() override { delete this; }
+
+ private:
+ size_t mIndex = 0;
+ char mActiveLocaleBuf[kMaxActiveLocaleLength + 1];
+ };
+
+ class SupportedCalendarTypesIteratorImpl : public SupportedCalendarTypesIterator
+ {
+ public:
+ SupportedCalendarTypesIteratorImpl() = default;
+ size_t Count() override;
+ bool Next(CalendarType & output) override;
+ void Release() override { delete this; }
+
+ private:
+ size_t mIndex = 0;
+ };
+
+ CHIP_ERROR SetUserLabelLength(EndpointId endpoint, size_t val) override;
+ CHIP_ERROR GetUserLabelLength(EndpointId endpoint, size_t & val) override;
+ CHIP_ERROR SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) override;
+ CHIP_ERROR DeleteUserLabelAt(EndpointId endpoint, size_t index) override;
+
+private:
+ static constexpr size_t UserLabelTLVMaxSize() { return TLV::EstimateStructOverhead(kMaxLabelNameLength, kMaxLabelValueLength); }
+};
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/DiagnosticDataProviderImpl.cpp b/src/platform/nxp/mw320/DiagnosticDataProviderImpl.cpp
index b13f11e8f96106..01d348567c2a2e 100644
--- a/src/platform/nxp/mw320/DiagnosticDataProviderImpl.cpp
+++ b/src/platform/nxp/mw320/DiagnosticDataProviderImpl.cpp
@@ -21,15 +21,25 @@
* for k32w0 platform.
*/
+#include
#include
#include
+#include
+#include
#include
+#include
#include
-#include
+extern "C" {
+#include "wlan.h"
+}
//#include
+using namespace ::chip;
+using namespace ::chip::app;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::DeviceLayer::Internal;
namespace chip {
namespace DeviceLayer {
@@ -79,6 +89,221 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & cu
return CHIP_NO_ERROR;
}
+CHIP_ERROR DiagnosticDataProviderImpl::ResetWatermarks()
+{
+ // If implemented, the server SHALL set the value of the CurrentHeapHighWatermark attribute to the
+ // value of the CurrentHeapUsed.
+
+ // On Linux, the write operation is non-op since we always rely on the mallinfo system
+ // function to get the current heap memory.
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount)
+{
+ uint32_t count = 0;
+
+ CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count);
+
+ if (err == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
+ rebootCount = static_cast(count);
+ }
+ return err;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason)
+{
+ uint32_t reason = 0;
+
+ CHIP_ERROR err = ConfigurationMgr().GetBootReason(reason);
+
+ if (err == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(reason <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
+ bootReason = static_cast(reason);
+ }
+
+ return err;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetActiveHardwareFaults(GeneralFaults & hardwareFaults)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetActiveRadioFaults(GeneralFaults & radioFaults)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetActiveNetworkFaults(GeneralFaults & networkFaults)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp)
+{
+ NetworkInterface * ifp = new NetworkInterface();
+ uint8_t size = 0;
+
+ strncpy(ifp->Name, "mlan0", Inet::InterfaceId::kMaxIfNameLength);
+ ifp->Name[Inet::InterfaceId::kMaxIfNameLength - 1] = '\0';
+ ifp->name = CharSpan::fromCharString(ifp->Name);
+ ifp->isOperational = true;
+ ifp->type = EMBER_ZCL_INTERFACE_TYPE_WI_FI;
+ ifp->offPremiseServicesReachableIPv4.SetNull();
+ ifp->offPremiseServicesReachableIPv6.SetNull();
+ if (ConnectivityUtils::GetInterfaceIPv4Addrs("", size, ifp) == CHIP_NO_ERROR)
+ {
+ if (size > 0)
+ {
+ ifp->IPv4Addresses = DataModel::List(ifp->Ipv4AddressSpans, size);
+ }
+ }
+ if (ConnectivityUtils::GetInterfaceIPv6Addrs("", size, ifp) == CHIP_NO_ERROR)
+ {
+ if (size > 0)
+ {
+ ifp->IPv6Addresses = DataModel::List(ifp->Ipv6AddressSpans, size);
+ }
+ }
+ ifp->Next = nullptr;
+ *netifpp = ifp;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNumber)
+{
+ return ConnectivityUtils::GetWiFiChannelNumber(ConnectivityMgrImpl().GetWiFiIfName(), channelNumber);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi)
+{
+ return ConnectivityUtils::GetWiFiRssi(ConnectivityMgrImpl().GetWiFiIfName(), rssi);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconRxCount(uint32_t & beaconRxCount)
+{
+ return ConnectivityUtils::GetWiFiBeaconLostCount(ConnectivityMgrImpl().GetWiFiIfName(), beaconRxCount);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconLostCount)
+{
+ return ConnectivityUtils::GetWiFiBeaconLostCount(ConnectivityMgrImpl().GetWiFiIfName(), beaconLostCount);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount)
+{
+#ifdef GET_FROM_SDK
+ int ret;
+ wifi_pkt_stats_t stats;
+
+ ret = wifi_get_log(&stats);
+ if (ret != WM_SUCCESS)
+ {
+ ChipLogError(DeviceLayer, "wifi_get_log failed ");
+ }
+ packetMulticastRxCount = stats.mcast_rx_frame;
+#else
+ packetMulticastRxCount = 0;
+#endif // GET_FROM_SDK
+ ChipLogProgress(DeviceLayer, "GetWiFiPacketMulticastRxCount: %lu ", packetMulticastRxCount);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount)
+{
+#ifdef GET_FROM_SDK
+ int ret;
+ wifi_pkt_stats_t stats;
+
+ ret = wifi_get_log(&stats);
+ if (ret != WM_SUCCESS)
+ {
+ ChipLogError(DeviceLayer, "wifi_get_log failed ");
+ }
+
+ packetMulticastTxCount = stats.mcast_tx_frame;
+#else
+ packetMulticastTxCount = 0;
+#endif // GET_FROM_SDK
+ ChipLogProgress(DeviceLayer, "GetWiFiPacketMulticastTxCount: %lu ", packetMulticastTxCount);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount)
+{
+ // => Not support in SDK yet
+ packetUnicastRxCount = 0;
+ ChipLogProgress(DeviceLayer, "GetWiFiPacketUnicastRxCount: %lu (ToDo)", packetUnicastRxCount);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount)
+{
+#ifdef GET_FROM_SDK
+ int ret;
+ wifi_pkt_stats_t stats;
+
+ ret = wifi_get_log(&stats);
+ if (ret != WM_SUCCESS)
+ {
+ ChipLogError(DeviceLayer, "wifi_get_log failed ");
+ }
+
+ packetUnicastTxCount = stats.tx_frame;
+#else
+ packetUnicastTxCount = 0;
+#endif // #ifdef GET_FROM_SDK
+ ChipLogProgress(DeviceLayer, "GetWiFiPacketUnicastTxCount: %lu", packetUnicastTxCount);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate)
+{
+ return ConnectivityUtils::GetWiFiCurrentMaxRate(ConnectivityMgrImpl().GetWiFiIfName(), currentMaxRate);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiOverrunCount(uint64_t & overrunCount)
+{
+ overrunCount = 0;
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::ResetWiFiNetworkDiagnosticsCounts()
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiVersion(uint8_t & wiFiVersion)
+{
+ return ConnectivityMgrImpl().GetWiFiVersion(wiFiVersion);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBssId(ByteSpan & value)
+{
+ return ConnectivityMgrImpl().GetWiFiBssId(value);
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiSecurityType(uint8_t & securityType)
+{
+ return ConnectivityMgrImpl().GetWiFiSecurityType(securityType);
+}
+
DiagnosticDataProvider & GetDiagnosticDataProviderImpl()
{
return DiagnosticDataProviderImpl::GetDefaultInstance();
diff --git a/src/platform/nxp/mw320/DiagnosticDataProviderImpl.h b/src/platform/nxp/mw320/DiagnosticDataProviderImpl.h
index ab6e1ed09bb8d4..939a692fcf4baf 100644
--- a/src/platform/nxp/mw320/DiagnosticDataProviderImpl.h
+++ b/src/platform/nxp/mw320/DiagnosticDataProviderImpl.h
@@ -39,9 +39,39 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider
// ===== Methods that implement the PlatformManager abstract interface.
+ bool SupportsWatermarks() override { return true; }
CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override;
CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override;
CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override;
+ CHIP_ERROR ResetWatermarks() override;
+
+ CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override;
+ CHIP_ERROR GetUpTime(uint64_t & upTime) override;
+ CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
+ CHIP_ERROR GetBootReason(BootReasonType & bootReason) override;
+
+ CHIP_ERROR GetActiveHardwareFaults(GeneralFaults & hardwareFaults) override;
+ CHIP_ERROR GetActiveRadioFaults(GeneralFaults & radioFaults) override;
+ CHIP_ERROR GetActiveNetworkFaults(GeneralFaults & networkFaults) override;
+
+ CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override;
+
+ // Wi-Fi Diagnostics
+ CHIP_ERROR GetWiFiChannelNumber(uint16_t & channelNumber) override;
+ CHIP_ERROR GetWiFiRssi(int8_t & rssi) override;
+ CHIP_ERROR GetWiFiBeaconRxCount(uint32_t & beaconRxCount) override;
+ CHIP_ERROR GetWiFiBeaconLostCount(uint32_t & beaconLostCount) override;
+ CHIP_ERROR GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) override;
+ CHIP_ERROR GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) override;
+ CHIP_ERROR GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) override;
+ CHIP_ERROR GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) override;
+ CHIP_ERROR GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) override;
+ CHIP_ERROR GetWiFiOverrunCount(uint64_t & overrunCount) override;
+ CHIP_ERROR ResetWiFiNetworkDiagnosticsCounts() override;
+
+ CHIP_ERROR GetWiFiVersion(uint8_t & wiFiVersion) override;
+ CHIP_ERROR GetWiFiBssId(ByteSpan & value) override;
+ CHIP_ERROR GetWiFiSecurityType(uint8_t & securityType) override;
};
/**
diff --git a/src/platform/nxp/mw320/FactoryDataProvider.cpp b/src/platform/nxp/mw320/FactoryDataProvider.cpp
new file mode 100644
index 00000000000000..a511c3d9f83e7f
--- /dev/null
+++ b/src/platform/nxp/mw320/FactoryDataProvider.cpp
@@ -0,0 +1,321 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FactoryDataProvider.h"
+#include "CHIPDevicePlatformConfig.h"
+#include
+#include
+#include
+#include
+#include
+
+/* Grab symbol for the base address from the linker file. */
+extern uint8_t * __FACTORY_DATA_START;
+extern uint32_t __FACTORY_DATA_SIZE;
+
+namespace chip {
+namespace {
+
+CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair)
+{
+ Crypto::P256SerializedKeypair serialized_keypair;
+ ReturnErrorOnFailure(serialized_keypair.SetLength(privateKey.size() + publicKey.size()));
+ memcpy(serialized_keypair.Bytes(), publicKey.data(), publicKey.size());
+ memcpy(serialized_keypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size());
+ return keypair.Deserialize(serialized_keypair);
+}
+} // namespace
+
+namespace DeviceLayer {
+
+FactoryDataProvider & FactoryDataProvider::GetDefaultInstance()
+{
+ static FactoryDataProvider sInstance;
+ return sInstance;
+}
+
+static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len =
+ BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1;
+static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1;
+static constexpr size_t kMaxCertLen = 600;
+static constexpr size_t kMaxKeyLen = 32;
+
+static constexpr size_t kVerifierId = 1;
+static constexpr size_t kSaltId = 2;
+static constexpr size_t kIcId = 3;
+static constexpr size_t kDacPrivateKeyId = 4;
+static constexpr size_t kDacCertificateId = 5;
+static constexpr size_t kPaiCertificateId = 6;
+static constexpr size_t kDiscriminatorId = 7;
+
+static constexpr size_t kMaxId = kDiscriminatorId;
+static uint16_t maxLengths[kMaxId + 1];
+
+static uint8_t ReadDataMemCpy(uint16_t num, uint32_t src, uint8_t * dst)
+{
+ memcpy(dst, (void *) (src), num);
+ return 0;
+}
+
+// format: [type:1][len:2][data:var]
+CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length)
+{
+ CHIP_ERROR err = CHIP_ERROR_NOT_FOUND;
+ uint8_t * addr = __FACTORY_DATA_START;
+ uint8_t type = 0;
+
+ while (addr < (__FACTORY_DATA_START + __FACTORY_DATA_SIZE))
+ {
+ type = addr[0];
+ length = *((uint16_t *) (addr + 1));
+
+ if ((type > kMaxId) || (length > maxLengths[type]))
+ {
+ break;
+ }
+
+ if (searchedType == type)
+ {
+ if (bufLength < length)
+ {
+ err = CHIP_ERROR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ memcpy(pBuf, addr + 3, length);
+ err = CHIP_NO_ERROR;
+ }
+ break;
+ }
+ else
+ {
+ /* Jump past 2 bytes of length and then use length to jump to next data */
+ addr = addr + 3 + length;
+ }
+ }
+
+ return err;
+}
+
+CHIP_ERROR FactoryDataProvider::Init()
+{
+ maxLengths[kVerifierId] = kSpake2pSerializedVerifier_MaxBase64Len;
+ maxLengths[kSaltId] = kSpake2pSalt_MaxBase64Len;
+ maxLengths[kIcId] = 4;
+ maxLengths[kDacPrivateKeyId] = kMaxKeyLen;
+ maxLengths[kDacCertificateId] = kMaxCertLen;
+ maxLengths[kPaiCertificateId] = kMaxCertLen;
+ maxLengths[kDiscriminatorId] = 4;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & outBuffer)
+{
+ constexpr uint8_t kCdForAllExamples[] = CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION;
+
+ return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer);
+}
+
+CHIP_ERROR FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer)
+{
+ uint16_t certificateSize = 0;
+
+ ReturnErrorOnFailure(SearchForId(kDacCertificateId, outBuffer.data(), outBuffer.size(), certificateSize));
+ outBuffer.reduce_size(certificateSize);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer)
+{
+ uint16_t certificateSize = 0;
+
+ ReturnErrorOnFailure(SearchForId(kPaiCertificateId, outBuffer.data(), outBuffer.size(), certificateSize));
+ outBuffer.reduce_size(certificateSize);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
+{
+ CHIP_ERROR res;
+
+ Crypto::P256ECDSASignature signature;
+ Crypto::P256Keypair keypair;
+ VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ // In a non-exemplary implementation, the public key is not needed here. It is used here merely because
+ // Crypto::P256Keypair is only (currently) constructable from raw keys if both private/public keys are present.
+
+ Crypto::P256PublicKey dacPublicKey;
+ uint8_t certBuf[kMaxCertLen];
+ MutableByteSpan dacCertSpan(certBuf);
+ uint16_t certificateSize = 0;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ err = SearchForId(kDacCertificateId, dacCertSpan.data(), dacCertSpan.size(), certificateSize);
+ ReturnErrorOnFailure(err);
+ dacCertSpan.reduce_size(certificateSize);
+
+#if (!defined(MBEDTLS_USE_TINYCRYPT))
+ /* Skip fetching public key if using tiny_crypt
+ In mbedtls_pk_parse_subpubkey(),
+ If using tiny_crypt => pk_get_ueccpubkey()
+ If not using tiny_crypt => pk_get_ecpubkey() (needed)
+ */
+ /* Extract Public Key of DAC certificate from itself */
+ err = Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey);
+ ReturnErrorOnFailure(err);
+#endif // MBEDTLS_USE_TINYCRYPT
+
+ /* Get private key of DAC certificate from reserved section */
+ uint8_t keyBuf[kMaxKeyLen];
+ MutableByteSpan dacPrivateKeySpan(keyBuf);
+ uint16_t keySize = 0;
+ ReturnErrorOnFailure(SearchForId(kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize));
+ dacPrivateKeySpan.reduce_size(keySize);
+
+ ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(dacPrivateKeySpan.data(), dacPrivateKeySpan.size()),
+ ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair));
+ ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature));
+
+ res = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
+ return res;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
+{
+ uint32_t discriminator = 0;
+ uint16_t temp = 0;
+
+ ReturnErrorOnFailure(SearchForId(kDiscriminatorId, (uint8_t *) &discriminator, sizeof(discriminator), temp));
+ setupDiscriminator = (uint16_t)(discriminator & 0x0000FFFF);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SetSetupDiscriminator(uint16_t setupDiscriminator)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
+{
+ uint16_t temp = 0;
+
+ return SearchForId(kIcId, (uint8_t *) &iterationCount, sizeof(iterationCount), temp);
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf)
+{
+ char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 };
+ uint16_t saltB64Len = 0;
+
+ ReturnErrorOnFailure(SearchForId(kSaltId, (uint8_t *) (&saltB64[0]), sizeof(saltB64), saltB64Len));
+ size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast(saltB64));
+
+ ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(saltBuf.data(), saltB64, saltLen);
+ saltBuf.reduce_size(saltLen);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
+{
+ char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 };
+ uint16_t verifierB64Len = 0;
+
+ ReturnErrorOnFailure(SearchForId(kVerifierId, (uint8_t *) &verifierB64[0], sizeof(verifierB64), verifierB64Len));
+
+ verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast(verifierB64));
+ ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(verifierBuf.data(), verifierB64, verifierLen);
+ verifierBuf.reduce_size(verifierLen);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSetupPasscode(uint32_t & setupPasscode)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
+CHIP_ERROR FactoryDataProvider::GetVendorName(char * buf, size_t bufSize)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetVendorId(uint16_t & vendorId)
+{
+ vendorId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductName(char * buf, size_t bufSize)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductId(uint16_t & productId)
+{
+ productId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
+{
+#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID)
+#endif
+
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER */
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/FactoryDataProvider.h b/src/platform/nxp/mw320/FactoryDataProvider.h
new file mode 100644
index 00000000000000..dcba9cd16a383c
--- /dev/null
+++ b/src/platform/nxp/mw320/FactoryDataProvider.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include
+#include
+#include
+
+#include "CHIPPlatformConfig.h"
+
+namespace chip {
+namespace DeviceLayer {
+
+/**
+ * @brief This class provides Commissionable data, Device Attestation Credentials,
+ * and Device Instance Info.
+ */
+
+class FactoryDataProvider : public CommissionableDataProvider,
+ public Credentials::DeviceAttestationCredentialsProvider
+#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
+ ,
+ public DeviceInstanceInfoProvider
+#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
+{
+public:
+ static FactoryDataProvider & GetDefaultInstance();
+
+ FactoryDataProvider() {}
+
+ CHIP_ERROR Init();
+
+ // ===== Members functions that implement the CommissionableDataProvider
+ CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
+ CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override;
+ CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
+ CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
+ CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
+ CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override;
+ CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override;
+
+ // ===== Members functions that implement the DeviceAttestationCredentialsProvider
+ CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override;
+ CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override;
+ CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override;
+ CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override;
+ CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
+ // ===== Members functions that implement the GenericDeviceInstanceInfoProvider
+ CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
+ CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetProductId(uint16_t & productId) override;
+ CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
+ CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
+
+ CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
+};
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/MW320Config.cpp b/src/platform/nxp/mw320/MW320Config.cpp
index 613e92b93bddbd..1a842dfad4361f 100644
--- a/src/platform/nxp/mw320/MW320Config.cpp
+++ b/src/platform/nxp/mw320/MW320Config.cpp
@@ -32,45 +32,75 @@
#include "FreeRTOS.h"
+extern "C" {
+#include
+}
+
namespace chip {
namespace DeviceLayer {
namespace Internal {
+#define kMaxKeyValueBytes 2048
+#define keyNameBytes 128
+
CHIP_ERROR MW320Config::Init()
{
-
return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::ReadConfigValue(Key key, bool & val)
{
- CHIP_ERROR err;
+ uint32_t ret;
+ uint32_t read_size = sizeof(bool);
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
- err = CHIP_NO_ERROR;
- err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+ ret = ::get_saved_wifi_network(keyname, (uint8_t *) (&val), &read_size);
+ VerifyOrReturnError(ret == 0, CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
- return err;
+ return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::ReadConfigValue(Key key, uint32_t & val)
{
- CHIP_ERROR err = CHIP_NO_ERROR;
- err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+ uint32_t ret;
+ uint32_t read_size = sizeof(uint32_t);
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
- return err;
+ ret = ::get_saved_wifi_network(keyname, (uint8_t *) (&val), &read_size);
+ VerifyOrReturnError(ret == 0, CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
+
+ return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::ReadConfigValue(Key key, uint64_t & val)
{
- CHIP_ERROR err = CHIP_NO_ERROR;
+ uint32_t ret;
+ uint32_t read_size = sizeof(uint64_t);
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
- return err;
+ ret = ::get_saved_wifi_network(keyname, (uint8_t *) (&val), &read_size);
+ VerifyOrReturnError(ret == 0, CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
+
+ return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
CHIP_ERROR err = CHIP_NO_ERROR;
- err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+ uint32_t ret;
+ uint32_t read_size = bufSize;
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+
+ ret = ::get_saved_wifi_network(keyname, (uint8_t *) (buf), &read_size);
+ VerifyOrReturnError(ret == 0, CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
+ if (read_size <= bufSize)
+ {
+ outLen = read_size;
+ }
return err;
}
@@ -78,10 +108,16 @@ CHIP_ERROR MW320Config::ReadConfigValueStr(Key key, char * buf, size_t bufSize,
CHIP_ERROR MW320Config::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
CHIP_ERROR err = CHIP_NO_ERROR;
-
- if (buf == NULL)
+ uint32_t ret;
+ uint32_t read_size = bufSize;
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+
+ ret = ::get_saved_wifi_network(keyname, (uint8_t *) (buf), &read_size);
+ VerifyOrReturnError(ret == 0, CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
+ if (read_size <= bufSize)
{
- return CHIP_ERROR_INVALID_ARGUMENT;
+ outLen = read_size;
}
return err;
@@ -96,19 +132,28 @@ CHIP_ERROR MW320Config::ReadConfigValueCounter(const char * index, uint32_t & va
CHIP_ERROR MW320Config::WriteConfigValue(Key key, bool val)
{
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ::save_wifi_network(keyname, (uint8_t *) &val, sizeof(bool));
return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::WriteConfigValue(Key key, uint32_t val)
{
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ::save_wifi_network(keyname, (uint8_t *) &val, sizeof(uint32_t));
return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::WriteConfigValue(Key key, uint64_t val)
{
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ::save_wifi_network(keyname, (uint8_t *) &val, sizeof(uint64_t));
return CHIP_NO_ERROR;
}
@@ -119,28 +164,48 @@ CHIP_ERROR MW320Config::WriteConfigValueStr(Key key, const char * str)
CHIP_ERROR MW320Config::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ::save_wifi_network(keyname, (uint8_t *) str, strLen);
return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ::save_wifi_network(keyname, (uint8_t *) data, dataLen);
return CHIP_NO_ERROR;
}
CHIP_ERROR MW320Config::ClearConfigValue(Key key)
{
+ char keyname[keyNameBytes];
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ::reset_saved_wifi_network(keyname);
return CHIP_NO_ERROR;
}
bool MW320Config::ConfigValueExists(Key key)
{
- CHIP_ERROR err = CHIP_NO_ERROR;
+ uint32_t ret;
+ uint32_t read_size = kMaxKeyValueBytes;
+ uint8_t buf[kMaxKeyValueBytes];
+ char keyname[keyNameBytes];
- // Return true if the record was found.
- return (err == CHIP_NO_ERROR);
+ snprintf(keyname, keyNameBytes, "%08lx", key);
+ ret = ::get_saved_wifi_network(keyname, buf, &read_size);
+ if (ret == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
CHIP_ERROR MW320Config::FactoryResetConfig(void)
diff --git a/src/platform/nxp/mw320/MW320Config.h b/src/platform/nxp/mw320/MW320Config.h
index ca462a7b6674a9..fbe66f66875061 100644
--- a/src/platform/nxp/mw320/MW320Config.h
+++ b/src/platform/nxp/mw320/MW320Config.h
@@ -61,6 +61,8 @@ class MW320Config
* runtime. Retained during factory reset. */
static constexpr uint8_t kFileId_KVS = CATEGORY_BASE + 3; /**< Category containing KVS set at runtime.
* Cleared during factory reset. */
+ static constexpr uint8_t kPDMId_ChipCounter = CATEGORY_BASE + 4; /**< Category containing KVS set at runtime.
+ * Cleared during factory reset. */
using Key = uint32_t;
@@ -96,6 +98,12 @@ class MW320Config
// static constexpr Key kConfigKey_Breadcrumb = ConfigKey(kFileId_ChipConfig, 0x0D);
static constexpr Key kConfigKey_UniqueId = ConfigKey(kFileId_ChipConfig, 0x0D);
+ // CHIP Counter Keys
+ static constexpr Key kCounterKey_RebootCount = ConfigKey(kPDMId_ChipCounter, 0x00);
+ static constexpr Key kCounterKey_UpTime = ConfigKey(kPDMId_ChipCounter, 0x01);
+ static constexpr Key kCounterKey_TotalOperationalHours = ConfigKey(kPDMId_ChipCounter, 0x02);
+ static constexpr Key kCounterKey_BootReason = ConfigKey(kPDMId_ChipCounter, 0x03);
+
static constexpr Key kConfigKey_GroupKey = ConfigKey(kFileId_ChipConfig, 0x0E);
static constexpr Key kConfigKey_GroupKey0 = ConfigKey(kFileId_ChipConfig, 0x0F);
static constexpr Key kConfigKey_GroupKey1 = ConfigKey(kFileId_ChipConfig, 0x10);
diff --git a/src/platform/nxp/mw320/NetworkCommissioningDriver.h b/src/platform/nxp/mw320/NetworkCommissioningDriver.h
new file mode 100644
index 00000000000000..aa567366bfbff9
--- /dev/null
+++ b/src/platform/nxp/mw320/NetworkCommissioningDriver.h
@@ -0,0 +1,143 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace chip {
+namespace DeviceLayer {
+namespace NetworkCommissioning {
+
+template
+class Mw320ScanResponseIterator : public Iterator
+{
+public:
+ Mw320ScanResponseIterator(std::vector * apScanResponse) : mpScanResponse(apScanResponse) {}
+ size_t Count() override { return mpScanResponse != nullptr ? mpScanResponse->size() : 0; }
+ bool Next(T & item) override
+ {
+ if (mpScanResponse == nullptr || currentIterating >= mpScanResponse->size())
+ {
+ return false;
+ }
+ item = (*mpScanResponse)[currentIterating];
+ currentIterating++;
+ return true;
+ }
+ void Release() override
+ { /* nothing to do, we don't hold the ownership of the vector, and users is not expected to hold the ownership in OnFinished for
+ scan. */
+ }
+
+private:
+ size_t currentIterating = 0;
+ // Note: We cannot post a event in ScheduleLambda since std::vector is not trivial copyable.
+ std::vector * mpScanResponse;
+};
+
+class Mw320WiFiDriver final : public WiFiDriver
+{
+public:
+ class WiFiNetworkIterator final : public NetworkIterator
+ {
+ public:
+ WiFiNetworkIterator(Mw320WiFiDriver * aDriver) : driver(aDriver) {}
+ size_t Count() override;
+ bool Next(Network & item) override;
+ void Release() override { delete this; }
+ ~WiFiNetworkIterator() override = default;
+
+ private:
+ Mw320WiFiDriver * driver;
+ bool exhausted = false;
+ };
+
+ struct WiFiNetwork
+ {
+ uint8_t ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength];
+ uint8_t ssidLen = 0;
+ uint8_t credentials[DeviceLayer::Internal::kMaxWiFiKeyLength];
+ uint8_t credentialsLen = 0;
+ };
+
+ // BaseDriver
+ NetworkIterator * GetNetworks() override { return new WiFiNetworkIterator(this); }
+ CHIP_ERROR Init(BaseDriver::NetworkStatusChangeCallback * networkStatusChangeCallback) override;
+ void Shutdown() override;
+
+ // WirelessDriver
+ uint8_t GetMaxNetworks() override { return 1; }
+ uint8_t GetScanNetworkTimeoutSeconds() override { return 10; }
+ uint8_t GetConnectNetworkTimeoutSeconds() override { return 20; }
+
+ CHIP_ERROR CommitConfiguration() override;
+ CHIP_ERROR RevertConfiguration() override;
+
+ Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override;
+ Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override;
+ void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override;
+
+ // WiFiDriver
+ Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText,
+ uint8_t & outNetworkIndex) override;
+ void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override;
+
+private:
+ bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId);
+
+ WiFiNetwork mSavedNetwork;
+ WiFiNetwork mStagingNetwork;
+ Optional mScanStatus;
+};
+
+class Mw320EthernetDriver final : public EthernetDriver
+{
+public:
+ struct EthernetNetworkIterator final : public NetworkIterator
+ {
+ EthernetNetworkIterator() = default;
+ size_t Count() override { return interfaceNameLen > 0 ? 1 : 0; }
+ bool Next(Network & item) override
+ {
+ if (exhausted)
+ {
+ return false;
+ }
+ exhausted = true;
+ memcpy(item.networkID, interfaceName, interfaceNameLen);
+ item.networkIDLen = interfaceNameLen;
+ item.connected = true;
+ return true;
+ }
+ void Release() override { delete this; }
+ ~EthernetNetworkIterator() override = default;
+
+ // Public, but cannot be accessed via NetworkIterator interface.
+ uint8_t interfaceName[kMaxNetworkIDLen];
+ uint8_t interfaceNameLen = 0;
+ bool exhausted = false;
+ };
+
+ uint8_t GetMaxNetworks() override { return 1; };
+ NetworkIterator * GetNetworks() override;
+};
+
+} // namespace NetworkCommissioning
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/NetworkCommissioningEthernetDriver.cpp b/src/platform/nxp/mw320/NetworkCommissioningEthernetDriver.cpp
new file mode 100644
index 00000000000000..f5d443b5983fc6
--- /dev/null
+++ b/src/platform/nxp/mw320/NetworkCommissioningEthernetDriver.cpp
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+using namespace chip::DeviceLayer::Internal;
+
+namespace chip {
+namespace DeviceLayer {
+namespace NetworkCommissioning {
+
+NetworkIterator * Mw320EthernetDriver::GetNetworks()
+{
+ auto ret = new EthernetNetworkIterator();
+ ConnectivityUtils::GetEthInterfaceName(SafePointerCast(ret->interfaceName), sizeof(ret->interfaceName));
+ ret->interfaceNameLen = static_cast(strnlen(SafePointerCast(ret->interfaceName), sizeof(ret->interfaceName)));
+ return ret;
+}
+
+} // namespace NetworkCommissioning
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/NetworkCommissioningWiFiDriver.cpp b/src/platform/nxp/mw320/NetworkCommissioningWiFiDriver.cpp
new file mode 100644
index 00000000000000..10b361c8fbd35d
--- /dev/null
+++ b/src/platform/nxp/mw320/NetworkCommissioningWiFiDriver.cpp
@@ -0,0 +1,230 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#include
+//#include
+#include
+#include
+
+#include
+#include
+#include
+
+using namespace chip;
+using namespace chip::Thread;
+
+namespace chip {
+namespace DeviceLayer {
+namespace NetworkCommissioning {
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WPA
+// TODO(#14172): Here, most interfaces are just calling ConnectivityManager interfaces, this is because the ConnectivityProvides
+// some bootstrap code for the wpa_supplicant. However, we can wrap the wpa_supplicant dbus api directly (and remove the related
+// code in ConnectivityManagerImpl).
+namespace {
+constexpr char kWiFiSSIDKeyName[] = "wifi-ssid";
+constexpr char kWiFiCredentialsKeyName[] = "wifi-pass";
+} // namespace
+
+// NOTE: For WiFiDriver, we uses two network configs, one is mSavedNetwork, and another is mStagingNetwork, during init, it will
+// load the network config from k-v storage, and loads it into both mSavedNetwork and mStagingNetwork. When updating the networks,
+// all changed are made on the staging network, and when the network is committed, it will update the mSavedNetwork to
+// mStagingNetwork and persist the changes.
+
+// NOTE: LinuxWiFiDriver uses network config with empty ssid (ssidLen = 0) for empty network config.
+
+// NOTE: For now, the LinuxWiFiDriver only supports one network, this can be fixed by using the wpa_supplicant API directly (then
+// wpa_supplicant will manage the networks for us.)
+
+CHIP_ERROR Mw320WiFiDriver::Init(BaseDriver::NetworkStatusChangeCallback * networkStatusChangeCallback)
+{
+ CHIP_ERROR err;
+ size_t ssidLen = 0;
+ size_t credentialsLen = 0;
+
+ err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, mSavedNetwork.credentials,
+ sizeof(mSavedNetwork.credentials), &credentialsLen);
+ if (err == CHIP_ERROR_KEY_NOT_FOUND)
+ {
+ return CHIP_NO_ERROR;
+ }
+ err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid), &ssidLen);
+ if (err == CHIP_ERROR_KEY_NOT_FOUND)
+ {
+ return CHIP_NO_ERROR;
+ }
+
+ mSavedNetwork.credentialsLen = credentialsLen;
+ mSavedNetwork.ssidLen = ssidLen;
+
+ mStagingNetwork = mSavedNetwork;
+
+ ConnectivityMgrImpl().SetNetworkStatusChangeCallback(networkStatusChangeCallback);
+ return CHIP_NO_ERROR;
+}
+
+void Mw320WiFiDriver::Shutdown()
+{
+ ConnectivityMgrImpl().SetNetworkStatusChangeCallback(nullptr);
+}
+
+CHIP_ERROR Mw320WiFiDriver::CommitConfiguration()
+{
+ ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen));
+ ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials,
+ mStagingNetwork.credentialsLen));
+ ReturnErrorOnFailure(ConnectivityMgrImpl().CommitConfig());
+ mSavedNetwork = mStagingNetwork;
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Mw320WiFiDriver::RevertConfiguration()
+{
+ mStagingNetwork = mSavedNetwork;
+ return CHIP_NO_ERROR;
+}
+
+bool Mw320WiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId)
+{
+ return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0;
+}
+
+Status Mw320WiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText,
+ uint8_t & outNetworkIndex)
+{
+ outDebugText.reduce_size(0);
+ outNetworkIndex = 0;
+ VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded);
+
+ static_assert(sizeof(WiFiNetwork::ssid) <= std::numeric_limits::max(),
+ "Max length of WiFi ssid exceeds the limit of ssidLen field");
+ static_assert(sizeof(WiFiNetwork::credentials) <= std::numeric_limits::max(),
+ "Max length of WiFi credentials exceeds the limit of credentialsLen field");
+
+ // Do the check before setting the values, so the data is not updated on error.
+ VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange);
+ VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange);
+
+ memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size());
+ mStagingNetwork.credentialsLen = static_cast(credentials.size());
+
+ memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size());
+ mStagingNetwork.ssidLen = static_cast(ssid.size());
+
+#if (MW320_CONNECT_SCAN_SYNC == 1)
+ // ConnectNetwork(ssid, nullptr);
+ ConnectivityMgrImpl().UpdateNetworkStatus();
+#endif // MW320_CONNECT_SCAN_SYNC
+
+ return Status::kSuccess;
+}
+
+Status Mw320WiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex)
+{
+ outDebugText.reduce_size(0);
+ outNetworkIndex = 0;
+ VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
+
+ // Use empty ssid for representing invalid network
+ mStagingNetwork.ssidLen = 0;
+ return Status::kSuccess;
+}
+
+Status Mw320WiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText)
+{
+ outDebugText.reduce_size(0);
+ VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
+ // We only support one network, so reorder is actually no-op.
+
+ return Status::kSuccess;
+}
+
+void Mw320WiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Status networkingStatus = Status::kSuccess;
+
+ VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound);
+
+ ChipLogProgress(NetworkProvisioning, "LinuxNetworkCommissioningDelegate: SSID: %s", networkId.data());
+
+ err = ConnectivityMgrImpl().ConnectWiFiNetworkAsync(ByteSpan(mStagingNetwork.ssid, mStagingNetwork.ssidLen),
+ ByteSpan(mStagingNetwork.credentials, mStagingNetwork.credentialsLen),
+ callback);
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ networkingStatus = Status::kUnknownError;
+ }
+
+ if (networkingStatus != Status::kSuccess)
+ {
+ ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network: %s", chip::ErrorStr(err));
+ callback->OnResult(networkingStatus, CharSpan(), 0);
+ }
+}
+
+void Mw320WiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback)
+{
+ CHIP_ERROR err = DeviceLayer::ConnectivityMgrImpl().StartWiFiScan(ssid, callback);
+ if (err != CHIP_NO_ERROR)
+ {
+ mScanStatus.SetValue(Status::kUnknownError);
+ callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
+ }
+ else
+ {
+ // On linux platform, once "scan" is started, we can say the result will always be success.
+ mScanStatus.SetValue(Status::kSuccess);
+ }
+}
+
+size_t Mw320WiFiDriver::WiFiNetworkIterator::Count()
+{
+ return driver->mStagingNetwork.ssidLen == 0 ? 0 : 1;
+}
+
+bool Mw320WiFiDriver::WiFiNetworkIterator::Next(Network & item)
+{
+ if (exhausted || driver->mStagingNetwork.ssidLen == 0)
+ {
+ return false;
+ }
+ memcpy(item.networkID, driver->mStagingNetwork.ssid, driver->mStagingNetwork.ssidLen);
+ item.networkIDLen = driver->mStagingNetwork.ssidLen;
+ item.connected = false;
+ exhausted = true;
+
+ Network configuredNetwork;
+ CHIP_ERROR err = DeviceLayer::ConnectivityMgrImpl().GetConfiguredNetwork(configuredNetwork);
+ if (err == CHIP_NO_ERROR)
+ {
+ if (DeviceLayer::ConnectivityMgrImpl().IsWiFiStationConnected() && configuredNetwork.networkIDLen == item.networkIDLen &&
+ memcmp(configuredNetwork.networkID, item.networkID, item.networkIDLen) == 0)
+ {
+ item.connected = true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
+
+} // namespace NetworkCommissioning
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/mw320/PlatformManagerImpl.cpp b/src/platform/nxp/mw320/PlatformManagerImpl.cpp
index fa9732571ea6d6..d6751849c7a899 100644
--- a/src/platform/nxp/mw320/PlatformManagerImpl.cpp
+++ b/src/platform/nxp/mw320/PlatformManagerImpl.cpp
@@ -27,16 +27,22 @@
#include
#include
+#include
#include
#include
+#include
#include
-
-#include
+#if defined(MBEDTLS_USE_TINYCRYPT)
+#include "ecc.h"
+#endif
namespace chip {
namespace DeviceLayer {
PlatformManagerImpl PlatformManagerImpl::sInstance;
+#if defined(MBEDTLS_USE_TINYCRYPT)
+sys_mutex_t PlatformManagerImpl::rngMutexHandle = NULL;
+#endif
static int app_entropy_source(void * data, unsigned char * output, size_t len, size_t * olen)
{
@@ -53,6 +59,19 @@ CHIP_ERROR InitClock_RealTime()
return System::SystemClock().SetClock_RealTime(curTime);
}
+#if defined(MBEDTLS_USE_TINYCRYPT)
+int PlatformManagerImpl::uECC_RNG_Function(uint8_t * dest, unsigned int size)
+{
+ int res;
+
+ sys_mutex_lock(&rngMutexHandle);
+ res = (chip::Crypto::DRBG_get_bytes(dest, size) == CHIP_NO_ERROR) ? size : 0;
+ sys_mutex_unlock(&rngMutexHandle);
+
+ return res;
+}
+#endif
+
CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
{
CHIP_ERROR err;
@@ -61,12 +80,23 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
err = Internal::MW320Config::Init();
SuccessOrExit(err);
+ SetDiagnosticDataProvider(&DiagnosticDataProviderImpl::GetDefaultInstance());
+ SetDeviceInfoProvider(&DeviceInfoProviderImpl::GetDefaultInstance());
+
// Initialize LwIP.
// tcpip_init(NULL, NULL);
err = chip::Crypto::add_entropy_source(app_entropy_source, NULL, 16);
SuccessOrExit(err);
+#if defined(MBEDTLS_USE_TINYCRYPT)
+ /* Set RNG function for tinycrypt operations. */
+ err_t ret;
+ ret = sys_mutex_new(&rngMutexHandle);
+ VerifyOrExit((ERR_OK == ret), err = CHIP_ERROR_NO_MEMORY);
+ uECC_set_rng(PlatformManagerImpl::uECC_RNG_Function);
+#endif
+
// Call _InitChipStack() on the generic implementation base class
// to finish the initialization process.
// err = Internal::GenericPlatformManagerImpl_FreeRTOS::_InitChipStack();
@@ -79,5 +109,30 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
return err;
}
+void PlatformManagerImpl::_Shutdown()
+{
+ uint64_t upTime = 0;
+
+ if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR)
+ {
+ uint32_t totalOperationalHours = 0;
+
+ if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR)
+ {
+ ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast(upTime / 3600));
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node");
+ }
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot");
+ }
+
+ Internal::GenericPlatformManagerImpl_FreeRTOS::_Shutdown();
+}
+
} // namespace DeviceLayer
} // namespace chip
diff --git a/src/platform/nxp/mw320/PlatformManagerImpl.h b/src/platform/nxp/mw320/PlatformManagerImpl.h
index 16ce4a3134a8a2..56e5be604265fd 100644
--- a/src/platform/nxp/mw320/PlatformManagerImpl.h
+++ b/src/platform/nxp/mw320/PlatformManagerImpl.h
@@ -48,12 +48,23 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener
public:
// ===== Platform-specific members that may be accessed directly by the application.
- /* none so far */
+#if defined(MBEDTLS_USE_TINYCRYPT)
+ // Since the RNG callback will be called from multiple threads,
+ // use this mutex to lock/unlock the call to Matter RNG API, which
+ // uses some global variables.
+ static sys_mutex_t rngMutexHandle;
+
+ // Callback used by tinycrypt to generate random numbers.
+ // It must be set before calling any sign operations,
+ // which are used in both Matter and OT threads.
+ static int uECC_RNG_Function(uint8_t * dest, unsigned int size);
+#endif
private:
// ===== Methods that implement the PlatformManager abstract interface.
CHIP_ERROR _InitChipStack(void);
+ void _Shutdown(void);
#if CHIP_STACK_LOCK_TRACKING_ENABLED
bool _IsChipStackLockedByCurrentThread() const { return true; };
diff --git a/src/platform/nxp/mw320/args.gni b/src/platform/nxp/mw320/args.gni
index 2c5a180d833f67..d03c467fe482b3 100644
--- a/src/platform/nxp/mw320/args.gni
+++ b/src/platform/nxp/mw320/args.gni
@@ -30,7 +30,11 @@ chip_config_network_layer_ble = false
chip_inet_config_enable_ipv4 = true
chip_inet_config_enable_dns_resolver = false
+chip_detail_logging = false
chip_build_tests = false
+chip_progress_logging = true
+chip_access_control_policy_logging_verbosity = 2
+chip_enable_schema_check = true
chip_mdns = "minimal"
mbedtls_target = "${chip_root}/third_party/nxp/mw320_sdk:mbedtls"
diff --git a/third_party/nxp/mw320_sdk/BUILD.gn b/third_party/nxp/mw320_sdk/BUILD.gn
index be6fb914b1c4a6..e88f2e842e725e 100644
--- a/third_party/nxp/mw320_sdk/BUILD.gn
+++ b/third_party/nxp/mw320_sdk/BUILD.gn
@@ -31,6 +31,13 @@ group("mw320_sdk") {
public_deps = [ mw320_sdk_target ]
}
+if (chip_crypto == "tinycrypt") {
+ assert(
+ mbedtls_repo ==
+ "//third_party/connectedhomeip/third_party/nxp/libs/mbedtls",
+ "mbedtls_repo must be set to nxp mbedtls-tinycrypt library when chip_crypto == \"tinycrypt\"")
+}
+
config("mbedtls_mw320_config") {
defines = [
"MBEDTLS_CONFIG_FILE=",
@@ -62,7 +69,18 @@ config("mbedtls_mw320_config") {
# "MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED",
]
- if (mbedtls_use_tinycrypt) {
+
+ if (chip_with_factory_data == 1) {
+ defines += [
+ "MBEDTLS_X509_CRT_PARSE_C",
+ "MBEDTLS_X509_USE_C",
+ "MBEDTLS_PK_PARSE_C",
+ "MBEDTLS_PLATFORM_C",
+ ]
+ }
+
+ #if (mbedtls_use_tinycrypt) {
+ if (chip_crypto == "tinycrypt") {
defines += [
"MBEDTLS_USE_TINYCRYPT",
"MBEDTLS_OPTIMIZE_TINYCRYPT_ASM",
@@ -71,7 +89,8 @@ config("mbedtls_mw320_config") {
include_dirs = [ chip_root ]
- if (mbedtls_use_tinycrypt) {
+ #if (mbedtls_use_tinycrypt) {
+ if (chip_crypto == "tinycrypt") {
include_dirs += [ "${mbedtls_repo}/repo/include/tinycrypt" ]
}
}
@@ -79,7 +98,8 @@ config("mbedtls_mw320_config") {
mbedtls_target("mbedtls") {
import("${mw320_sdk_build_root}/mw320_sdk.gni")
- if (mbedtls_use_tinycrypt) {
+ #if (mbedtls_use_tinycrypt) {
+ if (chip_crypto == "tinycrypt") {
if (!defined(sources)) {
sources = []
}
diff --git a/third_party/nxp/mw320_sdk/mw320_sdk.gni b/third_party/nxp/mw320_sdk/mw320_sdk.gni
index 4e9de699485dcc..4bcca85aed4163 100644
--- a/third_party/nxp/mw320_sdk/mw320_sdk.gni
+++ b/third_party/nxp/mw320_sdk/mw320_sdk.gni
@@ -16,10 +16,14 @@ import("//build_overrides/jlink.gni")
import("//build_overrides/lwip.gni")
import("//build_overrides/mw320_sdk.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
declare_args() {
# Location of the mw320 SDK.
mw320_sdk_root = "${chip_root}/third_party/nxp/mw320_sdk/repo"
- mbedtls_use_tinycrypt = false
+
+ #mbedtls_use_tinycrypt = false
+ chip_with_factory_data = 0
}
assert(mw320_sdk_root != "", "mw320_sdk_root must be specified")
@@ -108,6 +112,10 @@ template("mw320_sdk") {
defines += invoker.defines
}
+ if (chip_with_factory_data == 1) {
+ defines += [ "CONFIG_CHIP_MW320_REAL_FACTORY_DATA=1" ]
+ }
+
cflags = [
"-Wno-unused-function",
"-Wno-conversion",
diff --git a/third_party/nxp/mw320_sdk/repo b/third_party/nxp/mw320_sdk/repo
index 3d93e613c05052..d42ceda74ed481 160000
--- a/third_party/nxp/mw320_sdk/repo
+++ b/third_party/nxp/mw320_sdk/repo
@@ -1 +1 @@
-Subproject commit 3d93e613c050521b36624a9f8e1c35493daa56c2
+Subproject commit d42ceda74ed4818c49ad06590de0f045b769e732