diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 697b2469805f5c..8a37a969eef396 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -58,6 +58,7 @@ attrMask attSizeBytes attType ATW +ATWC AudioOutput auth autoconnect @@ -138,6 +139,7 @@ CHIPCryptoPALHsm CHIPDeviceController ChipDeviceCtrl CHIPDeviceEvent +CHIPDevicePlatformConfig CHIPDevicePlatformEvent ChipEchoRequester ChipEchoResponder @@ -145,6 +147,7 @@ ChipImInitiator ChipImResponder ChipLight ChipMessageLayer +CHIPOBLE CHIPTest CHIPTool chmod @@ -797,9 +800,9 @@ ScriptBinding SDC SDHC SDK -SDK's sdkconfig SDKs +SDK's SDKTARGETSYSROOT sdl segger diff --git a/config/ameba/args.gni b/config/ameba/args.gni index 772c7a01a3582e..b3f7af63e284ab 100755 --- a/config/ameba/args.gni +++ b/config/ameba/args.gni @@ -24,12 +24,14 @@ chip_ble_project_config_include = "" mbedtls_target = "//mbedtls:mbedtls" lwip_platform = "external" -chip_build_tests = true +chip_build_tests = false chip_inet_config_enable_tcp_endpoint = true chip_inet_config_enable_udp_endpoint = true -chip_bypass_rendezvous = true -chip_config_network_layer_ble = false +chip_bypass_rendezvous = false +chip_config_network_layer_ble = true +chip_ip_commissioning = true +chip_use_clusters_for_ip_commissioning = true custom_toolchain = "//third_party/connectedhomeip/config/ameba/toolchain:ameba" diff --git a/config/ameba/chip.cmake b/config/ameba/chip.cmake index 232f040f1ab5d2..92a138d0536f7d 100644 --- a/config/ameba/chip.cmake +++ b/config/ameba/chip.cmake @@ -26,7 +26,8 @@ list( -DCONFIG_FUNCION_O0_OPTIMIZE -DDM_ODM_SUPPORT_TYPE=32 -DCHIP_DEVICE_LAYER_TARGET=Ameba - -DMBEDTLS_CONFIG_FILE=\\\"mbedtls_config.h\\\" + -DMBEDTLS_CONFIG_FILE= + -D_POSIX_REALTIME_SIGNALS ) list( @@ -96,7 +97,6 @@ string(APPEND CHIP_GN_ARGS "ameba_ar = \"arm-none-eabi-ar\"\n") string(APPEND CHIP_GN_ARGS "ameba_cc = \"arm-none-eabi-gcc\"\n") string(APPEND CHIP_GN_ARGS "ameba_cxx = \"arm-none-eabi-c++\"\n") string(APPEND CHIP_GN_ARGS "ameba_cpu = \"ameba\"\n") -string(APPEND CHIP_GN_ARGS "chip_build_tests = false\n") file(GENERATE OUTPUT ${CHIP_OUTPUT}/args.gn CONTENT ${CHIP_GN_ARGS}) diff --git a/examples/all-clusters-app/ameba/.gitignore b/examples/all-clusters-app/ameba/.gitignore old mode 100644 new mode 100755 diff --git a/examples/all-clusters-app/ameba/README.md b/examples/all-clusters-app/ameba/README.md index 766e2ba284e2d4..38615327fa233f 100644 --- a/examples/all-clusters-app/ameba/README.md +++ b/examples/all-clusters-app/ameba/README.md @@ -10,6 +10,9 @@ control. - [Building the Example Application](#building-the-example-application) - [Commissioning and cluster control](#commissioning-and-cluster-control) - [Commissioning](#commissioning) + - [Bypass mode](#bypass-mode) + - [BLE mode](#ble-mode) + - [IP mode](#ip-mode) - [Cluster control](#cluster-control) --- @@ -40,36 +43,99 @@ The CHIP demo application is supported on The output image files are stored in `out/ameba-amebad-all-clusters/asdk/image` folder. + The bootloader image files are stored in + `out/ameba-amebad-all-clusters/asdk/bootloader` folder. + - After building the application, **Ameba Image Tool** is used to flash it to Ameba board. -1. Connect your device via USB and open Ameba Image Tool. -2. Select correct serial port and set baudrate as **115200**. -3. Browse and add the corresponding image files in the Flash Download list to - the correct locations -4. Click **Download** button. +1. Connect your device via USB and open Ameba Image Tool. +2. Select correct serial port and set baudrate as **115200**. +3. Browse and add the corresponding image files in the Flash Download list to + the correct locations +4. Click **Download** button. ## Commissioning and Cluster Control -### Commissioning +## Commissioning + +There are three commissioning modes supported by Ameba platform: + +### Bypass mode + +1. In "connectedhomeip/config/ameba/args.gni" + + - set `chip_bypass_rendezvous = true` + - Set `chip_ip_commissioning = false` + - Set `chip_use_clusters_for_ip_commissioning = false` + - Set `chip_config_network_layer_ble = false` + +2. In "connectedhomeip/src/platform/Ameba/CHIPDevicePlatformConfig.h" + + - Set `#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0` + +3. Build and Flash +4. Use ATS\$ command to run all-cluster example. +5. Connect to AP using `ATW0, ATW1, ATWC` commands +6. Test with + [Chip-Tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool) + or + [Python Controller](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/python_chip_controller_building.md). + +### BLE mode + +1. In "connectedhomeip/config/ameba/args.gni" -The commissioning is carried out via WiFi. + - set `chip_bypass_rendezvous = false` + - Set `chip_ip_commissioning = false` + - Set `chip_use_clusters_for_ip_commissioning = false` + - Set `chip_config_network_layer_ble = true` -1. After download all-cluster example to Ameba board, boot up the board by - pressing the reset button. -2. Use ATW commands to setup network. -3. Use ATS\$ command to run all-cluster example. -4. Use - [standalone chip-tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool) - to communicate with the device. +2. In "connectedhomeip/src/platform/Ameba/CHIPDevicePlatformConfig.h" - $ ./chip-tool pairing bypass ${NODE_ID_TO_ASSIGN} 192.168.xx.xxx 5540 + - Set `#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1` -### Cluster Control +3. Build and Flash +4. Use ATS\$ command to run all-cluster example. +5. Test with + [Chip-Tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool) + or + [Python Controller](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/python_chip_controller_building.md). -- After successful commissioning, use the OnOff cluster command to control the - OnOff attribute. This allows you to toggle a parameter implemented by the - device to be On or Off. +### IP mode + +1. In "connectedhomeip/config/ameba/args.gni" + + - set `chip_bypass_rendezvous = false` + - Set `chip_ip_commissioning = true` + - Set `chip_use_clusters_for_ip_commissioning = true` + - Set `chip_config_network_layer_ble = false` + +2. In "connectedhomeip/src/platform/Ameba/CHIPDevicePlatformConfig.h" + + - Set `#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0` + +3. Build and Flash +4. Use ATS\$ command to run all-cluster example. +5. Connect to AP using `ATW0, ATW1, ATWC` commands +6. Test with + [Chip-Tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool) + or + [Python Controller](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/python_chip_controller_building.md). + +## Cluster Control + +After successful commissioning, use the OnOff cluster command to control the +OnOff attribute. This allows you to toggle a parameter implemented by the device +to be On or Off. + +- Via + [Chip-Tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool#using-the-client-to-send-matter-commands) $ ./chip-tool onoff on 1 $ ./chip-tool onoff off 1 + +- Via + [Python Controller](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/python_chip_controller_building.md#step-8-control-application-zcl-clusters) + + $ chip-device-ctrl > zcl OnOff Toggle 1234 1 0 diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 54e9346e65126a..2e080b3e7055fd 100755 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -38,6 +38,8 @@ list( ${chip_dir}/examples/all-clusters-app/ameba/main/chipinterface.cpp ${chip_dir}/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp ${chip_dir}/examples/all-clusters-app/ameba/main/CHIPDeviceManager.cpp + ${chip_dir}/examples/all-clusters-app/ameba/main/Globals.cpp + ${chip_dir}/examples/all-clusters-app/ameba/main/LEDWidget.cpp ) add_library( @@ -81,6 +83,7 @@ list( -DCHIP_DEVICE_LAYER_TARGET=Ameba -DUSE_ZAP_CONFIG -DCHIP_HAVE_CONFIG_H + -DMBEDTLS_CONFIG_FILE= ) list( diff --git a/examples/all-clusters-app/ameba/main/CHIPDeviceManager.cpp b/examples/all-clusters-app/ameba/main/CHIPDeviceManager.cpp index affc259453d06d..2a2d964b5d6614 100644 --- a/examples/all-clusters-app/ameba/main/CHIPDeviceManager.cpp +++ b/examples/all-clusters-app/ameba/main/CHIPDeviceManager.cpp @@ -58,6 +58,11 @@ CHIP_ERROR CHIPDeviceManager::Init(CHIPDeviceManagerCallbacks * cb) err = PlatformMgr().InitChipStack(); SuccessOrExit(err); + if (CONFIG_NETWORK_LAYER_BLE) + { + ConnectivityMgr().SetBLEAdvertisingEnabled(true); + } + err = Platform::MemoryInit(); SuccessOrExit(err); diff --git a/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp b/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp index 7a04ad85b8c82a..3860c772891b74 100644 --- a/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp +++ b/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp @@ -37,6 +37,9 @@ #include #include +#include "Globals.h" +#include "LEDWidget.h" + static const char * TAG = "app-devicecallbacks"; using namespace ::chip; @@ -51,29 +54,91 @@ constexpr uint32_t kIdentifyTimerDelayMS = 250; void DeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg) { - // TODO - // Add callback functions for different ChipDeviceEvent Types + switch (event->Type) + { + case DeviceEventType::kInternetConnectivityChange: + OnInternetConnectivityChange(event); + break; + + case DeviceEventType::kSessionEstablished: + OnSessionEstablished(event); + break; + case DeviceEventType::kInterfaceIpAddressChanged: + if ((event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) || + (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned)) + { + // MDNS server restart on any ip assignment: if link local ipv6 is configured, that + // will not trigger a 'internet connectivity change' as there is no internet + // connectivity. MDNS still wants to refresh its listening interfaces to include the + // newly selected address. + chip::app::DnssdServer::Instance().StartServer(); + } + break; + } } void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) { - ChipLogProgress(DeviceLayer, - "[%s] PostAttributeChangeCallback - Cluster ID: 0x%04x, EndPoint ID: 0x%02x, Attribute ID: 0x%04x\r\n", TAG, - clusterId, endpointId, attributeId); - switch (clusterId) { + case ZCL_ON_OFF_CLUSTER_ID: + OnOnOffPostAttributeChangeCallback(endpointId, attributeId, value); + break; + case ZCL_IDENTIFY_CLUSTER_ID: OnIdentifyPostAttributeChangeCallback(endpointId, attributeId, value); break; default: - ChipLogProgress(DeviceLayer, "[%s] Unhandled cluster ID: 0x%04x\r\n", TAG, clusterId); break; } } +void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) +{ + if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) + { + ChipLogProgress(DeviceLayer, "Server ready at: %s:%d", event->InternetConnectivityChange.address, CHIP_PORT); + chip::app::DnssdServer::Instance().StartServer(); + } + else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) + { + ChipLogProgress(DeviceLayer, "Lost IPv4 connectivity..."); + } + if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) + { + ChipLogProgress(DeviceLayer, "IPv6 Server ready..."); + chip::app::DnssdServer::Instance().StartServer(); + } + else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) + { + ChipLogProgress(DeviceLayer, "Lost IPv6 connectivity..."); + } +} + +void DeviceCallbacks::OnSessionEstablished(const ChipDeviceEvent * event) +{ + if (event->SessionEstablished.IsCommissioner) + { + ChipLogProgress(DeviceLayer, "Commissioner detected!"); + } +} + +void DeviceCallbacks::OnOnOffPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + VerifyOrExit(attributeId == ZCL_ON_OFF_ATTRIBUTE_ID, + ChipLogError(DeviceLayer, TAG, "Unhandled Attribute ID: '0x%04x", attributeId)); + VerifyOrExit(endpointId == 1 || endpointId == 2, + ChipLogError(DeviceLayer, TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); + + // At this point we can assume that value points to a bool value. + statusLED1.Set(*value); + +exit: + return; +} + void IdentifyTimerHandler(Layer * systemLayer, void * appState, CHIP_ERROR error) { if (identifyTimerCount) diff --git a/examples/all-clusters-app/ameba/main/Globals.cpp b/examples/all-clusters-app/ameba/main/Globals.cpp new file mode 100755 index 00000000000000..71d9b6c9f0b940 --- /dev/null +++ b/examples/all-clusters-app/ameba/main/Globals.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * 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 "Globals.h" + +LEDWidget statusLED1; diff --git a/examples/all-clusters-app/ameba/main/LEDWidget.cpp b/examples/all-clusters-app/ameba/main/LEDWidget.cpp new file mode 100755 index 00000000000000..a050f4a4d4f0f0 --- /dev/null +++ b/examples/all-clusters-app/ameba/main/LEDWidget.cpp @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2018 Nest Labs, Inc. + * All rights reserved. + * + * 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 LEDWidget.cpp + * + * Implements an LED Widget controller that is usually tied to a GPIO + * It also updates the display widget if it's enabled + */ + +#include "LEDWidget.h" + +gpio_t gpio_led; + +void LEDWidget::Init(PinName gpioNum) +{ + + mGPIONum = gpioNum; + mState = false; + + if (gpioNum != (PinName) NC) + { + // Init LED control pin + gpio_init(&gpio_led, gpioNum); + gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + gpio_write(&gpio_led, mState); + } +} + +void LEDWidget::Set(bool state) +{ + DoSet(state); +} + +void LEDWidget::DoSet(bool state) +{ + bool stateChange = (mState != state); + mState = state; + + if (stateChange) + { + gpio_write(&gpio_led, state); + } +} diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp index ebd31e945128f8..d3059b23ca9764 100644 --- a/examples/all-clusters-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp @@ -1,11 +1,39 @@ +/* + * + * Copyright (c) 2020 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 "CHIPDeviceManager.h" #include "DeviceCallbacks.h" -#include "Server.h" +#include "Globals.h" +#include "LEDWidget.h" +#include "chip_porting.h" +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include #include extern "C" { @@ -13,6 +41,7 @@ void * __dso_handle = 0; } using namespace ::chip; +using namespace ::chip::Credentials; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; @@ -30,28 +59,171 @@ Identify gIdentify1 = { EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED, }; +#define QRCODE_BASE_URL "https://dhrishi.github.io/connectedhomeip/qrcode.html" +#define EXAMPLE_VENDOR_TAG_IP 1 + +#ifdef CONFIG_PLATFORM_8721D +#define STATUS_LED_GPIO_NUM PB_5 +#elif defined(CONFIG_PLATFORM_8710C) +#define STATUS_LED_GPIO_NUM PA_20 +#else +#define STATUS_LED_GPIO_NUM NC +#endif + static DeviceCallbacks EchoCallbacks; +void GetGatewayIP(char * ip_buf, size_t ip_len) +{ + uint8_t * gateway = LwIP_GetGW(&xnetif[0]); + sprintf(ip_buf, "%d.%d.%d.%d", gateway[0], gateway[1], gateway[2], gateway[3]); + ChipLogProgress(DeviceLayer, "Got gateway ip: %s\r\n", ip_buf); +} + +// need to check CONFIG_RENDEZVOUS_MODE +bool isRendezvousBLE() +{ + RendezvousInformationFlags flags = RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE); + return flags.Has(RendezvousInformationFlag::kBLE); +} + +std::string createSetupPayload() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + std::string result; + + uint16_t discriminator; + err = ConfigurationMgr().GetSetupDiscriminator(discriminator); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get discriminator: %s\r\n", ErrorStr(err)); + return result; + } + ChipLogProgress(DeviceLayer, "Setup discriminator: %u (0x%x)\r\n", discriminator, discriminator); + + uint32_t setupPINCode; + err = ConfigurationMgr().GetSetupPinCode(setupPINCode); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get setupPINCode: %s\r\n", ErrorStr(err)); + return result; + } + ChipLogProgress(DeviceLayer, "Setup PIN code: %u (0x%x)\r\n", setupPINCode, setupPINCode); + + uint16_t vendorId; + err = ConfigurationMgr().GetVendorId(vendorId); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get vendorId: %s\r\n", ErrorStr(err)); + return result; + } + + uint16_t productId; + err = ConfigurationMgr().GetProductId(productId); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get productId: %s\r\n", ErrorStr(err)); + return result; + } + + SetupPayload payload; + payload.version = 0; + payload.discriminator = discriminator; + payload.setUpPINCode = setupPINCode; + payload.rendezvousInformation = RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE); + payload.vendorID = vendorId; + payload.productID = productId; + + if (!isRendezvousBLE()) + { + char gw_ip[INET6_ADDRSTRLEN]; + GetGatewayIP(gw_ip, sizeof(gw_ip)); + payload.addOptionalVendorData(EXAMPLE_VENDOR_TAG_IP, gw_ip); + + QRCodeSetupPayloadGenerator generator(payload); + + size_t tlvDataLen = sizeof(gw_ip); + uint8_t tlvDataStart[tlvDataLen]; + err = generator.payloadBase38Representation(result, tlvDataStart, tlvDataLen); + } + else + { + QRCodeSetupPayloadGenerator generator(payload); + err = generator.payloadBase38Representation(result); + } + + { + ManualSetupPayloadGenerator generator(payload); + std::string outCode; + + if (generator.payloadDecimalStringRepresentation(outCode) == CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "Short Manual(decimal) setup code: %s\r\n", outCode.c_str()); + } + else + { + ChipLogError(DeviceLayer, "Failed to get decimal setup code\r\n"); + } + + payload.commissioningFlow = CommissioningFlow::kCustom; + generator = ManualSetupPayloadGenerator(payload); + + if (generator.payloadDecimalStringRepresentation(outCode) == CHIP_NO_ERROR) + { + // intentional extra space here to align the log with the short code + ChipLogProgress(DeviceLayer, "Long Manual(decimal) setup code: %s\r\n", outCode.c_str()); + } + else + { + ChipLogError(DeviceLayer, "Failed to get decimal setup code\r\n"); + } + } + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Couldn't get payload string %\r\n" CHIP_ERROR_FORMAT, err.Format()); + } + return result; +}; + extern "C" void ChipTest(void) { - printf("In ChipTest()\r\n"); + ChipLogProgress(DeviceLayer, "All Clusters Demo!"); CHIP_ERROR err = CHIP_NO_ERROR; + initPref(); + CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance(); err = deviceMgr.Init(&EchoCallbacks); - if (err != CHIP_NO_ERROR) { - printf("DeviceManagerInit() - ERROR!\r\n"); + ChipLogError(DeviceLayer, "DeviceManagerInit() - ERROR!\r\n"); } else { - printf("DeviceManagerInit() - OK\r\n"); + ChipLogProgress(DeviceLayer, "DeviceManagerInit() - OK\r\n"); } chip::Server::GetInstance().Init(); + // Initialize device attestation config + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); + + std::string qrCodeText = createSetupPayload(); + ChipLogProgress(DeviceLayer, "QR CODE Text: '%s'\r\n", qrCodeText.c_str()); + + { + std::vector qrCode(3 * qrCodeText.size() + 1); + err = EncodeQRCodeToUrl(qrCodeText.c_str(), qrCodeText.size(), qrCode.data(), qrCode.max_size()); + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "Copy/paste the below URL in a browser to see the QR CODE:\n\t%s?data=%s \r\n", + QRCODE_BASE_URL, qrCode.data()); + } + } + + statusLED1.Init(STATUS_LED_GPIO_NUM); + while (true) vTaskDelay(pdMS_TO_TICKS(50)); } diff --git a/examples/all-clusters-app/ameba/main/include/DeviceCallbacks.h b/examples/all-clusters-app/ameba/main/include/DeviceCallbacks.h index eb64cf3bde1c31..10ac917c02890a 100644 --- a/examples/all-clusters-app/ameba/main/include/DeviceCallbacks.h +++ b/examples/all-clusters-app/ameba/main/include/DeviceCallbacks.h @@ -38,6 +38,8 @@ class DeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallbacks uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) override; private: + void OnInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnSessionEstablished(const chip::DeviceLayer::ChipDeviceEvent * event); void OnOnOffPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); void OnIdentifyPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); }; diff --git a/examples/all-clusters-app/ameba/main/include/Globals.h b/examples/all-clusters-app/ameba/main/include/Globals.h new file mode 100755 index 00000000000000..4033f2d0a996ee --- /dev/null +++ b/examples/all-clusters-app/ameba/main/include/Globals.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * 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 "LEDWidget.h" + +extern LEDWidget statusLED1; diff --git a/examples/all-clusters-app/ameba/main/include/LEDWidget.h b/examples/all-clusters-app/ameba/main/include/LEDWidget.h new file mode 100755 index 00000000000000..53459a3628c22c --- /dev/null +++ b/examples/all-clusters-app/ameba/main/include/LEDWidget.h @@ -0,0 +1,281 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * 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 + +#ifdef CONFIG_PLATFORM_8710C +#include "rtl8710c_pin_name.h" + +typedef struct hal_gpio_pin_adapter_s +{ + uint8_t pin_name; ///< chip pin name to locate the GPIO pin by port & pin index + uint8_t port_idx; ///< the GPIO IP port index of the GPIO pin + uint8_t pin_idx; ///< the GPIO IP pin index of the GPIO port + uint8_t debounce_idx; ///< the index of GPIO debounce function allocated to this GPIO pin, 0 ~ 15 + uint32_t bit_mask; ///< the bit mask to read/write register + + volatile uint32_t * in_port; ///< the IN port address + volatile uint32_t * out0_port; ///< the OUT port address for write 0 + volatile uint32_t * out1_port; ///< the OUT port address for write 1 + volatile uint32_t * outt_port; ///< the OUT port address for toggling +} hal_gpio_adapter_t, *phal_gpio_adapter_t; + +typedef enum +{ + PIN_INPUT = 0, + PIN_OUTPUT +} PinDirection; + +typedef enum +{ + PA_0 = PIN_A0, + PA_1 = PIN_A1, + PA_2 = PIN_A2, + PA_3 = PIN_A3, + PA_4 = PIN_A4, + PA_5 = PIN_A5, + PA_6 = PIN_A6, + PA_7 = PIN_A7, + PA_8 = PIN_A8, + PA_9 = PIN_A9, + PA_10 = PIN_A10, + PA_11 = PIN_A11, + PA_12 = PIN_A12, + PA_13 = PIN_A13, + PA_14 = PIN_A14, + PA_15 = PIN_A15, + PA_16 = PIN_A16, + PA_17 = PIN_A17, + PA_18 = PIN_A18, + PA_19 = PIN_A19, + PA_20 = PIN_A20, + PA_21 = PIN_A21, + PA_22 = PIN_A22, + PA_23 = PIN_A23, + + PB_0 = PIN_B0, + PB_1 = PIN_B1, + PB_2 = PIN_B2, + PB_3 = PIN_B3, + PB_4 = PIN_B4, + PB_5 = PIN_B5, + PB_6 = PIN_B6, + PB_7 = PIN_B7, + PB_8 = PIN_B8, + PB_9 = PIN_B9, + PB_10 = PIN_B10, + PB_11 = PIN_B11, + PB_12 = PIN_B12, + + // Arduino connector namings + /* + A0 = PA_0, + A1 = PA_1, + A2 = PA_4, + A3 = PB_0, + A4 = PC_1, + A5 = PC_0, + D0 = PA_3, + D1 = PA_2, + D2 = PA_10, + D3 = PB_3, + D4 = PB_5, + D5 = PB_4, + D6 = PB_10, + D7 = PA_8, + D8 = PA_9, + D9 = PC_7, + D10 = PB_6, + D11 = PA_7, + D12 = PA_6, + D13 = PA_5, + D14 = PB_9, + D15 = PB_8, + */ + + // Generic signals namings + /* + LED1 = PB_4, + LED2 = PB_5, + LED3 = PB_6, + LED4 = PB_7, + USER_BUTTON = PA_3, + SERIAL_TX = PA_7, + SERIAL_RX = PA_6, + USBTX = PA_7, + USBRX = PA_6, + I2C_SCL = PC_5, + I2C_SDA = PC_4, + SPI_MOSI = PC_2, + SPI_MISO = PC_3, + SPI_SCK = PC_1, + SPI_CS = PC_0, + PWM_OUT = PD_4, + */ + // Not connected + NC = (uint32_t) 0xFFFFFFFF +} PinName; + +typedef enum +{ + PullNone = 0, + PullUp = 1, + PullDown = 2, + OpenDrain = 3, + PullDefault = PullNone +} PinMode; + +struct gpio_s +{ + hal_gpio_adapter_t adapter; +}; + +#else + +typedef enum +{ + PORT_A = 0, + PORT_B = 1, +} GPIO_PORT; + +typedef enum +{ + PIN_INPUT = 0, + PIN_OUTPUT +} PinDirection; + +typedef enum +{ + PullNone = 0, // IN HIGHZ + PullUp = 1, + PullDown = 2, + PullDefault = PullNone +} PinMode; + +/* (((port)<<5)|(pin)) */ +typedef enum +{ + PA_0 = (PORT_A << 5 | 0), + PA_1 = (PORT_A << 5 | 1), + PA_2 = (PORT_A << 5 | 2), + PA_3 = (PORT_A << 5 | 3), + PA_4 = (PORT_A << 5 | 4), + PA_5 = (PORT_A << 5 | 5), + PA_6 = (PORT_A << 5 | 6), + PA_7 = (PORT_A << 5 | 7), + PA_8 = (PORT_A << 5 | 8), + PA_9 = (PORT_A << 5 | 9), + PA_10 = (PORT_A << 5 | 10), + PA_11 = (PORT_A << 5 | 11), + PA_12 = (PORT_A << 5 | 12), + PA_13 = (PORT_A << 5 | 13), + PA_14 = (PORT_A << 5 | 14), + PA_15 = (PORT_A << 5 | 15), + PA_16 = (PORT_A << 5 | 16), + PA_17 = (PORT_A << 5 | 17), + PA_18 = (PORT_A << 5 | 18), + PA_19 = (PORT_A << 5 | 19), + PA_20 = (PORT_A << 5 | 20), + PA_21 = (PORT_A << 5 | 21), + PA_22 = (PORT_A << 5 | 22), + PA_23 = (PORT_A << 5 | 23), + PA_24 = (PORT_A << 5 | 24), + PA_25 = (PORT_A << 5 | 25), + PA_26 = (PORT_A << 5 | 26), + PA_27 = (PORT_A << 5 | 27), + PA_28 = (PORT_A << 5 | 28), + PA_29 = (PORT_A << 5 | 29), + PA_30 = (PORT_A << 5 | 30), + PA_31 = (PORT_A << 5 | 31), + + PB_0 = (PORT_B << 5 | 0), + PB_1 = (PORT_B << 5 | 1), + PB_2 = (PORT_B << 5 | 2), + PB_3 = (PORT_B << 5 | 3), + PB_4 = (PORT_B << 5 | 4), + PB_5 = (PORT_B << 5 | 5), + PB_6 = (PORT_B << 5 | 6), + PB_7 = (PORT_B << 5 | 7), + PB_8 = (PORT_B << 5 | 8), + PB_9 = (PORT_B << 5 | 9), + PB_10 = (PORT_B << 5 | 10), + PB_11 = (PORT_B << 5 | 11), + PB_12 = (PORT_B << 5 | 12), + PB_13 = (PORT_B << 5 | 13), + PB_14 = (PORT_B << 5 | 14), + PB_15 = (PORT_B << 5 | 15), + PB_16 = (PORT_B << 5 | 16), + PB_17 = (PORT_B << 5 | 17), + PB_18 = (PORT_B << 5 | 18), + PB_19 = (PORT_B << 5 | 19), + PB_20 = (PORT_B << 5 | 20), + PB_21 = (PORT_B << 5 | 21), + PB_22 = (PORT_B << 5 | 22), + PB_23 = (PORT_B << 5 | 23), + PB_24 = (PORT_B << 5 | 24), + PB_25 = (PORT_B << 5 | 25), + PB_26 = (PORT_B << 5 | 26), + PB_27 = (PORT_B << 5 | 27), + PB_28 = (PORT_B << 5 | 28), + PB_29 = (PORT_B << 5 | 29), + PB_30 = (PORT_B << 5 | 30), + PB_31 = (PORT_B << 5 | 31), + + VBAT_MEAS = (0x7 << 5 | 2), + AD_0 = PB_4, // CH0 + AD_1 = PB_5, // CH1 + AD_2 = PB_6, // CH2 + AD_3 = PB_7, // CH3 + AD_4 = PB_1, // CH4 + AD_5 = PB_2, // CH5 + AD_6 = PB_3, // CH6 + AD_7 = VBAT_MEAS, // CH7 + + // Not connected + NC = (uint32_t) 0xFFFFFFFF +} PinName; + +typedef struct gpio_s +{ + PinName pin; +} gpio_t; + +#endif + +typedef struct gpio_s gpio_t; + +extern "C" void gpio_init(gpio_t * obj, PinName pin); +extern "C" uint32_t gpio_set(PinName pin); +extern "C" void gpio_mode(gpio_t * obj, PinMode mode); +extern "C" void gpio_dir(gpio_t * obj, PinDirection direction); +extern "C" void gpio_write(gpio_t * obj, int value); +extern "C" int gpio_read(gpio_t * obj); + +class LEDWidget +{ +public: + void Init(PinName gpioNum); + void Set(bool state); + +private: + PinName mGPIONum; + bool mState; + void DoSet(bool state); +}; diff --git a/integrations/docker/images/chip-build-ameba/Dockerfile b/integrations/docker/images/chip-build-ameba/Dockerfile index f8ffa1cc51e9dd..ec3a956f21699b 100644 --- a/integrations/docker/images/chip-build-ameba/Dockerfile +++ b/integrations/docker/images/chip-build-ameba/Dockerfile @@ -9,7 +9,7 @@ RUN set -x \ && cd ${AMEBA_DIR} \ && git clone --progress -b cmake_build https://github.com/pankore/ambd_sdk_with_chip_non_NDA.git \ && cd ambd_sdk_with_chip_non_NDA \ - && git reset --hard 299dd4a \ + && git reset --hard ae7ff59 \ && git submodule update --depth 1 --init --progress \ && : # last line diff --git a/integrations/docker/images/chip-build/version b/integrations/docker/images/chip-build/version index a056745373e3f6..859a588171e2d5 100644 --- a/integrations/docker/images/chip-build/version +++ b/integrations/docker/images/chip-build/version @@ -1 +1 @@ -0.5.22 Version bump reason: Implement Docker best practices on mbed OS +0.5.23 Version bump reason: [Ameba] Support BLE & IP commissioning function diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 5111f3358023c0..7896091831d0bc 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -156,7 +156,8 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint // TODO @bzbarsky-apple @cecille Move to examples // ESP32 and Mbed OS examples have a custom logic for enabling DNS-SD -#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !CHIP_DEVICE_LAYER_TARGET_ESP32 && !CHIP_DEVICE_LAYER_TARGET_MBED +#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD && !CHIP_DEVICE_LAYER_TARGET_ESP32 && !CHIP_DEVICE_LAYER_TARGET_MBED && \ + (!CHIP_DEVICE_LAYER_TARGET_AMEBA || !CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE) // StartServer only enables commissioning mode if device has not been commissioned app::DnssdServer::Instance().StartServer(); #endif diff --git a/src/platform/Ameba/AmebaConfig.cpp b/src/platform/Ameba/AmebaConfig.cpp index 7de03ca21412dc..b0dbab66c91a6b 100644 --- a/src/platform/Ameba/AmebaConfig.cpp +++ b/src/platform/Ameba/AmebaConfig.cpp @@ -31,7 +31,8 @@ enum kPrefsTypeBoolean = 1, kPrefsTypeInteger = 2, kPrefsTypeString = 3, - kPrefsTypeBuffer = 4 + kPrefsTypeBuffer = 4, + kPrefsTypeBinary = 5 }; namespace chip { @@ -78,8 +79,11 @@ CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, bool & val) uint32_t intVal; int32_t success = 0; - success = getPref_u32(key.Namespace, key.Name, kPrefsTypeBoolean, &intVal); - val = (intVal != 0); + success = getPref_bool_new(key.Namespace, key.Name, &intVal); + if (!success) + ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name); + + val = (intVal != 0); if (success == 1) return CHIP_NO_ERROR; @@ -90,7 +94,10 @@ CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, bool & val) CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint32_t & val) { int32_t success = 0; - success = getPref_u32(key.Namespace, key.Name, kPrefsTypeInteger, &val); + + success = getPref_u32_new(key.Namespace, key.Name, &val); + if (!success) + ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name); if (success == 1) return CHIP_NO_ERROR; @@ -100,18 +107,27 @@ CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint32_t & val) CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint64_t & val) { - // TODO - // Read configuration value - return CHIP_ERROR_NOT_IMPLEMENTED; + int32_t success = 0; + + success = getPref_u64_new(key.Namespace, key.Name, &val); + if (!success) + ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name); + + if (success == 1) + return CHIP_NO_ERROR; + else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; } CHIP_ERROR AmebaConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) { - int32_t ret = 0; + int32_t success = 0; - ret = getPref_str(key.Namespace, key.Name, kPrefsTypeString, buf, &outLen); + success = getPref_str_new(key.Namespace, key.Name, buf, bufSize, &outLen); + if (!success) + ChipLogProgress(DeviceLayer, "getPref_str_new: %s/%s failed\n", key.Namespace, key.Name); - if (ret == 0) + if (success == 1) { return CHIP_NO_ERROR; } @@ -124,9 +140,21 @@ CHIP_ERROR AmebaConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, CHIP_ERROR AmebaConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) { - // TODO - // Read configuration value - return CHIP_ERROR_NOT_IMPLEMENTED; + int32_t success = 0; + + success = getPref_bin_new(key.Namespace, key.Name, buf, bufSize, &outLen); + if (!success) + ChipLogProgress(DeviceLayer, "getPref_bin_new: %s/%s failed\n", key.Namespace, key.Name); + + if (success == 1) + { + return CHIP_NO_ERROR; + } + else + { + outLen = 0; + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } } CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, bool val) @@ -138,7 +166,7 @@ CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, bool val) value = 1; else value = 0; - success = setPref(key.Namespace, key.Name, kPrefsTypeBoolean, &value, 1); + success = setPref_new(key.Namespace, key.Name, &value, 1); if (!success) ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, value ? "true" : "false"); @@ -149,7 +177,7 @@ CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint32_t val) { int32_t success; - success = setPref(key.Namespace, key.Name, kPrefsTypeInteger, (uint8_t *) &val, sizeof(uint32_t)); + success = setPref_new(key.Namespace, key.Name, (uint8_t *) &val, sizeof(uint32_t)); if (!success) ChipLogError(DeviceLayer, "setPref: %s/%s = %d(0x%x) failed\n", key.Namespace, key.Name, val, val); @@ -160,7 +188,7 @@ CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint64_t val) { int32_t success; - success = setPref(key.Namespace, key.Name, kPrefsTypeInteger, (uint8_t *) &val, sizeof(uint64_t)); + success = setPref_new(key.Namespace, key.Name, (uint8_t *) &val, sizeof(uint64_t)); if (!success) ChipLogError(DeviceLayer, "setPref: %s/%s = %d(0x%x) failed\n", key.Namespace, key.Name, val, val); @@ -170,20 +198,10 @@ CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint64_t val) CHIP_ERROR AmebaConfig::WriteConfigValueStr(Key key, const char * str) { int32_t success; - char * _str = (char *) malloc(strlen(str) + 1); - if (_str == NULL) - { - free(_str); - return CHIP_ERROR_NO_MEMORY; - } - strcpy(_str, str); - - success = setPref(key.Namespace, key.Name, kPrefsTypeString, (uint8_t *) _str, strlen(_str) + 1); + success = setPref_new(key.Namespace, key.Name, (uint8_t *) str, strlen(str) + 1); if (!success) - ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, _str); - - free(_str); + ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, str); return CHIP_NO_ERROR; } @@ -205,43 +223,63 @@ CHIP_ERROR AmebaConfig::WriteConfigValueStr(Key key, const char * str, size_t st CHIP_ERROR AmebaConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) { - // TODO - // Set configuration value - return CHIP_ERROR_NOT_IMPLEMENTED; + int32_t success; + + success = setPref_new(key.Namespace, key.Name, (uint8_t *) data, dataLen); + if (!success) + ChipLogError(DeviceLayer, "setPref: %s/%s failed\n", key.Namespace, key.Name); + + return CHIP_NO_ERROR; } CHIP_ERROR AmebaConfig::ClearConfigValue(Key key) { - // TODO - // Delete configuration value - return CHIP_ERROR_NOT_IMPLEMENTED; + int32_t success; + + success = deleteKey(key.Namespace, key.Name); + if (!success) + ChipLogProgress(DeviceLayer, "%s : %s/%s failed\n", __FUNCTION__, key.Namespace, key.Name); + + return CHIP_NO_ERROR; } bool AmebaConfig::ConfigValueExists(Key key) { - // TODO - // Check if configuration value exists - return 45; + int32_t exist; + CHIP_ERROR err; + + exist = checkExist(key.Namespace, key.Name); + + if (exist == 1) + err = CHIP_NO_ERROR; + else + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + + return (err == CHIP_NO_ERROR); } CHIP_ERROR AmebaConfig::EnsureNamespace(const char * ns) { - int32_t ret = -1; + int32_t success = -1; - ret = initPref(ns); - if (ret != 0) + success = registerPref(ns); + if (success != 0) + { ChipLogError(DeviceLayer, "dct_register_module failed\n"); + } return CHIP_NO_ERROR; } CHIP_ERROR AmebaConfig::ClearNamespace(const char * ns) { - int32_t ret = -1; + int32_t success = -1; - ret = clearPref(ns); - if (ret != 0) + success = clearPref(ns); + if (success != 0) + { ChipLogError(DeviceLayer, "ClearNamespace failed\n"); + } return CHIP_NO_ERROR; } diff --git a/src/platform/Ameba/AmebaConfig.h b/src/platform/Ameba/AmebaConfig.h index d0debd585e9461..67b4f510be55b6 100755 --- a/src/platform/Ameba/AmebaConfig.h +++ b/src/platform/Ameba/AmebaConfig.h @@ -33,7 +33,7 @@ class AmebaConfig public: struct Key; - // Maximum length of an NVS key name, as specified in the ESP-IDF documentation. + // Maximum length of an NVS key name. static constexpr size_t kMaxConfigKeyNameLength = 15; // NVS namespaces used to store device configuration information. diff --git a/src/platform/Ameba/BLEManagerImpl.cpp b/src/platform/Ameba/BLEManagerImpl.cpp new file mode 100755 index 00000000000000..df0452f47b101c --- /dev/null +++ b/src/platform/Ameba/BLEManagerImpl.cpp @@ -0,0 +1,1045 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * All rights reserved. + * + * 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 + * Provides an implementation of the BLEManager singleton object + * for the Ameba platforms. + */ + +/* this file behaves like a config.h, comes first */ +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include + +#include "stdio.h" +#include "timers.h" + +// Ameba BLE related header files +#include "bt_matter_adapter_app_main.h" +#include "bt_matter_adapter_app_task.h" +#include "bt_matter_adapter_peripheral_app.h" +#include "bt_matter_adapter_service.h" +#include "bte.h" +#include "gap.h" +#include "gap_adv.h" +#include "gap_conn_le.h" +#include "os_sched.h" +#include "profile_server.h" +#include "rtk_coex.h" +#include "trace_app.h" +#include "wifi_conf.h" +//#include "complete_ble_service.h" +#include "app_msg.h" + +extern void wifi_bt_coex_set_bt_on(void); +/******************************************************************************* + * Local data types + *******************************************************************************/ +using namespace ::chip; +using namespace ::chip::Ble; + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +namespace { + +/******************************************************************************* + * Macros & Constants definitions + *******************************************************************************/ +#define APP_MAX_LINKS 4 +#define MAX_ADV_DATA_LEN 31 +#define CHIP_ADV_DATA_TYPE_FLAGS 0x01 +#define CHIP_ADV_DATA_FLAGS 0x06 +#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16 + +#define LOOP_EV_BLE (0x08) + +/* ble app task configuration */ +#define CHIP_DEVICE_CONFIG_BLE_APP_TASK_PRIORITY (HOST_TASK_PRIORITY - 1) +#define CHIP_DEVICE_CONFIG_BLE_APP_TASK_STACK_SIZE (1024) + +/* advertising configuration */ +#define CHIP_ADV_SHORT_UUID_LEN (2) + +/* FreeRTOS sw timer */ +TimerHandle_t sbleAdvTimeoutTimer; + +/* Used by BLE App Task to handle asynchronous GATT events */ +EventGroupHandle_t bleAppTaskLoopEvent; + +/* keep the device ID of the connected peer */ +uint8_t device_id; + +/** Type of UUID */ +enum +{ + /** 16-bit UUID (BT SIG assigned) */ + BLE_UUID_TYPE_16 = 16, + + /** 32-bit UUID (BT SIG assigned) */ + BLE_UUID_TYPE_32 = 32, + + /** 128-bit UUID */ + BLE_UUID_TYPE_128 = 128, +}; + +typedef struct +{ + /** Type of the UUID */ + uint8_t type; +} ble_uuid_t; + +/** 16-bit UUID */ +typedef struct +{ + ble_uuid_t u; + uint16_t value; +} ble_uuid16_t; + +const ble_uuid16_t ShortUUID_CHIPoBLEService = { BLE_UUID_TYPE_16, 0xFFF6 }; +const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, + 0x9D, 0x11 } }; +const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, + 0x9D, 0x12 } }; +} // namespace + +BLEManagerImpl BLEManagerImpl::sInstance; + +CHIP_ERROR BLEManagerImpl::_Init() +{ + CHIP_ERROR err; + + // Initialize the CHIP BleLayer. + err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer()); + SuccessOrExit(err); + + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; + + // Check if BLE stack is initialized + VerifyOrExit(!mFlags.Has(Flags::kAMEBABLEStackInitialized), err = CHIP_ERROR_INCORRECT_STATE); + + err = MapBLEError(bt_matter_adapter_init()); + chip_blemgr_set_callback_func((chip_blemgr_callback)(ble_callback_dispatcher), this); + SuccessOrExit(err); + + // Set related flags + mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); + mFlags.Set(Flags::kAMEBABLEStackInitialized); + mFlags.Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? true : false); + mFlags.Set(Flags::kFastAdvertisingEnabled); + + PlatformMgr().ScheduleWork(DriveBLEState, 0); + +exit: + return err; +} + +void BLEManagerImpl::HandleTXCharRead(struct ble_gatt_char_context * param) +{ + /* Not supported */ + ChipLogError(DeviceLayer, "BLEManagerImpl::HandleTXCharRead() not supported"); +} + +void BLEManagerImpl::HandleTXCharCCCDRead(void * param) +{ + /* Not Supported */ + ChipLogError(DeviceLayer, "BLEManagerImpl::HandleTXCharCCCDRead() not supported"); +} + +void BLEManagerImpl::HandleTXCharCCCDWrite(int conn_id, int indicationsEnabled, int notificationsEnabled) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // If the client has requested to enabled indications/notifications + if (indicationsEnabled || notificationsEnabled) + { + // If indications are not already enabled for the connection... + if (!IsSubscribed(conn_id)) + { + // Record that indications have been enabled for this connection. + err = SetSubscribed(conn_id); + VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR); + SuccessOrExit(err); + } + } + else + { + // If indications had previously been enabled for this connection, record that they are no longer + // enabled. + UnsetSubscribed(conn_id); + } + + // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on + // whether the client is enabling or disabling indications. + { + ChipDeviceEvent event; + event.Type = (indicationsEnabled || notificationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe + : DeviceEventType::kCHIPoBLEUnsubscribe; + event.CHIPoBLESubscribe.ConId = conn_id; + PlatformMgr().PostEventOrDie(&event); + } + + ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", + (indicationsEnabled || notificationsEnabled) ? "subscribe" : "unsubscribe"); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err)); + } + + return; +} + +CHIP_ERROR BLEManagerImpl::HandleTXComplete(int conn_id) +{ + // Post an event to the Chip queue to process the indicate confirmation. + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm; + event.CHIPoBLEIndicateConfirm.ConId = conn_id; + PlatformMgr().PostEventOrDie(&event); + return CHIP_NO_ERROR; +} + +uint16_t BLEManagerImpl::_NumConnections(void) +{ + uint16_t numCons = 0; + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED) + { + numCons++; + } + } + + return numCons; +} + +CHIP_ERROR BLEManagerImpl::HandleGAPConnect(uint16_t conn_id) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + // Track the number of active GAP connections. + mNumGAPCons++; + err = SetSubscribed(conn_id); + VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR); + SuccessOrExit(err); + + mFlags.Set(Flags::kAdvertisingRefreshNeeded); + mFlags.Clear(Flags::kAdvertisingConfigured); + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(uint16_t conn_id, uint16_t disc_cause) +{ + // Update the number of GAP connections. + if (mNumGAPCons > 0) + { + mNumGAPCons--; + } + + if (UnsetSubscribed(conn_id)) + { + CHIP_ERROR disconReason; + switch (disc_cause) + { + case HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE: // BLE_ERR_REM_USER_CONN_TERM: + disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED; + break; + case HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE: // BLE_ERR_CONN_TERM_LOCAL: + disconReason = BLE_ERROR_APP_CLOSED_CONNECTION; + break; + default: + disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT; + break; + } + HandleConnectionError(conn_id, disconReason); + } + + // Force a reconfiguration of advertising in case we switched to non-connectable mode when + // the BLE connection was established. + mFlags.Set(Flags::kAdvertisingRefreshNeeded); + mFlags.Clear(Flags::kAdvertisingConfigured); + + return CHIP_NO_ERROR; +} + +bool BLEManagerImpl::RemoveConnection(uint8_t connectionHandle) +{ + CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true); + bool status = false; + + if (bleConnState != NULL) + { + memset(bleConnState, 0, sizeof(CHIPoBLEConState)); + status = true; + } + return status; +} + +void BLEManagerImpl::AddConnection(uint8_t connectionHandle) +{ + CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true); + + if (bleConnState != NULL) + { + memset(bleConnState, 0, sizeof(CHIPoBLEConState)); + bleConnState->allocated = 1; + bleConnState->connectionHandle = connectionHandle; + } +} + +BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint8_t connectionHandle, bool allocate) +{ + uint8_t freeIndex = kMaxConnections; + + for (uint8_t i = 0; i < kMaxConnections; i++) + { + if (mBleConnections[i].allocated == 1) + { + if (mBleConnections[i].connectionHandle == connectionHandle) + { + return &mBleConnections[i]; + } + } + + else if (i < freeIndex) + { + freeIndex = i; + } + } + + if (allocate) + { + if (freeIndex < kMaxConnections) + { + return &mBleConnections[freeIndex]; + } + + ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState"); + } + + return NULL; +} + +CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (val != mServiceMode) + { + mServiceMode = val; + PlatformMgr().ScheduleWork(DriveBLEState, 0); + } + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (mFlags.Has(Flags::kAdvertisingEnabled) != val) + { + mFlags.Set(Flags::kAdvertisingEnabled, val); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + } + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) +{ + switch (mode) + { + case BLEAdvertisingMode::kFastAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, true); + break; + case BLEAdvertisingMode::kSlowAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, false); + break; + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + mFlags.Set(Flags::kRestartAdvertising); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) +{ + if (strlen(mDeviceName) >= bufSize) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + strcpy(buf, mDeviceName); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (deviceName != NULL && deviceName[0] != 0) + { + VerifyOrExit(strlen(deviceName) >= kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT); + strcpy(mDeviceName, deviceName); + mFlags.Set(Flags::kDeviceNameSet); + ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", deviceName); + } + else + { + mDeviceName[0] = 0; + mFlags.Clear(Flags::kDeviceNameSet); + } + +exit: + return err; +} + +void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + switch (event->Type) + { + // Platform specific events + case DeviceEventType::kCHIPoBLESubscribe: + HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + { + ChipDeviceEvent connEstEvent; + connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; + PlatformMgr().PostEventOrDie(&connEstEvent); + } + break; + + case DeviceEventType::kCHIPoBLEUnsubscribe: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe"); + HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + } + break; + + case DeviceEventType::kCHIPoBLEWriteReceived: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived"); + HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX, + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); + } + break; + + case DeviceEventType::kCHIPoBLEConnectionError: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError"); + HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); + } + break; + + case DeviceEventType::kCHIPoBLEIndicateConfirm: { + ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm"); + HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + } + break; + + case DeviceEventType::kFabricMembershipChange: + case DeviceEventType::kServiceProvisioningChange: + case DeviceEventType::kAccountPairingChange: + case DeviceEventType::kWiFiConnectivityChange: + +// If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, when there is a change to the device's provisioning state and device +// is now fully provisioned, the CHIPoBLE advertising will be disabled. +#if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + if (ConfigurationMgr().IsFullyProvisioned()) + { + mFlags.Clear(Flags::kAdvertisingEnabled); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned"); + } +#endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + ChipLogProgress(DeviceLayer, "Updating advertising data"); + StartAdvertising(); + break; + + default: + ChipLogProgress(DeviceLayer, "_OnPlatformEvent default: event->Type = %d", event->Type); + break; + } +} + +bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported"); + return false; +} + +bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported"); + return false; +} + +bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) +{ + CHIP_ERROR err; + ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId); + + // Ameba Ble close function + err = MapBLEError(le_disconnect(conId)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "le_disconnect() failed: %s", ErrorStr(err)); + } + + return (err == CHIP_NO_ERROR); +} + +uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const +{ + int mtu; + mtu = ble_att_mtu_z2(conId); + return mtu; +} + +bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) +{ + ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported"); + return false; +} + +bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle pBuf) +{ + ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported"); + return false; +} + +bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, + const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported"); + return false; +} + +void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) +{ + // Nothing to do +} + +bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle data) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT); + server_send_data(conId, bt_matter_adapter_service_id, BT_MATTER_ADAPTER_SERVICE_CHAR_NOTIFY_CCCD_INDEX - 1, data->Start(), + data->DataLength(), GATT_PDU_TYPE_NOTIFICATION); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err)); + return false; + } + return true; +} + +/******************************************************************************* + * Private functions + *******************************************************************************/ + +CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) +{ + CHIP_ERROR err; + uint8_t advData[MAX_ADV_DATA_LEN] = { 0 }; + uint8_t advPayload[MAX_ADV_DATA_LEN] = { 0 }; + uint8_t deviceIdInfoLength = 0; + ChipBLEDeviceIdentificationInfo deviceIdInfo; + uint8_t index = 0; + uint32_t bleAdvTimeoutMs; + uint16_t adv_int_min; + uint16_t adv_int_max; + T_GAP_DEV_STATE new_state; + + // If the device name is not specified, generate a CHIP-standard name based on the bottom digits of the Chip device id. + uint16_t discriminator; + SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator)); + + if (!mFlags.Has(Flags::kDeviceNameSet)) + { + snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator); + mDeviceName[kMaxDeviceNameLength] = 0; + } + + // Configure the BLE device name. + le_set_gap_param(GAP_PARAM_DEVICE_NAME, kMaxDeviceNameLength, mDeviceName); + + /**************** Prepare advertising data *******************************************/ + memset(advData, 0, sizeof(advData)); + advData[index++] = 0x02; // length + advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags + advData[index++] = CHIP_ADV_DATA_FLAGS; // AD value + advData[index++] = 0x0A; // length + advData[index++] = 0x16; // AD type: (Service Data - 16-bit UUID) + advData[index++] = static_cast(ShortUUID_CHIPoBLEService.value & 0xFF); // AD value + advData[index++] = static_cast((ShortUUID_CHIPoBLEService.value >> 8) & 0xFF); // AD value + + err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "GetBLEDeviceIdentificationInfo(): %s", ErrorStr(err)); + ExitNow(); + } + + VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG); + memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo)); + index = static_cast(index + sizeof(deviceIdInfo)); + + if (mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + adv_int_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; + adv_int_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; + bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME; + } + else + { + adv_int_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; + adv_int_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; + bleAdvTimeoutMs = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT; + } + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(advData), (void *) advData); // set advData + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::StartAdvertising(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + err = ConfigureAdvertisingData(); + SuccessOrExit(err); + + // Start advertising + le_adv_stop(); + vTaskDelay(100); + le_adv_start(); + + mFlags.Set(Flags::kAdvertising); + mFlags.Clear(Flags::kRestartAdvertising); + + if (err == CHIP_NO_ERROR) + { + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started; + PlatformMgr().PostEventOrDie(&advChange); + } + +exit: + return err; +} + +CHIP_ERROR BLEManagerImpl::StopAdvertising(void) +{ + CHIP_ERROR err; + + // Stop advertising + le_adv_stop(); + + // Change flag status to the 'not Advertising state' + if (mFlags.Has(Flags::kAdvertising)) + { + mFlags.Clear(Flags::kAdvertising); + mFlags.Set(Flags::kFastAdvertisingEnabled); + + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); + + // Post a CHIPoBLEAdvertisingChange(Stopped) event. + { + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped; + PlatformMgr().PostEventOrDie(&advChange); + } + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) +{ + switch (bleErr) + { + case 0: + return CHIP_NO_ERROR; + default: + return CHIP_ERROR_INCORRECT_STATE; + } +} + +void BLEManagerImpl::DriveBLEState(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Check if BLE stack is initialized + VerifyOrExit(mFlags.Has(Flags::kAMEBABLEStackInitialized), /* */); + +// If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled and the device is fully provisioned, the CHIPoBLE +// advertising will be disabled. +#if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + if (ConfigurationMgr().IsFullyProvisioned()) + { + mFlags.Clear(Flags::kAdvertisingEnabled); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned"); + } +#endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED + + // Start advertising if needed... + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled)) + { + // Start/re-start advertising if not already started, or if there is a pending change + // to the advertising configuration. + if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kRestartAdvertising)) + { + err = StartAdvertising(); + SuccessOrExit(err); + } + } + // Otherwise, stop advertising if it is enabled. + else if (mFlags.Has(Flags::kAdvertising)) + { + err = StopAdvertising(); + SuccessOrExit(err); + ChipLogProgress(DeviceLayer, "Stopped Advertising"); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + } +} + +void BLEManagerImpl::DriveBLEState(intptr_t arg) +{ + sInstance.DriveBLEState(); +} + +/******************************************************************************* + * BLE App Task Processing + *******************************************************************************/ + +/******************************************************************************* + * BLE stack callbacks + *******************************************************************************/ + +/******************************************************************************* + * Add to message queue functions + *******************************************************************************/ + +/******************************************************************************* + * FreeRTOS Task Management Functions + *******************************************************************************/ + +void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer) +{ + if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertisement"); + + sInstance.mFlags.Clear(Flags::kFastAdvertisingEnabled); + // Stop advertising, change interval and restart it; + sInstance.StopAdvertising(); + sInstance.StartAdvertising(); + sInstance.StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT); // Slow advertise for 15 Minutes + } + else if (sInstance._IsAdvertisingEnabled()) + { + // Advertisement time expired. Stop advertising + ChipLogDetail(DeviceLayer, "bleAdv Timeout : Stop advertisement"); + sInstance.StopAdvertising(); + } +} + +void BLEManagerImpl::CancelBleAdvTimeoutTimer(void) +{ + if (xTimerStop(sbleAdvTimeoutTimer, 0) == pdFAIL) + { + ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer"); + } +} + +void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs) +{ + if (xTimerIsTimerActive(sbleAdvTimeoutTimer)) + { + CancelBleAdvTimeoutTimer(); + } + + // timer is not active, change its period to required value (== restart). + // FreeRTOS- Block for a maximum of 100 ticks if the change period command + // cannot immediately be sent to the timer command queue. + if (xTimerChangePeriod(sbleAdvTimeoutTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) + { + ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer"); + } +} + +CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId) +{ + uint16_t freeIndex = kMaxConnections; + + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mSubscribedConIds[i] == conId) + { + return CHIP_NO_ERROR; + } + else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex) + { + freeIndex = i; + } + } + + if (freeIndex < kMaxConnections) + { + mSubscribedConIds[freeIndex] = conId; + return CHIP_NO_ERROR; + } + else + { + return CHIP_ERROR_NO_MEMORY; + } +} + +bool BLEManagerImpl::UnsetSubscribed(uint16_t conId) +{ + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mSubscribedConIds[i] == conId) + { + mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED; + return true; + } + } + return false; +} + +bool BLEManagerImpl::IsSubscribed(uint16_t conId) +{ + if (conId != BLE_CONNECTION_UNINITIALIZED) + { + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mSubscribedConIds[i] == conId) + { + return true; + } + } + } + return false; +} + +CHIP_ERROR BLEManagerImpl::ble_svr_gap_msg_event(void * param, T_IO_MSG * p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + CHIP_ERROR err = CHIP_NO_ERROR; + uint16_t conn_id = gap_msg.msg_data.gap_conn_state_change.conn_id; + uint16_t new_state = gap_msg.msg_data.gap_conn_state_change.new_state; + uint16_t disc_cause = gap_msg.msg_data.gap_conn_state_change.disc_cause; + + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_CONN_STATE_CHANGE: + /* A new connection was established or a connection attempt failed */ + if (new_state == GAP_CONN_STATE_CONNECTED) + { + err = sInstance.HandleGAPConnect(conn_id); + SuccessOrExit(err); + } + else if (new_state == GAP_CONN_STATE_DISCONNECTED) + { + err = sInstance.HandleGAPDisconnect(conn_id, disc_cause); + SuccessOrExit(err); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: // BLE_GAP_EVENT_MTU: + break; + + default: + break; + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + sInstance.mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + } + + // Schedule DriveBLEState() to run. + PlatformMgr().ScheduleWork(DriveBLEState, 0); + + return err; +} + +CHIP_ERROR BLEManagerImpl::ble_svr_gap_event(void * param, int cb_type, void * p_cb_data) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + T_LE_CB_DATA * p_data = (T_LE_CB_DATA *) p_cb_data; + switch (cb_type) + { +#if defined(CONFIG_PLATFORM_8721D) + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + break; + + default: + break; + } + return err; +} + +CHIP_ERROR BLEManagerImpl::gatt_svr_chr_access(void * param, T_SERVER_ID service_id, TBTCONFIG_CALLBACK_DATA * p_data) +{ + + CHIP_ERROR err = CHIP_NO_ERROR; + + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA * p_param = (T_SERVER_APP_CB_DATA *) p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE: // srv register result event. + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + err = sInstance.HandleTXComplete(p_param->event_data.send_data_result.conn_id); + break; + + default: + break; + } + } + else + { + uint8_t conn_id = p_data->conn_id; + T_SERVICE_CALLBACK_TYPE msg_type = p_data->msg_type; + uint8_t * p_value = p_data->msg_data.write.p_value; + uint16_t len = p_data->msg_data.write.len; + BLEManagerImpl * blemgr = static_cast(param); + switch (msg_type) + { + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + break; + + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + sInstance.HandleRXCharWrite(p_value, len, conn_id); + break; + + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: { + TSIMP_CALLBACK_DATA * pp_data; + pp_data = (TSIMP_CALLBACK_DATA *) p_data; + switch (pp_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: { + sInstance.HandleTXCharCCCDWrite(conn_id, 0, 1); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: { + sInstance.HandleTXCharCCCDWrite(conn_id, 0, 0); + } + break; + } + } + break; + + default: + break; + } + } + PlatformMgr().ScheduleWork(DriveBLEState, 0); + + return err; +} + +void BLEManagerImpl::HandleRXCharWrite(uint8_t * p_value, uint16_t len, uint8_t conn_id) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + PacketBufferHandle buf = System::PacketBufferHandle::New(len, 0); + memcpy(buf->Start(), p_value, len); + buf->SetDataLength(len); + + // Post an event to the Chip queue to deliver the data into the Chip stack. + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEWriteReceived; + event.CHIPoBLEWriteReceived.ConId = (uint16_t) conn_id; + event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease(); + PlatformMgr().PostEventOrDie(&event); + } + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err)); + } +} + +int BLEManagerImpl::ble_callback_dispatcher(void * param, void * p_cb_data, int type, T_CHIP_BLEMGR_CALLBACK_TYPE callback_type) +{ + BLEManagerImpl * blemgr = static_cast(param); + switch (callback_type) + { + case CB_PROFILE_CALLBACK: + blemgr->gatt_svr_chr_access(param, type, (TBTCONFIG_CALLBACK_DATA *) p_cb_data); + break; + case CB_GAP_CALLBACK: + blemgr->ble_svr_gap_event(param, type, p_cb_data); + break; + case CB_GAP_MSG_CALLBACK: + blemgr->ble_svr_gap_msg_event(param, (T_IO_MSG *) p_cb_data); + break; + default: + break; + } + return 0; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Ameba/BLEManagerImpl.h b/src/platform/Ameba/BLEManagerImpl.h new file mode 100755 index 00000000000000..bfb2ed1df37cef --- /dev/null +++ b/src/platform/Ameba/BLEManagerImpl.h @@ -0,0 +1,215 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * All rights reserved. + * + * 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 + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include "FreeRTOS.h" +#include "app_msg.h" +#include "bt_matter_adapter_peripheral_app.h" +#include "bt_matter_adapter_service.h" +#include "event_groups.h" +#include "gap_msg.h" +#include "timers.h" + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +using namespace chip::Ble; + +/** + * Concrete implementation of the BLEManager singleton object for the Ameba platforms. + */ +class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePlatformDelegate, private BleApplicationDelegate +{ + // Allow the BLEManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend BLEManager; + +private: + // ===== Members that implement the BLEManager internal interface. + + CHIP_ERROR _Init(void); + CHIPoBLEServiceMode _GetCHIPoBLEServiceMode(void); + CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val); + bool _IsAdvertisingEnabled(void); + CHIP_ERROR _SetAdvertisingEnabled(bool val); + bool _IsAdvertising(void); + CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode); + CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize); + CHIP_ERROR _SetDeviceName(const char * deviceName); + uint16_t _NumConnections(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + BleLayer * _GetBleLayer(void); + + // ===== Members that implement virtual methods on BlePlatformDelegate. + + bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + bool CloseConnection(BLE_CONNECTION_OBJECT conId) override; + uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override; + bool SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle pBuf) override; + bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle pBuf) override; + bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle pBuf) override; + bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + + // ===== Members that implement virtual methods on BleApplicationDelegate. + + void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override; + + // ===== Members for internal use by the following friends. + + friend BLEManager & BLEMgr(void); + friend BLEManagerImpl & BLEMgrImpl(void); + + static BLEManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + + typedef enum + { + BC_DEV_DISABLED = 0x0, + BC_DEV_INIT = 0x1, + BC_DEV_IDLE = 0x2, + BC_DEV_BT_CONNECTED = 0x3, + BC_DEV_DEINIT = 0x4, + } BC_device_state_t; + + enum class Flags : uint8_t + { + kAdvertisingEnabled = 0x0001, + kFastAdvertisingEnabled = 0x0002, + kAdvertising = 0x0004, + kRestartAdvertising = 0x0008, + kAMEBABLEStackInitialized = 0x0010, + kDeviceNameSet = 0x0020, + kAdvertisingRefreshNeeded = 0x030, + kAdvertisingConfigured = 0x040, + }; + BitFlags mFlags; + + enum + { + kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS, + kMaxDeviceNameLength = 16, + kUnusedIndex = 0xFF, + }; + + struct CHIPoBLEConState + { + uint16_t mtu : 10; + uint16_t allocated : 1; + uint16_t subscribed : 1; + uint16_t unused : 4; + uint8_t connectionHandle; + uint8_t bondingHandle; + }; + CHIPoBLEConState mBleConnections[kMaxConnections]; + + CHIPoBLEServiceMode mServiceMode; + + uint16_t mNumGAPCons; + uint16_t mTXCharCCCDAttrHandle; + uint16_t mSubscribedConIds[kMaxConnections]; + char mDeviceName[kMaxDeviceNameLength + 1]; + CHIP_ERROR MapBLEError(int bleErr); + + void DriveBLEState(void); + CHIP_ERROR StartAdvertising(void); + CHIP_ERROR StopAdvertising(void); + CHIP_ERROR ConfigureAdvertisingData(void); + + void HandleRXCharWrite(uint8_t *, uint16_t, uint8_t); + void HandleTXCharRead(struct ble_gatt_char_context * param); + void HandleTXCharCCCDRead(void * param); + void HandleTXCharCCCDWrite(int, int, int); + CHIP_ERROR HandleTXComplete(int); + CHIP_ERROR HandleGAPConnect(uint16_t); + CHIP_ERROR HandleGAPDisconnect(uint16_t, uint16_t); + CHIP_ERROR SetSubscribed(uint16_t conId); + bool UnsetSubscribed(uint16_t conId); + bool IsSubscribed(uint16_t conId); + + bool RemoveConnection(uint8_t connectionHandle); + void AddConnection(uint8_t connectionHandle); + + BLEManagerImpl::CHIPoBLEConState * GetConnectionState(uint8_t connectionHandle, bool allocate); + static CHIP_ERROR ble_svr_gap_msg_event(void * param, T_IO_MSG * p_gap_msg); + static CHIP_ERROR ble_svr_gap_event(void * param, int cb_type, void * p_cb_data); + static CHIP_ERROR gatt_svr_chr_access(void * param, T_SERVER_ID service_id, TBTCONFIG_CALLBACK_DATA * p_data); + static int ble_callback_dispatcher(void * param, void * p_cb_data, int type, T_CHIP_BLEMGR_CALLBACK_TYPE callback_type); + static void DriveBLEState(intptr_t arg); + static void BleAdvTimeoutHandler(TimerHandle_t xTimer); + static void CancelBleAdvTimeoutTimer(void); + static void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs); +}; + +/** + * Returns a reference to the public interface of the BLEManager singleton object. + * + * Internal components should use this to access features of the BLEManager object + * that are common to all platforms. + */ +inline BLEManager & BLEMgr(void) +{ + return BLEManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the BLEManager singleton object. + * + * Internal components can use this to gain access to features of the BLEManager + * that are specific to the platforms. + */ +inline BLEManagerImpl & BLEMgrImpl(void) +{ + return BLEManagerImpl::sInstance; +} + +inline BleLayer * BLEManagerImpl::_GetBleLayer() +{ + return this; +} + +inline BLEManager::CHIPoBLEServiceMode BLEManagerImpl::_GetCHIPoBLEServiceMode(void) +{ + return mServiceMode; +} + +inline bool BLEManagerImpl::_IsAdvertisingEnabled(void) +{ + return mFlags.Has(Flags::kAdvertisingEnabled); +} + +inline bool BLEManagerImpl::_IsAdvertising(void) +{ + return mFlags.Has(Flags::kAdvertising); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Ameba/BUILD.gn b/src/platform/Ameba/BUILD.gn index 6fc6a20b9dc2f9..15849c83b426f0 100755 --- a/src/platform/Ameba/BUILD.gn +++ b/src/platform/Ameba/BUILD.gn @@ -23,6 +23,8 @@ static_library("Ameba") { "../FreeRTOS/SystemTimeSupport.cpp", "AmebaConfig.cpp", "AmebaConfig.h", + "BLEManagerImpl.cpp", + "BLEManagerImpl.h", "CHIPDevicePlatformConfig.h", "CHIPDevicePlatformEvent.h", "ConfigurationManagerImpl.cpp", @@ -31,6 +33,7 @@ static_library("Ameba") { "ConnectivityManagerImpl.h", "DeviceNetworkProvisioningDelegateImpl.cpp", "DeviceNetworkProvisioningDelegateImpl.h", + "KeyValueStoreManagerImpl.cpp", "KeyValueStoreManagerImpl.h", "Logging.cpp", "LwIPCoreLock.cpp", @@ -38,6 +41,7 @@ static_library("Ameba") { "PlatformManagerImpl.h", "ServiceProvisioning.cpp", "ServiceProvisioning.h", + "SoftwareUpdateManagerImpl.h", "SystemTimeSupport.cpp", ] diff --git a/src/platform/Ameba/BlePlatformConfig.h b/src/platform/Ameba/BlePlatformConfig.h index d61703e3e2b1d2..7cd031fe83dfa5 100644 --- a/src/platform/Ameba/BlePlatformConfig.h +++ b/src/platform/Ameba/BlePlatformConfig.h @@ -31,12 +31,8 @@ #define BLE_CONNECTION_UNINITIALIZED (0xFFFF) #define BLE_MAX_RECEIVE_WINDOW_SIZE 5 -#define BLE_CONFIG_ERROR_TYPE int32_t -#define BLE_CONFIG_ERROR_FORMAT PRId32 -#define BLE_CONFIG_NO_ERROR 0 #define BLE_CONFIG_ERROR_MIN 6000000 #define BLE_CONFIG_ERROR_MAX 6000999 -#define _BLE_CONFIG_ERROR(e) (BLE_CONFIG_ERROR_MIN + (e)) // ========== Platform-specific Configuration Overrides ========= diff --git a/src/platform/Ameba/CHIPDevicePlatformConfig.h b/src/platform/Ameba/CHIPDevicePlatformConfig.h index 8b3a16161fb95a..c7deb609f5676f 100755 --- a/src/platform/Ameba/CHIPDevicePlatformConfig.h +++ b/src/platform/Ameba/CHIPDevicePlatformConfig.h @@ -34,7 +34,7 @@ #define CHIP_DEVICE_CONFIG_ENABLE_THREAD 1 #endif -#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0 +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1 #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 0 @@ -53,7 +53,7 @@ // ========== Platform-specific Configuration Overrides ========= #ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE -#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 4096 +#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 8192 #endif // CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE #ifndef CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE @@ -64,4 +64,12 @@ #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0 #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0 #define CHIP_DEVICE_CONFIG_LOG_PROVISIONING_HASH 0 + #define CHIP_DEVICE_LAYER_NONE 0 + +// 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 + +#define CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY 34 +#define CONFIG_RENDEZVOUS_MODE 6 diff --git a/src/platform/Ameba/CHIPDevicePlatformEvent.h b/src/platform/Ameba/CHIPDevicePlatformEvent.h index d07608e9d03978..6ecc1db465772c 100644 --- a/src/platform/Ameba/CHIPDevicePlatformEvent.h +++ b/src/platform/Ameba/CHIPDevicePlatformEvent.h @@ -48,6 +48,7 @@ enum InternalPlatformSpecificEventTypes kCHIPoBLECCCWriteEvent, kCHIPoBLERXCharWriteEvent, kCHIPoBLETXCharWriteEvent, + kRtkWiFiStationConnectedEvent, }; } // namespace DeviceEventType diff --git a/src/platform/Ameba/ConfigurationManagerImpl.cpp b/src/platform/Ameba/ConfigurationManagerImpl.cpp index 24a6c273889187..1728f578f7c8ac 100644 --- a/src/platform/Ameba/ConfigurationManagerImpl.cpp +++ b/src/platform/Ameba/ConfigurationManagerImpl.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace chip { namespace DeviceLayer { @@ -44,12 +45,18 @@ CHIP_ERROR ConfigurationManagerImpl::Init() CHIP_ERROR err; bool failSafeArmed; + // Force initialization of NVS namespaces if they doesn't already exist. + err = EnsureNamespace(kConfigNamespace_ChipFactory); + SuccessOrExit(err); + err = EnsureNamespace(kConfigNamespace_ChipConfig); + SuccessOrExit(err); + err = EnsureNamespace(kConfigNamespace_ChipCounters); + SuccessOrExit(err); + // Initialize the generic implementation base class. err = Internal::GenericConfigurationManagerImpl::Init(); SuccessOrExit(err); - // TODO: initialize NVM component - // If the fail-safe was armed when the device last shutdown, initiate a factory reset. if (GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed) { @@ -64,7 +71,16 @@ CHIP_ERROR ConfigurationManagerImpl::Init() CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + char temp[32]; + uint32_t mac[ETH_ALEN]; + int i = 0; + + wifi_get_mac_address(temp); + sscanf(temp, "%02x:%02x:%02x:%02x:%02x:%02x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); + for (i = 0; i < ETH_ALEN; i++) + buf[i] = mac[i] & 0xFF; + + return CHIP_NO_ERROR; } bool ConfigurationManagerImpl::CanFactoryReset() @@ -78,24 +94,40 @@ void ConfigurationManagerImpl::InitiateFactoryReset() PlatformMgr().ScheduleWork(DoFactoryReset); } -CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey, - uint32_t & value) +CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) { - // TODO - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + AmebaConfig::Key configKey{ kConfigNamespace_ChipCounters, key }; + + CHIP_ERROR err = ReadConfigValue(configKey, value); + if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } + return err; } -CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey, - uint32_t value) +CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) { - // TODO - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + AmebaConfig::Key configKey{ kConfigNamespace_ChipCounters, key }; + return WriteConfigValue(configKey, value); } void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) { - // TODO + CHIP_ERROR err; + + ChipLogProgress(DeviceLayer, "Performing factory reset"); + + // Erase all values in the chip-config NVS namespace. + err = ClearNamespace(kConfigNamespace_ChipConfig); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "ClearNamespace(ChipConfig) failed: %s", chip::ErrorStr(err)); + } + + // Restart the system. ChipLogProgress(DeviceLayer, "System restarting"); + // sys_reset(); } } // namespace DeviceLayer diff --git a/src/platform/Ameba/ConfigurationManagerImpl.h b/src/platform/Ameba/ConfigurationManagerImpl.h index 4dab60d474208e..8e1d02c55fc8c9 100644 --- a/src/platform/Ameba/ConfigurationManagerImpl.h +++ b/src/platform/Ameba/ConfigurationManagerImpl.h @@ -31,23 +31,23 @@ namespace chip { namespace DeviceLayer { -namespace Internal { -class NetworkProvisioningServerImpl; -} - /** * Concrete implementation of the ConfigurationManager singleton object for the Ameba platform. */ class ConfigurationManagerImpl final : public Internal::GenericConfigurationManagerImpl, private Internal::AmebaConfig { + // Allow the ConfigurationManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConfigurationManager; + +private: // Allow the GenericConfigurationManagerImpl base class to access helper methods and types // defined on this class. #ifndef DOXYGEN_SHOULD_SKIP_THIS friend class Internal::GenericConfigurationManagerImpl; #endif -private: // ===== Members that implement the ConfigurationManager public interface. CHIP_ERROR Init(void) override; @@ -61,7 +61,6 @@ class ConfigurationManagerImpl final : public Internal::GenericConfigurationMana // ===== Members for internal use by the following friends. - friend class Internal::NetworkProvisioningServerImpl; friend ConfigurationManager & ConfigurationMgr(void); friend ConfigurationManagerImpl & ConfigurationMgrImpl(void); diff --git a/src/platform/Ameba/ConnectivityManagerImpl.cpp b/src/platform/Ameba/ConnectivityManagerImpl.cpp index 1efed6cfa9ee5f..7518d9cdb7d621 100644 --- a/src/platform/Ameba/ConnectivityManagerImpl.cpp +++ b/src/platform/Ameba/ConnectivityManagerImpl.cpp @@ -36,7 +36,11 @@ #include #include +#include +#include + using namespace ::chip; +using namespace ::chip::Inet; using namespace ::chip::TLV; using namespace ::chip::DeviceLayer::Internal; @@ -45,27 +49,741 @@ namespace DeviceLayer { ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; -CHIP_ERROR ConnectivityManagerImpl::_Init() +ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void) +{ + if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) + { + mWiFiStationMode = (wifi_mode == RTW_MODE_STA) ? kWiFiStationMode_Enabled : kWiFiStationMode_Disabled; + } + return mWiFiStationMode; +} + +bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void) +{ + return GetWiFiStationMode() == kWiFiStationMode_Enabled; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val) { CHIP_ERROR err = CHIP_NO_ERROR; - // Initialize the generic base classes that require it. -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - GenericConnectivityManagerImpl_Thread::_Init(); -#endif + VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (val != kWiFiStationMode_ApplicationControlled) + { + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); + } - SuccessOrExit(err); + if (mWiFiStationMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi station mode change: %d -> %d", (mWiFiStationMode), (val)); + } + + mWiFiStationMode = val; exit: return err; } +bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void) +{ + rtw_wifi_setting_t mWiFiSetting; + CHIP_GetWiFiConfig(&mWiFiSetting); + return mWiFiSetting.ssid[0] != 0; +} + +void ConnectivityManagerImpl::_ClearWiFiStationProvision(void) +{ + // TBD +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (mWiFiAPMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val)); + } + + mWiFiAPMode = val; + + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + +exit: + return err; +} + +void ConnectivityManagerImpl::_DemandStartWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + mLastAPDemandTime = System::SystemClock().GetMonotonicMilliseconds(); + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +void ConnectivityManagerImpl::_StopOnDemandWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + mLastAPDemandTime = 0; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + if (mWiFiAPState == kWiFiAPState_Activating || mWiFiAPState == kWiFiAPState_Active) + { + mLastAPDemandTime = System::SystemClock().GetMonotonicMilliseconds(); + } + } +} + +void ConnectivityManagerImpl::_SetWiFiAPIdleTimeoutMS(uint32_t val) +{ + mWiFiAPIdleTimeoutMS = val; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); +} + +#define WIFI_BAND_2_4GHZ 2400 +#define WIFI_BAND_5_0GHZ 5000 + +static uint16_t Map2400MHz(const uint8_t inChannel) +{ + uint16_t frequency = 0; + + if (inChannel >= 1 && inChannel <= 13) + { + // Cast is OK because we definitely fit in 16 bits. + frequency = static_cast(2412 + ((inChannel - 1) * 5)); + } + else if (inChannel == 14) + { + frequency = 2484; + } + + return frequency; +} + +static uint16_t 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; +} + +static uint16_t MapFrequency(const uint16_t inBand, const uint8_t inChannel) +{ + uint16_t frequency = 0; + + if (inBand == WIFI_BAND_2_4GHZ) + { + frequency = Map2400MHz(inChannel); + } + else if (inBand == WIFI_BAND_5_0GHZ) + { + frequency = Map5000MHz(inChannel); + } + + return frequency; +} + +CHIP_ERROR ConnectivityManagerImpl::_GetAndLogWifiStatsCounters(void) +{ + return CHIP_NO_ERROR; +} + +// ==================== ConnectivityManager Platform Internal Methods ==================== + +CHIP_ERROR ConnectivityManagerImpl::_Init() +{ + mLastStationConnectFailTime = 0; + mLastAPDemandTime = 0; + mWiFiStationMode = kWiFiStationMode_Disabled; + mWiFiStationState = kWiFiStationState_NotConnected; + mWiFiAPMode = kWiFiAPMode_Disabled; + mWiFiAPState = kWiFiAPState_NotActive; + mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL; + mWiFiAPIdleTimeoutMS = CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT; + mFlags.SetRaw(0); + + // Ensure that station mode is enabled. + wifi_on(RTW_MODE_STA); + + // Ensure that station mode is enabled in the WiFi layer. + wifi_set_mode(RTW_MODE_STA); + ; + + // If there is no persistent station provision... + if (!IsWiFiStationProvisioned()) + { + // If the code has been compiled with a default WiFi station provision, configure that now. +#if !defined(CONFIG_DEFAULT_WIFI_SSID) + printf("%s %d pls define CONFIG_DEFAULT_WIFI_SSID\r\n", __func__, __LINE__); +#else + if (CONFIG_DEFAULT_WIFI_SSID[0] != 0) + { + ChipLogProgress(DeviceLayer, "Setting default WiFi station configuration (SSID: %s)", CONFIG_DEFAULT_WIFI_SSID); + + // Set a default station configuration. + rtw_wifi_setting_t wifiConfig; + + // Set the wifi configuration + memset(&wifiConfig, 0, sizeof(wifiConfig)); + memcpy(wifiConfig.ssid, CONFIG_DEFAULT_WIFI_SSID, strlen(CONFIG_DEFAULT_WIFI_SSID) + 1); + memcpy(wifiConfig.password, CONFIG_DEFAULT_WIFI_PASSWORD, strlen(CONFIG_DEFAULT_WIFI_PASSWORD) + 1); + wifiConfig.mode = RTW_MODE_STA; + + // Configure the WiFi interface. + int err = CHIP_SetWiFiConfig(&wifiConfig); + if (err != 0) + { + ChipLogError(DeviceLayer, "_Init _SetWiFiConfig() failed: %d", err); + } + + // Enable WiFi station mode. + ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Enabled)); + } + + // Otherwise, ensure WiFi station mode is disabled. + else + { + ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Disabled)); + } +#endif + } + + // Force AP mode off for now. + + // Queue work items to bootstrap the AP and station state machines once the Chip event loop is running. + ReturnErrorOnFailure(DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL)); + ReturnErrorOnFailure(DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL)); + + return CHIP_NO_ERROR; +} + void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) { // Forward the event to the generic base classes as needed. #if CHIP_DEVICE_CONFIG_ENABLE_THREAD GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event); +#else + if (event->Type == DeviceEventType::kRtkWiFiStationConnectedEvent) + { + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED"); + if (mWiFiStationState == kWiFiStationState_Connecting) + { + ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); + } + DriveStationState(); + DHCPProcess(); + } +#endif +} + +void ConnectivityManagerImpl::_OnWiFiScanDone() +{ + // Schedule a call to DriveStationState method in case a station connect attempt was + // deferred because the scan was in progress. + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +} + +void ConnectivityManagerImpl::_OnWiFiStationProvisionChange() +{ + // Schedule a call to the DriveStationState method to adjust the station state as needed. + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +} + +// ==================== ConnectivityManager Private Methods ==================== + +void ConnectivityManagerImpl::DriveStationState() +{ + bool stationConnected; + + GetWiFiStationMode(); + + // If the station interface is NOT under application control... + if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) + { + // Ensure that the WiFi layer is started. + wifi_on(RTW_MODE_STA); + + // Ensure that station mode is enabled in the WiFi layer. + wifi_set_mode(RTW_MODE_STA); + ; + } + + // Determine if the WiFi layer thinks the station interface is currently connected. + stationConnected = (wifi_is_connected_to_ap() == RTW_SUCCESS) ? 1 : 0; + + // If the station interface is currently connected ... + if (stationConnected) + { + // Advance the station state to Connected if it was previously NotConnected or + // a previously initiated connect attempt succeeded. + if (mWiFiStationState == kWiFiStationState_NotConnected || mWiFiStationState == kWiFiStationState_Connecting_Succeeded) + { + ChangeWiFiStationState(kWiFiStationState_Connected); + ChipLogProgress(DeviceLayer, "WiFi station interface connected"); + mLastStationConnectFailTime = 0; + OnStationConnected(); + } + + // If the WiFi station interface is no longer enabled, or no longer provisioned, + // disconnect the station from the AP, unless the WiFi station mode is currently + // under application control. + if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled && + (mWiFiStationMode != kWiFiStationMode_Enabled || !IsWiFiStationProvisioned())) + { + ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface"); + int err = wifi_disconnect(); + if (err != 0) + { + ChipLogError(DeviceLayer, "wifi_disconnect() failed: %s", err); + return; + } + + ChangeWiFiStationState(kWiFiStationState_Disconnecting); + } + } + + // Otherwise the station interface is NOT connected to an AP, so... + else + { + uint64_t now = System::SystemClock().GetMonotonicMilliseconds(); + + // Advance the station state to NotConnected if it was previously Connected or Disconnecting, + // or if a previous initiated connect attempt failed. + if (mWiFiStationState == kWiFiStationState_Connected || mWiFiStationState == kWiFiStationState_Disconnecting || + mWiFiStationState == kWiFiStationState_Connecting_Failed) + { + WiFiStationState prevState = mWiFiStationState; + ChangeWiFiStationState(kWiFiStationState_NotConnected); + if (prevState != kWiFiStationState_Connecting_Failed) + { + ChipLogProgress(DeviceLayer, "WiFi station interface disconnected"); + mLastStationConnectFailTime = 0; + OnStationDisconnected(); + } + else + { + mLastStationConnectFailTime = now; + } + } + // If the WiFi station interface is now enabled and provisioned (and by implication, + // not presently under application control), AND the system is not in the process of + // scanning, then... + if (mWiFiStationMode == kWiFiStationMode_Enabled && IsWiFiStationProvisioned()) + { + // Initiate a connection to the AP if we haven't done so before, or if enough + // time has passed since the last attempt. + if (mLastStationConnectFailTime == 0 || now >= mLastStationConnectFailTime + mWiFiStationReconnectIntervalMS) + { + ChipLogProgress(DeviceLayer, "Attempting to connect WiFi station interface"); + rtw_wifi_setting_t wifi_info; + CHIP_GetWiFiConfig(&wifi_info); + wifi_reg_event_handler(WIFI_EVENT_CONNECT, ConnectivityManagerImpl::RtkWiFiStationConnectedHandler, NULL); + wifi_connect((char *) wifi_info.ssid, RTW_SECURITY_WPA_WPA2_MIXED, (char *) wifi_info.password, + strlen((const char *) wifi_info.ssid), strlen((const char *) wifi_info.password), 0, NULL); + ChangeWiFiStationState(kWiFiStationState_Connecting); + } + + // Otherwise arrange another connection attempt at a suitable point in the future. + else + { + uint32_t timeToNextConnect = (uint32_t)((mLastStationConnectFailTime + mWiFiStationReconnectIntervalMS) - now); + + ChipLogProgress(DeviceLayer, "Next WiFi station reconnect in %" PRIu32 " ms", timeToNextConnect); + + ReturnOnFailure(DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(timeToNextConnect), + DriveStationState, NULL)); + } + } + } + + ChipLogProgress(DeviceLayer, "Done driving station state, nothing else to do..."); + // Kick-off any pending network scan that might have been deferred due to the activity + // of the WiFi station. +} + +void ConnectivityManagerImpl::OnStationConnected() +{ + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Established; + PlatformMgr().PostEventOrDie(&event); + + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::OnStationDisconnected() +{ + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Lost; + PlatformMgr().PostEventOrDie(&event); + + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::ChangeWiFiStationState(WiFiStationState newState) +{ + if (mWiFiStationState != newState) + { + ChipLogProgress(DeviceLayer, "WiFi station state change: %d -> %d", (mWiFiStationState), (newState)); + mWiFiStationState = newState; + } +} + +void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState) +{ + sInstance.DriveStationState(); +} + +void ConnectivityManagerImpl::DriveAPState() +{ + CHIP_ERROR err = CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() +{ + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState) +{ + if (mWiFiAPState != newState) + { + ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState)); + mWiFiAPState = newState; + } +} + +void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState) +{ + sInstance.DriveAPState(); +} + +void ConnectivityManagerImpl::UpdateInternetConnectivityState(void) +{ + bool haveIPv4Conn = false; + bool haveIPv6Conn = false; + const bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity); + const bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity); + IPAddress addr; + + // If the WiFi station is currently in the connected state... + if (mWiFiStationState == kWiFiStationState_Connected) + { + // Get the LwIP netif for the WiFi station interface. + struct netif * netif = &xnetif[0]; + + // If the WiFi station interface is up... + if (netif != NULL && netif_is_up(netif) && netif_is_link_up(netif)) + { + // Check if a DNS server is currently configured. If so... + ip_addr_t dnsServerAddr = *dns_getserver(0); + if (!ip_addr_isany_val(dnsServerAddr)) + { + // If the station interface has been assigned an IPv4 address, and has + // an IPv4 gateway, then presume that the device has IPv4 Internet + // connectivity. + if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) && !ip4_addr_isany_val(*netif_ip4_gw(netif))) + { + haveIPv4Conn = true; + char addrStr[INET_ADDRSTRLEN]; + ip4addr_ntoa_r((const ip4_addr_t *) LwIP_GetIP(&xnetif[0]), addrStr, sizeof(addrStr)); + IPAddress::FromString(addrStr, addr); + } + + // Search among the IPv6 addresses assigned to the interface for a Global Unicast + // address (2000::/3) that is in the valid state. If such an address is found... + for (uint8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) + { + if (ip6_addr_isglobal(netif_ip6_addr(netif, i)) && ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) + { + // Determine if there is a default IPv6 router that is currently reachable + // via the station interface. If so, presume for now that the device has + // IPv6 connectivity. + struct netif * found_if = nd6_find_route(IP6_ADDR_ANY6); + if (found_if && netif->num == found_if->num) + { + haveIPv6Conn = true; + } + } + } + } + } + } + + // If the internet connectivity state has changed... + if (haveIPv4Conn != hadIPv4Conn || haveIPv6Conn != hadIPv6Conn) + { + // Update the current state. + mFlags.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn) + .Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn); + + // Alert other components of the state change. + ChipDeviceEvent event; + event.Type = DeviceEventType::kInternetConnectivityChange; + event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn); + event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn); + addr.ToString(event.InternetConnectivityChange.address); + PlatformMgr().PostEventOrDie(&event); + + if (haveIPv4Conn != hadIPv4Conn) + { + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST"); + } + + if (haveIPv6Conn != hadIPv6Conn) + { + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST"); + } + } +} + +void ConnectivityManagerImpl::OnStationIPv4AddressAvailable(void) +{ + uint8_t * ip = LwIP_GetIP(&xnetif[0]); + uint8_t * gw = LwIP_GetGW(&xnetif[0]); + uint8_t * msk = LwIP_GetMASK(&xnetif[0]); +#if CHIP_PROGRESS_LOGGING + { + ChipLogProgress(DeviceLayer, "\n\r\tIP => %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + ChipLogProgress(DeviceLayer, "\n\r\tGW => %d.%d.%d.%d\n\r", gw[0], gw[1], gw[2], gw[3]); + ChipLogProgress(DeviceLayer, "\n\r\tmsk => %d.%d.%d.%d\n\r", msk[0], msk[1], msk[2], msk[3]); + } +#endif // CHIP_PROGRESS_LOGGING + + RefreshMessageLayer(); + + UpdateInternetConnectivityState(); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Assigned; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::OnStationIPv4AddressLost(void) +{ + ChipLogProgress(DeviceLayer, "IPv4 address lost on WiFi station interface"); + + RefreshMessageLayer(); + + UpdateInternetConnectivityState(); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Lost; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::OnIPv6AddressAvailable(void) +{ +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 +#if LWIP_IPV6 + uint8_t * ipv6_0 = LwIP_GetIPv6_linklocal(&xnetif[0]); + uint8_t * ipv6_1 = LwIP_GetIPv6_global(&xnetif[0]); +#endif +#endif +#if CHIP_PROGRESS_LOGGING + { +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 +#if LWIP_IPV6 + ChipLogProgress(DeviceLayer, + "\n\r\tLink-local IPV6 => %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ipv6_0[0], ipv6_0[1], ipv6_0[2], ipv6_0[3], ipv6_0[4], ipv6_0[5], ipv6_0[6], ipv6_0[7], ipv6_0[8], + ipv6_0[9], ipv6_0[10], ipv6_0[11], ipv6_0[12], ipv6_0[13], ipv6_0[14], ipv6_0[15]); + ChipLogProgress(DeviceLayer, + "\n\r\tIPV6 => %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ipv6_1[0], ipv6_1[1], ipv6_1[2], ipv6_1[3], ipv6_1[4], ipv6_1[5], ipv6_1[6], ipv6_1[7], ipv6_1[8], + ipv6_1[9], ipv6_1[10], ipv6_1[11], ipv6_1[12], ipv6_1[13], ipv6_1[14], ipv6_1[15]); +#endif #endif + } +#endif // CHIP_PROGRESS_LOGGING + + RefreshMessageLayer(); + + UpdateInternetConnectivityState(); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV6_Assigned; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::RefreshMessageLayer(void) {} + +void ConnectivityManagerImpl::RtkWiFiStationConnectedHandler(char * buf, int buf_len, int flags, void * userdata) +{ + ChipDeviceEvent event; + memset(&event, 0, sizeof(event)); + event.Type = DeviceEventType::kRtkWiFiStationConnectedEvent; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::DHCPProcessThread(void * param) +{ + LwIP_DHCP(0, DHCP_START); + PlatformMgr().LockChipStack(); + sInstance.OnStationIPv4AddressAvailable(); + PlatformMgr().UnlockChipStack(); +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 +#if LWIP_IPV6 + LwIP_DHCP6(0, DHCP6_START); + PlatformMgr().LockChipStack(); + sInstance.OnIPv6AddressAvailable(); + PlatformMgr().UnlockChipStack(); +#endif +#endif + vTaskDelete(NULL); +} + +void ConnectivityManagerImpl::DHCPProcess(void) +{ + xTaskCreate(DHCPProcessThread, "DHCPProcess", 4096 / sizeof(StackType_t), this, 1, NULL); } } // namespace DeviceLayer diff --git a/src/platform/Ameba/ConnectivityManagerImpl.h b/src/platform/Ameba/ConnectivityManagerImpl.h index 1b9f4a5e034175..c27c8ebd17c103 100644 --- a/src/platform/Ameba/ConnectivityManagerImpl.h +++ b/src/platform/Ameba/ConnectivityManagerImpl.h @@ -20,50 +20,66 @@ #include #include +#include #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE #include #else #include #endif -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD -#include -#else +#include #include -#endif -#include -namespace chip { +#include + namespace Inet { class IPAddress; } // namespace Inet -} // namespace chip namespace chip { namespace DeviceLayer { class ConnectivityManagerImpl final : public ConnectivityManager, public Internal::GenericConnectivityManagerImpl, + public Internal::GenericConnectivityManagerImpl_WiFi, #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE public Internal::GenericConnectivityManagerImpl_BLE, #else public Internal::GenericConnectivityManagerImpl_NoBLE, #endif -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - public Internal::GenericConnectivityManagerImpl_Thread, -#else - public Internal::GenericConnectivityManagerImpl_NoThread, -#endif - public Internal::GenericConnectivityManagerImpl_NoWiFi + public Internal::GenericConnectivityManagerImpl_NoThread { // Allow the ConnectivityManager interface class to delegate method calls to // the implementation methods provided by this class. friend class ConnectivityManager; private: + using Flags = GenericConnectivityManagerImpl_WiFi::ConnectivityFlags; // ===== Members that implement the ConnectivityManager abstract interface. + WiFiStationMode _GetWiFiStationMode(void); + CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val); + bool _IsWiFiStationEnabled(void); + bool _IsWiFiStationApplicationControlled(void); + bool _IsWiFiStationConnected(void); + uint32_t _GetWiFiStationReconnectIntervalMS(void); + CHIP_ERROR _SetWiFiStationReconnectIntervalMS(uint32_t val); + bool _IsWiFiStationProvisioned(void); + void _ClearWiFiStationProvision(void); + WiFiAPMode _GetWiFiAPMode(void); + CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); + bool _IsWiFiAPActive(void); + bool _IsWiFiAPApplicationControlled(void); + void _DemandStartWiFiAP(void); + void _StopOnDemandWiFiAP(void); + void _MaintainOnDemandWiFiAP(void); + uint32_t _GetWiFiAPIdleTimeoutMS(void); + void _SetWiFiAPIdleTimeoutMS(uint32_t val); + CHIP_ERROR _GetAndLogWifiStatsCounters(void); CHIP_ERROR _Init(void); void _OnPlatformEvent(const ChipDeviceEvent * event); + bool _CanStartWiFiScan(); + void _OnWiFiScanDone(); + void _OnWiFiStationProvisionChange(); // ===== Members for internal use by the following friends. @@ -71,8 +87,81 @@ class ConnectivityManagerImpl final : public ConnectivityManager, friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); static ConnectivityManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + + uint64_t mLastStationConnectFailTime; + uint64_t mLastAPDemandTime; + WiFiStationMode mWiFiStationMode; + WiFiStationState mWiFiStationState; + WiFiAPMode mWiFiAPMode; + WiFiAPState mWiFiAPState; + uint32_t mWiFiStationReconnectIntervalMS; + uint32_t mWiFiAPIdleTimeoutMS; + BitFlags mFlags; + + void DriveStationState(void); + void OnStationConnected(void); + void OnStationDisconnected(void); + void ChangeWiFiStationState(WiFiStationState newState); + static void DriveStationState(::chip::System::Layer * aLayer, void * aAppState); + + void DriveAPState(void); + CHIP_ERROR ConfigureWiFiAP(void); + void ChangeWiFiAPState(WiFiAPState newState); + static void DriveAPState(::chip::System::Layer * aLayer, void * aAppState); + + void UpdateInternetConnectivityState(void); + void OnStationIPv4AddressAvailable(void); + void OnStationIPv4AddressLost(void); + void OnIPv6AddressAvailable(void); + + static void RefreshMessageLayer(void); + static void RtkWiFiStationConnectedHandler(char * buf, int buf_len, int flags, void * userdata); + void DHCPProcess(void); + static void DHCPProcessThread(void * param); }; +inline bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void) +{ + return mWiFiStationMode == kWiFiStationMode_ApplicationControlled; +} + +inline bool ConnectivityManagerImpl::_IsWiFiStationConnected(void) +{ + return mWiFiStationState == kWiFiStationState_Connected; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled(void) +{ + return mWiFiAPMode == kWiFiAPMode_ApplicationControlled; +} + +inline uint32_t ConnectivityManagerImpl::_GetWiFiStationReconnectIntervalMS(void) +{ + return mWiFiStationReconnectIntervalMS; +} + +inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void) +{ + return mWiFiAPMode; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPActive(void) +{ + return mWiFiAPState == kWiFiAPState_Active; +} + +inline uint32_t ConnectivityManagerImpl::_GetWiFiAPIdleTimeoutMS(void) +{ + return mWiFiAPIdleTimeoutMS; +} + +inline bool ConnectivityManagerImpl::_CanStartWiFiScan() +{ + return mWiFiStationState != kWiFiStationState_Connecting; +} + /** * Returns the public interface of the ConnectivityManager singleton object. * diff --git a/src/platform/Ameba/DnssdImpl.cpp b/src/platform/Ameba/DnssdImpl.cpp new file mode 100755 index 00000000000000..f6f700e03c1ab7 --- /dev/null +++ b/src/platform/Ameba/DnssdImpl.cpp @@ -0,0 +1,112 @@ +/* + * + * Copyright (c) 2020 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 "lib/dnssd/platform/Dnssd.h" +#include "platform/CHIPDeviceLayer.h" +#include "support/CHIPMem.h" +#include "support/CodeUtils.h" +#include "support/logging/CHIPLogging.h" + +#include +#include +#include +#include + +extern struct netif xnetif[]; + +namespace { + +static constexpr uint32_t kTimeoutMilli = 3000; +static constexpr size_t kMaxResults = 20; + +} // namespace + +namespace chip { +namespace Dnssd { + +CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + int ameba_error = 0; + + ameba_error = mDNSResponderInit(); + VerifyOrExit(ameba_error == 0, error = CHIP_ERROR_INTERNAL); + +exit: + if (ameba_error != 0) + { + ChipLogError(DeviceLayer, "Ameba mdns internal error"); + } + initCallback(context, error); + + return error; +} + +const char * GetProtocolString(DnssdServiceProtocol protocol) +{ + return protocol == DnssdServiceProtocol::kDnssdProtocolTcp ? "_tcp" : "_udp"; +} + +CHIP_ERROR ChipDnssdPublishService(const DnssdService * service) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + + DNSServiceRef dnsServiceRef = NULL; + TXTRecordRef txtRecord; + unsigned char txt_buf[100]; + + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + + for (size_t i = 0; i < (service->mTextEntrySize); i++) + { + const char * value = reinterpret_cast(service->mTextEntries[i].mData); + TXTRecordSetValue(&txtRecord, service->mTextEntries[i].mKey, strlen(value), value); + } + + char * name = const_cast(service->mName); + char * service_type = strcat(strcat(const_cast(service->mType), "."), GetProtocolString(service->mProtocol)); + char * domain = "local"; + unsigned short port = service->mPort; + + dnsServiceRef = mDNSRegisterService(name, service_type, domain, port, &txtRecord); + VerifyOrExit(dnsServiceRef != NULL, error = CHIP_ERROR_INTERNAL); + +exit: + + return error; +} + +CHIP_ERROR ChipDnssdStopPublish() +{ + mDNSResponderDeinit(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, + chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context); +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR ChipDnssdResolve(DnssdService * /*service*/, chip::Inet::InterfaceId /*interface*/, DnssdResolveCallback /*callback*/, + void * /*context*/) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +} // namespace Dnssd +} // namespace chip diff --git a/src/platform/Ameba/InetPlatformConfig.h b/src/platform/Ameba/InetPlatformConfig.h index ab3ba9010176d7..3cb97a0c97b459 100755 --- a/src/platform/Ameba/InetPlatformConfig.h +++ b/src/platform/Ameba/InetPlatformConfig.h @@ -37,11 +37,11 @@ // NOTE: Values that are mapped to CONFIG_ #defines are settable via the Kconfig mechanism. #ifndef INET_CONFIG_NUM_TCP_ENDPOINTS -#define INET_CONFIG_NUM_TCP_ENDPOINTS 4 +#define INET_CONFIG_NUM_TCP_ENDPOINTS 10 #endif // INET_CONFIG_NUM_TCP_ENDPOINTS #ifndef INET_CONFIG_NUM_UDP_ENDPOINTS -#define INET_CONFIG_NUM_UDP_ENDPOINTS 4 +#define INET_CONFIG_NUM_UDP_ENDPOINTS 10 #endif // INET_CONFIG_NUM_UDP_ENDPOINTS #define INET_CONFIG_ENABLE_IPV4 1 diff --git a/src/platform/Ameba/KeyValueStoreManagerImpl.cpp b/src/platform/Ameba/KeyValueStoreManagerImpl.cpp new file mode 100755 index 00000000000000..e2b8afbefd4eec --- /dev/null +++ b/src/platform/Ameba/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,104 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * 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 + * Platform-specific key value storage implementation for Ameba + */ +/* this file behaves like a config.h, comes first */ +#include "chip_porting.h" +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, + size_t offset_bytes) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + int32_t ret = -1; + + if (!value) + { + return (err = CHIP_ERROR_INVALID_ARGUMENT); + } + + if (offset_bytes > 0) + { + // Offset and partial reads are not supported in nvs, for now just return NOT_IMPLEMENTED. Support can be added in the + // future if this is needed. + return (err = CHIP_ERROR_NOT_IMPLEMENTED); + } + + ret = getPref_bin_new(key, key, (uint8_t *) value, value_size, read_bytes_size); + + if (TRUE == ret) + { + err = CHIP_NO_ERROR; + if (read_bytes_size) + { + *read_bytes_size = value_size; + } + } + else + { + err = CHIP_ERROR_INTERNAL; + } + + return err; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + int32_t ret = -1; + + if (!value) + { + return (err = CHIP_ERROR_INVALID_ARGUMENT); + } + + ret = setPref_new(key, key, (uint8_t *) value, value_size); + + if (TRUE == ret) + err = CHIP_NO_ERROR; + else + err = CHIP_ERROR_INTERNAL; + + return err; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (TRUE == deleteKey(key, key)) + err = CHIP_NO_ERROR; + else + err = CHIP_ERROR_INTERNAL; + + return err; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Ameba/KeyValueStoreManagerImpl.h b/src/platform/Ameba/KeyValueStoreManagerImpl.h index 458a46be32895b..3b38413f0ac454 100755 --- a/src/platform/Ameba/KeyValueStoreManagerImpl.h +++ b/src/platform/Ameba/KeyValueStoreManagerImpl.h @@ -37,14 +37,11 @@ class KeyValueStoreManagerImpl final : public KeyValueStoreManager public: // NOTE: Currently this platform does not support partial and offset reads // these will return CHIP_ERROR_NOT_IMPLEMENTED. - CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) - { - return CHIP_ERROR_NOT_IMPLEMENTED; - } + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0); - CHIP_ERROR _Delete(const char * key) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _Delete(const char * key); - CHIP_ERROR _Put(const char * key, const void * value, size_t value_size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); private: // ===== Members for internal use by the following friends. @@ -65,6 +62,16 @@ inline KeyValueStoreManager & KeyValueStoreMgr(void) return KeyValueStoreManagerImpl::sInstance; } +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + } // namespace PersistedStorage } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Ameba/PlatformManagerImpl.cpp b/src/platform/Ameba/PlatformManagerImpl.cpp index 1bf6d2073a926d..07981d2ade2231 100644 --- a/src/platform/Ameba/PlatformManagerImpl.cpp +++ b/src/platform/Ameba/PlatformManagerImpl.cpp @@ -76,5 +76,22 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) return err; } +CHIP_ERROR PlatformManagerImpl::_GetCurrentHeapFree(uint64_t & currentHeapFree) +{ + currentHeapFree = xPortGetFreeHeapSize(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR PlatformManagerImpl::_GetCurrentHeapUsed(uint64_t & currentHeapUsed) +{ + currentHeapUsed = xPortGetTotalHeapSize() - xPortGetFreeHeapSize(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR PlatformManagerImpl::_GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) +{ + currentHeapHighWatermark = xPortGetTotalHeapSize() - xPortGetMinimumEverFreeHeapSize(); + return CHIP_NO_ERROR; +} } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Ameba/PlatformManagerImpl.h b/src/platform/Ameba/PlatformManagerImpl.h index 8c316db33df9d6..ba4839ec6e5217 100644 --- a/src/platform/Ameba/PlatformManagerImpl.h +++ b/src/platform/Ameba/PlatformManagerImpl.h @@ -53,6 +53,9 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener // ===== Methods that implement the PlatformManager abstract interface. CHIP_ERROR _InitChipStack(void); + CHIP_ERROR _GetCurrentHeapFree(uint64_t & currentHeapFree); + CHIP_ERROR _GetCurrentHeapUsed(uint64_t & currentHeapUsed); + CHIP_ERROR _GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark); // ===== Members for internal use by the following friends. diff --git a/src/platform/Ameba/ServiceProvisioning.cpp b/src/platform/Ameba/ServiceProvisioning.cpp index 411eed7cf47cc2..16ef3c85d2952d 100644 --- a/src/platform/Ameba/ServiceProvisioning.cpp +++ b/src/platform/Ameba/ServiceProvisioning.cpp @@ -22,11 +22,31 @@ #include "ServiceProvisioning.h" +#include + using namespace ::chip::DeviceLayer; CHIP_ERROR SetWiFiStationProvisioning(const char * ssid, const char * key) { - // TODO - printf("TODO : SetWiFiStationProvisioning\n"); + ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled); + rtw_wifi_setting_t wifiConfig; + + // Set the wifi configuration + memset(&wifiConfig, 0, sizeof(wifiConfig)); + memcpy(wifiConfig.ssid, ssid, strlen(ssid) + 1); + memcpy(wifiConfig.password, key, strlen(key) + 1); + wifiConfig.mode = RTW_MODE_STA; + + // Configure the WiFi interface. + int err = CHIP_SetWiFiConfig(&wifiConfig); + if (err != 0) + { + ChipLogError(DeviceLayer, "_SetWiFiConfig() failed: %d", err); + return CHIP_ERROR_INCORRECT_STATE; + } + + ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled); + ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled); + return CHIP_NO_ERROR; } diff --git a/src/platform/Ameba/SoftwareUpdateManagerImpl.h b/src/platform/Ameba/SoftwareUpdateManagerImpl.h new file mode 100755 index 00000000000000..c91f15d5c65860 --- /dev/null +++ b/src/platform/Ameba/SoftwareUpdateManagerImpl.h @@ -0,0 +1,89 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * 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 + +#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER + +#include +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the SoftwareUpdateManager singleton object for the + * Ameba platform. + */ +class SoftwareUpdateManagerImpl final : public SoftwareUpdateManager, + public Internal::GenericSoftwareUpdateManagerImpl, + public Internal::GenericSoftwareUpdateManagerImpl_BDX +{ + // Allow the SoftwareUpdateManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class SoftwareUpdateManager; + + // Allow the GenericSoftwareUpdateManagerImpl base class to access helper methods + // and types defined on this class. + friend class Internal::GenericSoftwareUpdateManagerImpl; + + // Allow the GenericSoftwareUpdateManagerImpl_BDX base class to access helper methods + // and types defined on this class. + friend class Internal::GenericSoftwareUpdateManagerImpl_BDX; + +public: + // ===== Members for internal use by the following friends. + + friend ::chip::DeviceLayer::SoftwareUpdateManager & SoftwareUpdateMgr(void); + friend SoftwareUpdateManagerImpl & SoftwareUpdateMgrImpl(void); + + static SoftwareUpdateManagerImpl sInstance; + +private: + // ===== Members that implement the SoftwareUpdateManager abstract interface. + + CHIP_ERROR _Init(void); +}; + +/** + * Returns a reference to the public interface of the SoftwareUpdateManager singleton object. + * + * Internal components should use this to access features of the SoftwareUpdateManager object + * that are common to all platforms. + */ +inline SoftwareUpdateManager & SoftwareUpdateMgr(void) +{ + return SoftwareUpdateManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the SoftwareUpdateManager singleton object. + * + * Internal components can use this to gain access to features of the SoftwareUpdateManager + * that are specific to the Ameba platform. + */ +inline SoftwareUpdateManagerImpl & SoftwareUpdateMgrImpl(void) +{ + return SoftwareUpdateManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_UPDATE_MANAGER diff --git a/src/platform/device.gni b/src/platform/device.gni index 79635e71ea6847..82ba57988caf69 100755 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -65,7 +65,8 @@ declare_args() { # Select DNS-SD implementation if (chip_device_platform == "linux" || chip_device_platform == "esp32" || - chip_device_platform == "mbed" || chip_device_platform == "p6") { + chip_device_platform == "mbed" || chip_device_platform == "p6" || + chip_device_platform == "ameba") { chip_mdns = "minimal" } else if (chip_device_platform == "darwin" || chip_device_platform == "cc13x2_26x2" || current_os == "android" ||