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