diff --git a/examples/chip-tool/commands/pairing/Commands.h b/examples/chip-tool/commands/pairing/Commands.h index 41a35bb6bae6ad..c202178657df7b 100644 --- a/examples/chip-tool/commands/pairing/Commands.h +++ b/examples/chip-tool/commands/pairing/Commands.h @@ -181,6 +181,16 @@ class PairSoftAP : public PairingCommand {} }; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +class PairWiFiPAF : public PairingCommand +{ +public: + PairWiFiPAF(CredentialIssuerCommands * credsIssuerConfig) : + PairingCommand("wifipaf-wifi", PairingMode::WiFiPAF, PairingNetworkType::WiFi, credsIssuerConfig) + {} +}; +#endif + class PairAlreadyDiscovered : public PairingCommand { public: @@ -243,6 +253,9 @@ void registerCommandsPairing(Commands & commands, CredentialIssuerCommands * cre make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + make_unique(credsIssuerConfig), +#endif make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 35ce2ba1cc7aaa..245c9ed57ff82c 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -80,6 +80,11 @@ CHIP_ERROR PairingCommand::RunInternal(NodeId remoteId) case PairingMode::SoftAP: err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort, mRemoteAddr.interfaceId)); break; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + case PairingMode::WiFiPAF: + err = Pair(remoteId, PeerAddress::WiFiPAF(remoteId)); + break; +#endif case PairingMode::AlreadyDiscovered: err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort, mRemoteAddr.interfaceId)); break; diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 0cf4e1de2de713..9965b663ec111c 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -35,6 +35,9 @@ enum class PairingMode CodePaseOnly, Ble, SoftAP, +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + WiFiPAF, +#endif AlreadyDiscovered, AlreadyDiscoveredByIndex, AlreadyDiscoveredByIndexWithCode, @@ -127,6 +130,13 @@ class PairingCommand : public CHIPCommand, AddArgument("device-remote-port", 0, UINT16_MAX, &mRemotePort); AddArgument("pase-only", 0, 1, &mPaseOnly); break; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + case PairingMode::WiFiPAF: + AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); + AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); + AddArgument("discriminator", 0, 4096, &mDiscriminator.emplace()); + break; +#endif case PairingMode::AlreadyDiscovered: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); diff --git a/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp index 7ab62c7da5101d..de1afad1835385 100644 --- a/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp +++ b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp @@ -108,6 +108,14 @@ CHIP_ERROR SetupPayloadParseCommand::Print(chip::SetupPayload payload) } humanFlags.Add("On IP network"); } + if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kWiFiPAF)) + { + if (!humanFlags.Empty()) + { + humanFlags.Add(", "); + } + humanFlags.Add("Wi-Fi PAF"); + } } else { diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 6a6deae1473084..307b3428126db2 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -367,12 +367,15 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions, #if CONFIG_NETWORK_LAYER_BLE RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kBLE; #else // CONFIG_NETWORK_LAYER_BLE - RendezvousInformationFlag rendezvousFlags = RendezvousInformationFlag::kOnNetwork; + RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kOnNetwork; #endif // CONFIG_NETWORK_LAYER_BLE #ifdef CONFIG_RENDEZVOUS_MODE rendezvousFlags = static_cast(CONFIG_RENDEZVOUS_MODE); #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + rendezvousFlags.Set(RendezvousInformationFlag::kWiFiPAF); +#endif err = Platform::MemoryInit(); SuccessOrExit(err); @@ -471,6 +474,20 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions, } } #endif // CHIP_DEVICE_CONFIG_ENABLE_WPA +#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + ChipLogProgress(NotSpecified, "WiFi-PAF: initialzing"); + if (LinuxDeviceOptions::GetInstance().mWiFi) + { + if (EnsureWiFiIsStarted()) + { + ChipLogProgress(NotSpecified, "Wi-Fi Management started"); + DeviceLayer::ConnectivityManager::WiFiPAFAdvertiseParam args; + args.enable = LinuxDeviceOptions::GetInstance().mWiFiPAF; + args.ExtCmds = LinuxDeviceOptions::GetInstance().mWiFiPAFExtCmds; + DeviceLayer::ConnectivityMgr().SetWiFiPAFAdvertisingEnabled(args); + } + } +#endif #if CHIP_ENABLE_OPENTHREAD if (LinuxDeviceOptions::GetInstance().mThread) diff --git a/examples/platform/linux/Options.cpp b/examples/platform/linux/Options.cpp index 9d6edc8bc43846..9b83d126c1f495 100644 --- a/examples/platform/linux/Options.cpp +++ b/examples/platform/linux/Options.cpp @@ -106,6 +106,9 @@ enum #if CHIP_WITH_NLFAULTINJECTION kDeviceOption_FaultInjection, #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + kDeviceOption_WiFi_PAF, +#endif }; constexpr unsigned kAppUsageLength = 64; @@ -117,6 +120,9 @@ OptionDef sDeviceOptionDefs[] = { #if CHIP_DEVICE_CONFIG_ENABLE_WIFI { "wifi", kNoArgument, kDeviceOption_WiFi }, { "wifi-supports-5g", kNoArgument, kDeviceOption_WiFiSupports5g }, +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + { "wifipaf", kArgumentRequired, kDeviceOption_WiFi_PAF }, +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF #endif // CHIP_DEVICE_CONFIG_ENABLE_WPA #if CHIP_ENABLE_OPENTHREAD { "thread", kNoArgument, kDeviceOption_Thread }, @@ -189,6 +195,12 @@ const char * sDeviceOptionHelp = " --wifi-supports-5g\n" " Indicate that local Wi-Fi hardware should report 5GHz support.\n" #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + "\n" + " --wifipaf freq_list=,... \n" + " Enable Wi-Fi PAF via wpa_supplicant.\n" + " Give an empty string if not setting freq_list: \"\"\n" +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAFs #if CHIP_ENABLE_OPENTHREAD "\n" " --thread\n" @@ -588,6 +600,13 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, } break; } +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + case kDeviceOption_WiFi_PAF: { + LinuxDeviceOptions::GetInstance().mWiFiPAF = true; + LinuxDeviceOptions::GetInstance().mWiFiPAFExtCmds = aValue; + break; + } #endif default: PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName); diff --git a/examples/platform/linux/Options.h b/examples/platform/linux/Options.h index 51e60f0ab63eca..f921bee4ced554 100644 --- a/examples/platform/linux/Options.h +++ b/examples/platform/linux/Options.h @@ -49,6 +49,10 @@ struct LinuxDeviceOptions bool wifiSupports5g = false; bool mWiFi = false; bool mThread = false; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + bool mWiFiPAF = false; + const char * mWiFiPAFExtCmds = nullptr; +#endif #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS uint16_t securedDevicePort = CHIP_PORT; uint16_t unsecuredCommissionerPort = CHIP_UDC_PORT; diff --git a/src/app/server/CommissioningWindowManager.cpp b/src/app/server/CommissioningWindowManager.cpp index 229fd67c5bb24b..47bc3e8ff97f07 100644 --- a/src/app/server/CommissioningWindowManager.cpp +++ b/src/app/server/CommissioningWindowManager.cpp @@ -71,6 +71,12 @@ void CommissioningWindowManager::OnPlatformEvent(const DeviceLayer::ChipDeviceEv #if CONFIG_NETWORK_LAYER_BLE && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION // If in NonConcurrentConnection, this will already have been completed mServer->GetBleLayerObject()->CloseAllBleConnections(); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + DeviceLayer::ConnectivityManager::WiFiPAFAdvertiseParam args; + args.enable = false; + args.ExtCmds = nullptr; + DeviceLayer::ConnectivityMgr().SetWiFiPAFAdvertisingEnabled(args); #endif } else if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 33f657f7ec1030..22cd274ba87e39 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -56,6 +56,10 @@ #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif + #if defined(CHIP_SUPPORT_ENABLE_STORAGE_API_AUDIT) || defined(CHIP_SUPPORT_ENABLE_STORAGE_LOAD_TEST_AUDIT) #include #endif // defined(CHIP_SUPPORT_ENABLE_STORAGE_API_AUDIT) || defined(CHIP_SUPPORT_ENABLE_STORAGE_LOAD_TEST_AUDIT) @@ -214,6 +218,10 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) TcpListenParameters(DeviceLayer::TCPEndPointManager()) .SetAddressType(IPAddressType::kIPv6) .SetListenPort(mOperationalServicePort) +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + , + Transport::WiFiPAFListenParameters(DeviceLayer::ConnectivityMgr().GetWiFiPAF()) #endif ); diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 9e0216877fea61..2f6126a4ace635 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -65,6 +65,9 @@ #if CONFIG_NETWORK_LAYER_BLE #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif #include #include #include @@ -104,6 +107,10 @@ using ServerTransportMgr = chip::TransportMgr +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + , + chip::Transport::WiFiPAFBase #endif >; diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 8232292479ff3f..0e83d7125cf175 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -590,11 +590,16 @@ CHIP_ERROR AutoCommissioner::StartCommissioning(DeviceCommissioner * commissione mStopCommissioning = false; mCommissioner = commissioner; mCommissioneeDeviceProxy = proxy; - mNeedsNetworkSetup = - mCommissioneeDeviceProxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress().GetTransportType() == - Transport::Type::kBle; + + auto transportType = + mCommissioneeDeviceProxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress().GetTransportType(); + mNeedsNetworkSetup = (transportType == Transport::Type::kBle); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + mNeedsNetworkSetup = mNeedsNetworkSetup || (transportType == Transport::Type::kWiFiPAF); +#endif CHIP_ERROR err = CHIP_NO_ERROR; CommissioningStage nextStage = GetNextCommissioningStage(CommissioningStage::kSecurePairing, err); + mCommissioner->PerformCommissioningStep(mCommissioneeDeviceProxy, nextStage, mParams, this, GetEndpoint(nextStage), GetCommandTimeout(mCommissioneeDeviceProxy, nextStage)); return CHIP_NO_ERROR; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 5212350c913696..955e36bfb0d8a2 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -66,6 +66,9 @@ #include #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif #include #include @@ -466,6 +469,13 @@ DeviceCommissioner::DeviceCommissioner() : mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this), mSetUpCodePairer(this) {} +DeviceCommissioner::~DeviceCommissioner() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + DeviceLayer::ConnectivityMgr().WiFiPAFCancelConnect(); +#endif +} + CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params) { VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -730,6 +740,12 @@ CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, Re peerAddress = Transport::PeerAddress::UDP(params.GetPeerAddress().GetIPAddress(), params.GetPeerAddress().GetPort(), params.GetPeerAddress().GetInterface()); } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + else if (params.GetPeerAddress().GetTransportType() == Transport::Type::kWiFiPAF) + { + peerAddress = Transport::PeerAddress::WiFiPAF(remoteDeviceId); + } +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF current = FindCommissioneeDevice(peerAddress); if (current != nullptr) @@ -804,6 +820,24 @@ CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, Re ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); } } +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + if (params.GetPeerAddress().GetTransportType() == Transport::Type::kWiFiPAF) + { + if (DeviceLayer::ConnectivityMgr().GetWiFiPAF()->GetWiFiPAFState() != Transport::WiFiPAFBase::State::kConnected) + { + ChipLogProgress(Controller, "WiFi-PAF: Subscribing the NAN-USD devices"); + if (!DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted()) + { + ChipLogError(Controller, "Wi-Fi Management should have be started now."); + ExitNow(CHIP_ERROR_INTERNAL); + } + mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = params; + DeviceLayer::ConnectivityMgr().WiFiPAFConnect(params.GetSetupDiscriminator().value(), (void *) this, + OnWiFiPAFSubscribeComplete, OnWiFiPAFSubscribeError); + ExitNow(CHIP_NO_ERROR); + } + } #endif session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress(), params.GetMRPConfig()); VerifyOrExit(session.HasValue(), err = CHIP_ERROR_NO_MEMORY); @@ -872,6 +906,43 @@ void DeviceCommissioner::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ER } #endif // CONFIG_NETWORK_LAYER_BLE +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +void DeviceCommissioner::OnWiFiPAFSubscribeComplete(void * appState) +{ + auto self = (DeviceCommissioner *) appState; + auto device = self->mDeviceInPASEEstablishment; + + if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kWiFiPAF) + { + ChipLogProgress(Controller, "WiFi-PAF: Subscription Completed, dev_id = %lu", device->GetDeviceId()); + auto remoteId = device->GetDeviceId(); + auto params = self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF; + + self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = RendezvousParameters(); + self->ReleaseCommissioneeDevice(device); + LogErrorOnFailure(self->EstablishPASEConnection(remoteId, params)); + } +} + +void DeviceCommissioner::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err) +{ + auto self = (DeviceCommissioner *) appState; + auto device = self->mDeviceInPASEEstablishment; + + if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kWiFiPAF) + { + ChipLogError(Controller, "WiFi-PAF: Subscription Error, id = %lu, err = %" CHIP_ERROR_FORMAT, device->GetDeviceId(), + err.Format()); + self->ReleaseCommissioneeDevice(device); + self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = RendezvousParameters(); + if (self->mPairingDelegate != nullptr) + { + self->mPairingDelegate->OnPairingComplete(err); + } + } +} +#endif + CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningParameters & params) { if (mDefaultCommissioner == nullptr) diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 1c4b490faa891a..4b876156199735 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -468,7 +468,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, { public: DeviceCommissioner(); - ~DeviceCommissioner() override {} + ~DeviceCommissioner() override; #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable /** @@ -847,6 +847,11 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, static void OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err); RendezvousParameters mRendezvousParametersForDeviceDiscoveredOverBle; #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + static void OnWiFiPAFSubscribeComplete(void * appState); + static void OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err); + RendezvousParameters mRendezvousParametersForDeviceDiscoveredOverWiFiPAF; +#endif static void OnBasicFailure(void * context, CHIP_ERROR err); static void OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &); diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp index 24f60ed9d8a50a..dbc55dd7b7327e 100644 --- a/src/controller/CHIPDeviceControllerFactory.cpp +++ b/src/controller/CHIPDeviceControllerFactory.cpp @@ -141,6 +141,9 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) #else stateParams.bleLayer = params.bleLayer; #endif // CONFIG_DEVICE_LAYER +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + stateParams.wifipaf_layer = params.wifipaf_layer; +#endif VerifyOrReturnError(stateParams.bleLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); #endif @@ -167,6 +170,10 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) Transport::TcpListenParameters(stateParams.tcpEndPointManager) .SetAddressType(IPAddressType::kIPv6) .SetListenPort(params.listenPort) +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + , + Transport::WiFiPAFListenParameters() #endif )); diff --git a/src/controller/CHIPDeviceControllerFactory.h b/src/controller/CHIPDeviceControllerFactory.h index 474357ec4a4bde..16e2ad487126b9 100644 --- a/src/controller/CHIPDeviceControllerFactory.h +++ b/src/controller/CHIPDeviceControllerFactory.h @@ -145,6 +145,9 @@ struct FactoryInitParams #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * bleLayer = nullptr; #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + Transport::WiFiPAFLayer * wifipaf_layer = nullptr; +#endif // // Controls enabling server cluster interactions on a controller. This in turn diff --git a/src/controller/CHIPDeviceControllerSystemState.h b/src/controller/CHIPDeviceControllerSystemState.h index da8f25a75d2541..e040ad14616431 100644 --- a/src/controller/CHIPDeviceControllerSystemState.h +++ b/src/controller/CHIPDeviceControllerSystemState.h @@ -52,10 +52,16 @@ #include #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif namespace chip { inline constexpr size_t kMaxDeviceTransportBlePendingPackets = 1; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +inline constexpr size_t kMaxDeviceTransportWiFiPAFPendingPackets = 1; +#endif #if INET_CONFIG_ENABLE_TCP_ENDPOINT inline constexpr size_t kMaxDeviceTransportTcpActiveConnectionCount = CHIP_CONFIG_MAX_ACTIVE_TCP_CONNECTIONS; @@ -76,6 +82,10 @@ using DeviceTransportMgr = #if INET_CONFIG_ENABLE_TCP_ENDPOINT , Transport::TCP +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + , + Transport::WiFiPAF /* WiFiPAF */ #endif >; @@ -93,6 +103,9 @@ struct DeviceControllerSystemStateParams FabricTable * fabricTable = nullptr; #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * bleLayer = nullptr; +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + Transport::WiFiPAFLayer * wifipaf_layer = nullptr; #endif Credentials::GroupDataProvider * groupDataProvider = nullptr; Crypto::SessionKeystore * sessionKeystore = nullptr; diff --git a/src/controller/SetUpCodePairer.cpp b/src/controller/SetUpCodePairer.cpp index 17f2e5945eb1bf..99e991dfe8c114 100644 --- a/src/controller/SetUpCodePairer.cpp +++ b/src/controller/SetUpCodePairer.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,13 @@ CHIP_ERROR GetPayload(const char * setUpCode, SetupPayload & payload) } } // namespace +SetUpCodePairer::~SetUpCodePairer() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + DeviceLayer::ConnectivityMgr().WiFiPAFCancelConnect(); +#endif +} + CHIP_ERROR SetUpCodePairer::PairDevice(NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour commission, DiscoveryType discoveryType, Optional resolutionData) { @@ -129,6 +137,15 @@ CHIP_ERROR SetUpCodePairer::Connect(SetupPayload & payload) } VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err || CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err, err); } + if (searchOverAll || payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kWiFiPAF)) + { + ChipLogProgress(Controller, "WiFi-PAF: has RendezvousInformationFlag::kWiFiPAF"); + if (CHIP_NO_ERROR == (err = StartDiscoverOverWiFiPAF(payload))) + { + isRunning = true; + } + VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err || CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err, err); + } } // We always want to search on network because any node that has already been commissioned will use on-network regardless of the @@ -243,6 +260,31 @@ CHIP_ERROR SetUpCodePairer::StopConnectOverSoftAP() return CHIP_NO_ERROR; } +CHIP_ERROR SetUpCodePairer::StartDiscoverOverWiFiPAF(SetupPayload & payload) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + ChipLogProgress(Controller, "Starting commissioning discovery over WiFiPAF"); + VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); + mWaitingForDiscovery[kWiFiPAFTransport] = true; + CHIP_ERROR err = DeviceLayer::ConnectivityMgr().WiFiPAFConnect(payload.discriminator, (void *) this, OnWiFiPAFSubscribeComplete, + OnWiFiPAFSubscribeError); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Commissioning discovery over WiFiPAF failed, err = %" CHIP_ERROR_FORMAT, err.Format()); + mWaitingForDiscovery[kWiFiPAFTransport] = false; + } + return err; +#else + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif // CONFIG_NETWORK_LAYER_BLE +} + +CHIP_ERROR SetUpCodePairer::StopConnectOverWiFiPAF() +{ + mWaitingForDiscovery[kWiFiPAFTransport] = false; + return CHIP_NO_ERROR; +} + bool SetUpCodePairer::ConnectToDiscoveredDevice() { if (mWaitingForPASE) @@ -335,6 +377,37 @@ void SetUpCodePairer::OnBLEDiscoveryError(CHIP_ERROR err) } #endif // CONFIG_NETWORK_LAYER_BLE +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +void SetUpCodePairer::OnDiscoveredDeviceOverWifiPAF() +{ + ChipLogProgress(Controller, "Discovered device to be commissioned over WiFiPAF, RemoteId: %lu", mRemoteId); + + mWaitingForDiscovery[kWiFiPAFTransport] = false; + auto param = SetUpCodePairerParameters(); + param.SetPeerAddress(Transport::PeerAddress(Transport::Type::kWiFiPAF, mRemoteId)); + mDiscoveredParameters.emplace_back(param); + ConnectToDiscoveredDevice(); +} + +void SetUpCodePairer::OnWifiPAFDiscoveryError(CHIP_ERROR err) +{ + ChipLogError(Controller, "Commissioning discovery over WiFiPAF failed: %" CHIP_ERROR_FORMAT, err.Format()); + mWaitingForDiscovery[kWiFiPAFTransport] = false; +} + +void SetUpCodePairer::OnWiFiPAFSubscribeComplete(void * appState) +{ + auto self = (SetUpCodePairer *) appState; + self->OnDiscoveredDeviceOverWifiPAF(); +} + +void SetUpCodePairer::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err) +{ + auto self = (SetUpCodePairer *) appState; + self->OnWifiPAFDiscoveryError(err); +} +#endif + bool SetUpCodePairer::IdIsPresent(uint16_t vendorOrProductID) { return vendorOrProductID != kNotAvailable; @@ -473,6 +546,7 @@ void SetUpCodePairer::ResetDiscoveryState() StopConnectOverBle(); StopConnectOverIP(); StopConnectOverSoftAP(); + StopConnectOverWiFiPAF(); // Just in case any of those failed to reset the waiting state properly. for (auto & waiting : mWaitingForDiscovery) diff --git a/src/controller/SetUpCodePairer.h b/src/controller/SetUpCodePairer.h index e177af7322d391..3414341a2cdd51 100644 --- a/src/controller/SetUpCodePairer.h +++ b/src/controller/SetUpCodePairer.h @@ -77,7 +77,7 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate { public: SetUpCodePairer(DeviceCommissioner * commissioner) : mCommissioner(commissioner) {} - virtual ~SetUpCodePairer() {} + ~SetUpCodePairer(); CHIP_ERROR PairDevice(chip::NodeId remoteId, const char * setUpCode, SetupCodePairerBehaviour connectionType = SetupCodePairerBehaviour::kCommission, @@ -111,6 +111,8 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate CHIP_ERROR StopConnectOverIP(); CHIP_ERROR StartDiscoverOverSoftAP(SetupPayload & payload); CHIP_ERROR StopConnectOverSoftAP(); + CHIP_ERROR StartDiscoverOverWiFiPAF(SetupPayload & payload); + CHIP_ERROR StopConnectOverWiFiPAF(); // Returns whether we have kicked off a new connection attempt. bool ConnectToDiscoveredDevice(); @@ -150,6 +152,7 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate kBLETransport = 0, kIPTransport, kSoftAPTransport, + kWiFiPAFTransport, kTransportTypeCount, }; @@ -165,6 +168,12 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate static void OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj); static void OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err); #endif // CONFIG_NETWORK_LAYER_BLE +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + void OnDiscoveredDeviceOverWifiPAF(); + void OnWifiPAFDiscoveryError(CHIP_ERROR err); + static void OnWiFiPAFSubscribeComplete(void * appState); + static void OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err); +#endif bool NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) const; static bool IdIsPresent(uint16_t vendorOrProductID); diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 49a94d75c23fcc..bc13696c8c36a2 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -425,6 +425,15 @@ #define CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME "wlan0" #endif +/** + * CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + * + * Enable support for commissioning using Wi-Fi Public Action Frame as the transport. + */ +#ifndef CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#define CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF 0 +#endif + // -------------------- WiFi AP Configuration -------------------- /** diff --git a/src/include/platform/CHIPDeviceEvent.h b/src/include/platform/CHIPDeviceEvent.h index 437b20e670284f..09f4c46b652920 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -281,7 +281,9 @@ enum InternalEventTypes * This event should populate CHIPoBLEConnectionError structure. */ kCHIPoBLEConnectionError, - kCHIPoBLENotifyConfirm + kCHIPoBLENotifyConfirm, + kCHIPoWiFiPAFWriteReceived, + kCHIPoWiFiPAFConnected, }; static_assert(kEventTypeNotSet == 0, "kEventTypeNotSet must be defined as 0"); @@ -491,6 +493,12 @@ struct ChipDeviceEvent final { BLE_CONNECTION_OBJECT ConId; } CHIPoBLENotifyConfirm; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + struct + { + chip::System::PacketBuffer * Data; + } CHIPoWiFiPAFWriteReceived; +#endif struct { bool RoleChanged : 1; diff --git a/src/include/platform/ConnectivityManager.h b/src/include/platform/ConnectivityManager.h index 817019b3c1c63c..209d7484b92bda 100644 --- a/src/include/platform/ConnectivityManager.h +++ b/src/include/platform/ConnectivityManager.h @@ -35,6 +35,9 @@ #if INET_CONFIG_ENABLE_TCP_ENDPOINT #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif namespace chip { @@ -171,6 +174,19 @@ class ConnectivityManager bool IsWiFiStationProvisioned(); void ClearWiFiStationProvision(); CHIP_ERROR GetAndLogWiFiStatsCounters(); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + struct WiFiPAFAdvertiseParam; + + CHIP_ERROR SetWiFiPAFAdvertisingEnabled(WiFiPAFAdvertiseParam & args); + typedef void (*OnConnectionCompleteFunct)(void * appState); + typedef void (*OnConnectionErrorFunct)(void * appState, CHIP_ERROR err); + CHIP_ERROR WiFiPAFConnect(const SetupDiscriminator & connDiscriminator, void * appState, OnConnectionCompleteFunct onSuccess, + OnConnectionErrorFunct onError); + CHIP_ERROR WiFiPAFCancelConnect(); + CHIP_ERROR WiFiPAFSend(System::PacketBufferHandle && msgBuf); + Transport::WiFiPAFBase * GetWiFiPAF(); + void SetWiFiPAF(Transport::WiFiPAFBase * pmWiFiPAF); +#endif // WiFi AP methods WiFiAPMode GetWiFiAPMode(); @@ -268,6 +284,16 @@ struct ConnectivityManager::SEDIntervalsConfig System::Clock::Milliseconds32 IdleIntervalMS; }; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +struct ConnectivityManager::WiFiPAFAdvertiseParam +{ + /* To enable/disable WiFiPAF Commissioning */ + bool enable; + /* The optional commands */ + const char * ExtCmds; +}; +#endif + /** * Returns a reference to the public interface of the ConnectivityManager singleton object. * @@ -407,6 +433,29 @@ inline CHIP_ERROR ConnectivityManager::GetAndLogWiFiStatsCounters() return static_cast(this)->_GetAndLogWiFiStatsCounters(); } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +inline CHIP_ERROR ConnectivityManager::SetWiFiPAFAdvertisingEnabled(WiFiPAFAdvertiseParam & args) +{ + return static_cast(this)->_SetWiFiPAFAdvertisingEnabled(args); +} + +inline CHIP_ERROR ConnectivityManager::WiFiPAFConnect(const SetupDiscriminator & connDiscriminator, void * appState, + OnConnectionCompleteFunct onSuccess, OnConnectionErrorFunct onError) +{ + return static_cast(this)->_WiFiPAFConnect(connDiscriminator, appState, onSuccess, onError); +} + +inline CHIP_ERROR ConnectivityManager::WiFiPAFCancelConnect() +{ + return static_cast(this)->_WiFiPAFCancelConnect(); +} + +inline CHIP_ERROR ConnectivityManager::WiFiPAFSend(chip::System::PacketBufferHandle && msgBuf) +{ + return static_cast(this)->_WiFiPAFSend(std::move(msgBuf)); +} +#endif + inline bool ConnectivityManager::IsThreadEnabled() { return static_cast(this)->_IsThreadEnabled(); @@ -451,6 +500,18 @@ inline void ConnectivityManager::ResetThreadNetworkDiagnosticsCounts() static_cast(this)->_ResetThreadNetworkDiagnosticsCounts(); } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +inline Transport::WiFiPAFBase * ConnectivityManager::GetWiFiPAF() +{ + return static_cast(this)->_GetWiFiPAF(); +} + +inline void ConnectivityManager::SetWiFiPAF(Transport::WiFiPAFBase * pWiFiPAF) +{ + return static_cast(this)->_SetWiFiPAF(pWiFiPAF); +} +#endif + inline Ble::BleLayer * ConnectivityManager::GetBleLayer() { return static_cast(this)->_GetBleLayer(); diff --git a/src/lib/shell/commands/OnboardingCodes.cpp b/src/lib/shell/commands/OnboardingCodes.cpp index 1e17812d183a3f..a08a63be68770f 100644 --- a/src/lib/shell/commands/OnboardingCodes.cpp +++ b/src/lib/shell/commands/OnboardingCodes.cpp @@ -128,6 +128,13 @@ static CHIP_ERROR RendezvousStringToFlag(char * str, chip::RendezvousInformation *aRendezvousFlags = chip::RendezvousInformationFlag::kOnNetwork; return CHIP_NO_ERROR; } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + if (strcmp(str, "wifipaf") == 0) + { + *aRendezvousFlags = chip::RendezvousInformationFlag::kWiFiPAF; + return CHIP_NO_ERROR; + } +#endif return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 474e3c17ce284b..38becc7ede7471 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -140,6 +140,7 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER=${chip_use_transitional_commissionable_data_provider}", "CHIP_USE_TRANSITIONAL_DEVICE_INSTANCE_INFO_PROVIDER=${chip_use_transitional_device_instance_info_provider}", "CHIP_DEVICE_CONFIG_ENABLE_DYNAMIC_MRP_CONFIG=${chip_device_config_enable_dynamic_mrp_config}", + "CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF=${chip_device_config_enable_wifipaf}", ] if (chip_device_platform == "linux" || chip_device_platform == "darwin" || diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index cd3922baaf2b02..0ba16f90d874a9 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,9 @@ #include #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif #endif using namespace ::chip; @@ -152,6 +156,22 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) #if CHIP_DEVICE_CONFIG_ENABLE_THREAD GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event); #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + switch (event->Type) + { + case DeviceEventType::kCHIPoWiFiPAFWriteReceived: + ChipLogProgress(DeviceLayer, "WiFi-PAF: event: kCHIPoWiFiPAFWriteReceived"); + _GetWiFiPAF()->OnWiFiPAFMessageReceived(System::PacketBufferHandle::Adopt(event->CHIPoWiFiPAFWriteReceived.Data)); + break; + case DeviceEventType::kCHIPoWiFiPAFConnected: + ChipLogProgress(DeviceLayer, "WiFi-PAF: event: kCHIPoWiFiPAFConnected"); + if (mOnPafSubscribeComplete != nullptr) + { + mOnPafSubscribeComplete(mAppState); + } + break; + } +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF } #if CHIP_DEVICE_CONFIG_ENABLE_WPA @@ -797,6 +817,113 @@ bool ConnectivityManagerImpl::IsWiFiManagementStarted() return ret; } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +const char srv_name[] = "_matterc._udp"; +/* + NAN-USD Service Protocol Type: ref: Table 58 of Wi-Fi Aware Specificaiton +*/ +#define MAX_PAF_PUBLISH_SSI_BUFLEN 512 +#define MAX_PAF_TX_SSI_BUFLEN 2048 +#define NAN_SRV_PROTO_MATTER 3 +#define NAM_PUBLISH_PERIOD 300u +#define NAN_PUBLISH_SSI_TAG " ssi=" + +#pragma pack(push, 1) +struct PAFPublishSSI +{ + uint8_t DevOpCode; + uint16_t DevInfo; + uint16_t ProductId; + uint16_t VendorId; +}; +#pragma pack(pop) +CHIP_ERROR ConnectivityManagerImpl::_WiFiPAFPublish(ConnectivityManager::WiFiPAFAdvertiseParam & InArgs) +{ + CHIP_ERROR ret; + GAutoPtr err; + gchar args[MAX_PAF_PUBLISH_SSI_BUFLEN]; + gint publish_id; + size_t req_len; + + snprintf(args, sizeof(args), "service_name=%s srv_proto_type=%u ttl=%u ", srv_name, NAN_SRV_PROTO_MATTER, NAM_PUBLISH_PERIOD); + req_len = strlen(args) + strlen(InArgs.ExtCmds); + if ((InArgs.ExtCmds != nullptr) && (MAX_PAF_PUBLISH_SSI_BUFLEN > req_len)) + { + strcat(args, InArgs.ExtCmds); + } + else + { + ChipLogError(DeviceLayer, "Input cmd is too long: limit:%d, req: %lu", MAX_PAF_PUBLISH_SSI_BUFLEN, req_len); + } + + struct PAFPublishSSI PafPublish_ssi; + VerifyOrReturnError( + (strlen(args) + strlen(NAN_PUBLISH_SSI_TAG) + (sizeof(struct PAFPublishSSI) * 2) < MAX_PAF_PUBLISH_SSI_BUFLEN), + CHIP_ERROR_BUFFER_TOO_SMALL); + PafPublish_ssi.DevOpCode = 0; + VerifyOrDie(DeviceLayer::GetCommissionableDataProvider()->GetSetupDiscriminator(PafPublish_ssi.DevInfo) == CHIP_NO_ERROR); + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(PafPublish_ssi.ProductId) != CHIP_NO_ERROR) + { + PafPublish_ssi.ProductId = 0; + } + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(PafPublish_ssi.VendorId) != CHIP_NO_ERROR) + { + PafPublish_ssi.VendorId = 0; + } + if (MAX_PAF_PUBLISH_SSI_BUFLEN > strlen(args) + strlen(NAN_PUBLISH_SSI_TAG)) + { + strcat(args, NAN_PUBLISH_SSI_TAG); + } + ret = Encoding::BytesToUppercaseHexString((uint8_t *) &PafPublish_ssi, sizeof(PafPublish_ssi), &args[strlen(args)], + MAX_PAF_PUBLISH_SSI_BUFLEN - strlen(args)); + VerifyOrReturnError(ret == CHIP_NO_ERROR, ret); + ChipLogProgress(DeviceLayer, "WiFi-PAF: publish: [%s]", args); + wpa_fi_w1_wpa_supplicant1_interface_call_nanpublish_sync(mWpaSupplicant.iface, args, &publish_id, nullptr, &err.GetReceiver()); + ChipLogProgress(DeviceLayer, "WiFi-PAF: publish_id: %d ! ", publish_id); + + g_signal_connect(mWpaSupplicant.iface, "nan-receive", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * obj, ConnectivityManagerImpl * self) { + return self->OnNanReceive(obj); + }), + this); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_WiFiPAFCancelPublish() +{ + GAutoPtr err; + gchar args[MAX_PAF_PUBLISH_SSI_BUFLEN]; + + ChipLogProgress(DeviceLayer, "WiFi-PAF: cancel publish_id: %d ! ", mpaf_info.peer_publish_id); + snprintf(args, sizeof(args), "publish_id=%d", mpaf_info.peer_publish_id); + wpa_fi_w1_wpa_supplicant1_interface_call_nancancel_publish_sync(mWpaSupplicant.iface, args, nullptr, &err.GetReceiver()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiPAFAdvertisingEnabled(WiFiPAFAdvertiseParam & args) +{ + if (args.enable == true) + { + return _WiFiPAFPublish(args); + } + else + { + return _WiFiPAFCancelPublish(); + } +} + +Transport::WiFiPAFBase * ConnectivityManagerImpl::_GetWiFiPAF() +{ + return pmWiFiPAF; +} + +void ConnectivityManagerImpl::_SetWiFiPAF(Transport::WiFiPAFBase * pWiFiPAF) +{ + pmWiFiPAF = pWiFiPAF; + return; +} +#endif + void ConnectivityManagerImpl::StartNonConcurrentWiFiManagement() { StartWiFiManagement(); @@ -1226,6 +1353,229 @@ CHIP_ERROR ConnectivityManagerImpl::ConnectWiFiNetworkWithPDCAsync( return _ConnectWiFiNetworkAsync(args, connectCallback); } #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +/* + NAN-USD Service Protocol Type: ref: Table 58 of Wi-Fi Aware Specificaiton +*/ +#define MAX_PAF_SUBSCRIBE_SSI_BUFLEN 128 +#define NAN_SRV_PROTO_MATTER 3 +#define NAM_SUBSCRIBE_PERIOD 30u +void ConnectivityManagerImpl::OnDiscoveryResult(gboolean success, GVariant * discov_info) +{ + ChipLogProgress(Controller, "WiFi-PAF: OnDiscoveryResult, %d", success); + + std::lock_guard lock(mWpaSupplicantMutex); + if (g_variant_n_children(discov_info) == 0) + { + return; + } + + if (success == true) + { + GAutoPtr dataValue(g_variant_lookup_value(discov_info, "discov_info", G_VARIANT_TYPE_BYTESTRING)); + size_t bufferLen; + auto buffer = g_variant_get_fixed_array(dataValue.get(), &bufferLen, sizeof(uint8_t)); + if (((struct wpa_dbus_discov_info *) buffer)->subscribe_id == mpaf_info.subscribe_id) + { + return; + } + memcpy(&mpaf_info, buffer, sizeof(struct wpa_dbus_discov_info)); + ChipLogProgress(DeviceLayer, "WiFi-PAF: subscribe_id: %u", mpaf_info.subscribe_id); + ChipLogProgress(DeviceLayer, "WiFi-PAF: peer_publish_id: %u", mpaf_info.peer_publish_id); + ChipLogProgress(DeviceLayer, "WiFi-PAF: peer_addr: [%02x:%02x:%02x:%02x:%02x:%02x]", mpaf_info.peer_addr[0], + mpaf_info.peer_addr[1], mpaf_info.peer_addr[2], mpaf_info.peer_addr[3], mpaf_info.peer_addr[4], + mpaf_info.peer_addr[5]); + GetWiFiPAF()->SetWiFiPAFState(Transport::WiFiPAFBase::State::kConnected); + + // Read the ssi + GAutoPtr ssiValue(g_variant_lookup_value(discov_info, "ssi", G_VARIANT_TYPE_BYTESTRING)); + size_t ssiBufLen; + g_variant_get_fixed_array(ssiValue.get(), &ssiBufLen, sizeof(uint8_t)); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoWiFiPAFConnected; + PlatformMgr().PostEventOrDie(&event); + } + else + { + GetWiFiPAF()->SetWiFiPAFState(Transport::WiFiPAFBase::State::kInitialized); + if (mOnPafSubscribeError != nullptr) + { + mOnPafSubscribeError(mAppState, CHIP_ERROR_TIMEOUT); + } + } + + return; +} + +void ConnectivityManagerImpl::OnNanReceive(GVariant * obj) +{ + if (g_variant_n_children(obj) == 0) + { + return; + } + // Read the rx_info + GAutoPtr dataValueInfo(g_variant_lookup_value(obj, "nanrx_info", G_VARIANT_TYPE_BYTESTRING)); + size_t infoBufferLen; + auto infoBuffer = g_variant_get_fixed_array(dataValueInfo.get(), &infoBufferLen, sizeof(uint8_t)); + + memcpy(&mpaf_nanrx_info, infoBuffer, sizeof(struct wpa_dbus_nanrx_info)); + mpaf_info.subscribe_id = mpaf_nanrx_info.id; + mpaf_info.peer_publish_id = mpaf_nanrx_info.peer_id; + memcpy(mpaf_info.peer_addr, mpaf_nanrx_info.peer_addr, 6); + if (mpaf_nanrx_info.ssi_len == 0) + { + return; + } + // Read the rx_data + GAutoPtr dataValue(g_variant_lookup_value(obj, "ssi", G_VARIANT_TYPE_BYTESTRING)); + size_t bufferLen; + System::PacketBufferHandle buf; + auto rxbuf = g_variant_get_fixed_array(dataValue.get(), &bufferLen, sizeof(uint8_t)); + ChipLogProgress(DeviceLayer, "WiFi-PAF: wpa_supplicant: nan-rx: [len: %lu]", bufferLen); + buf = System::PacketBufferHandle::NewWithData(rxbuf, bufferLen); + + // Post an event to the Chip queue to deliver the data into the Chip stack. + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoWiFiPAFWriteReceived; + event.CHIPoWiFiPAFWriteReceived.Data = std::move(buf).UnsafeRelease(); + PlatformMgr().PostEventOrDie(&event); + + return; +} + +void ConnectivityManagerImpl::OnNanSubscribeTerminated(gint term_subscribe_id, gint reason) +{ + ChipLogProgress(Controller, "WiFi-PAF: Subscription terminated (%d, %d)", term_subscribe_id, reason); + if (mpresubscribe_id == (uint32_t) term_subscribe_id) + { + mpresubscribe_id = 0; + } + if (mpaf_info.subscribe_id == (uint32_t) term_subscribe_id) + { + mpaf_info.subscribe_id = 0; + } + return; +} + +CHIP_ERROR ConnectivityManagerImpl::_WiFiPAFConnect(const SetupDiscriminator & connDiscriminator, void * appState, + OnConnectionCompleteFunct onSuccess, OnConnectionErrorFunct onError) +{ + ChipLogProgress(Controller, "WiFi-PAF: Try to subscribe the NAN-USD devices"); + gchar args[MAX_PAF_SUBSCRIBE_SSI_BUFLEN]; + gint subscribe_id; + snprintf(args, sizeof(args), "service_name=%s srv_proto_type=%u ttl=%u ", srv_name, NAN_SRV_PROTO_MATTER, NAM_SUBSCRIBE_PERIOD); + GAutoPtr err; + CHIP_ERROR ret; + struct PAFPublishSSI PafPublish_ssi; + + VerifyOrReturnError( + (strlen(args) + strlen(NAN_PUBLISH_SSI_TAG) + (sizeof(struct PAFPublishSSI) * 2) < MAX_PAF_PUBLISH_SSI_BUFLEN), + CHIP_ERROR_BUFFER_TOO_SMALL); + mAppState = appState; + PafPublish_ssi.DevOpCode = 0; + PafPublish_ssi.DevInfo = connDiscriminator.GetLongValue(); + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(PafPublish_ssi.ProductId) != CHIP_NO_ERROR) + { + PafPublish_ssi.ProductId = 0; + } + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(PafPublish_ssi.VendorId) != CHIP_NO_ERROR) + { + PafPublish_ssi.VendorId = 0; + } + strcat(args, NAN_PUBLISH_SSI_TAG); + ret = Encoding::BytesToUppercaseHexString((uint8_t *) &PafPublish_ssi, sizeof(PafPublish_ssi), &args[strlen(args)], + MAX_PAF_PUBLISH_SSI_BUFLEN - strlen(args)); + VerifyOrReturnError(ret == CHIP_NO_ERROR, ret); + ChipLogProgress(DeviceLayer, "WiFi-PAF: subscribe: [%s]", args); + + wpa_fi_w1_wpa_supplicant1_interface_call_nansubscribe_sync(mWpaSupplicant.iface, args, &subscribe_id, nullptr, + &err.GetReceiver()); + ChipLogProgress(DeviceLayer, "WiFi-PAF: subscribe_id: [%d]", subscribe_id); + mpresubscribe_id = subscribe_id; + mOnPafSubscribeComplete = onSuccess; + mOnPafSubscribeError = onError; + g_signal_connect(mWpaSupplicant.iface, "nan-discoveryresult", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, gboolean success, GVariant * obj, + ConnectivityManagerImpl * self) { return self->OnDiscoveryResult(success, obj); }), + this); + + g_signal_connect(mWpaSupplicant.iface, "nan-receive", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * obj, ConnectivityManagerImpl * self) { + return self->OnNanReceive(obj); + }), + this); + + g_signal_connect( + mWpaSupplicant.iface, "nan-subscribeterminated", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, gint term_subscribe_id, gint reason, + ConnectivityManagerImpl * self) { return self->OnNanSubscribeTerminated(term_subscribe_id, reason); }), + this); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_WiFiPAFCancelConnect() +{ + if (mpresubscribe_id == 0) + { + return CHIP_NO_ERROR; + } + GAutoPtr err; + gchar args[MAX_PAF_PUBLISH_SSI_BUFLEN]; + + snprintf(args, sizeof(args), "subscribe_id=%d", mpresubscribe_id); + wpa_fi_w1_wpa_supplicant1_interface_call_nancancel_subscribe_sync(mWpaSupplicant.iface, args, nullptr, &err.GetReceiver()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_WiFiPAFSend(System::PacketBufferHandle && msgBuf) +{ + ChipLogProgress(Controller, "WiFi-PAF: sending PAF Follow-up packets, (%lu)", msgBuf->DataLength()); + CHIP_ERROR ret = CHIP_NO_ERROR; + + if (msgBuf.IsNull()) + { + ChipLogError(Controller, "WiFi-PAF: Invalid Packet (%lu)", msgBuf->DataLength()); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Ensure outgoing message fits in a single contiguous packet buffer, as currently required by the + // message fragmentation and reassembly engine. + if (msgBuf->HasChainedBuffer()) + { + msgBuf->CompactHead(); + + if (msgBuf->HasChainedBuffer()) + { + ret = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG; + ChipLogError(Controller, "WiFi-PAF: Outbound message too big (%lu), skip temporally", msgBuf->DataLength()); + return ret; + } + } + + // ================================================================================================================ + // Send the packets + GAutoPtr err; + gchar args[MAX_PAF_TX_SSI_BUFLEN]; + + snprintf(args, sizeof(args), "handle=%u req_instance_id=%u address=%02x:%02x:%02x:%02x:%02x:%02x ssi=", mpaf_info.subscribe_id, + mpaf_info.peer_publish_id, mpaf_info.peer_addr[0], mpaf_info.peer_addr[1], mpaf_info.peer_addr[2], + mpaf_info.peer_addr[3], mpaf_info.peer_addr[4], mpaf_info.peer_addr[5]); + + ChipLogProgress(Controller, "===> %s(), (%lu, %u)", __FUNCTION__, (strlen(args) + msgBuf->DataLength()), MAX_PAF_TX_SSI_BUFLEN) + VerifyOrReturnError((strlen(args) + msgBuf->DataLength() < MAX_PAF_TX_SSI_BUFLEN), CHIP_ERROR_BUFFER_TOO_SMALL); + + ret = chip::Encoding::BytesToUppercaseHexString(msgBuf->Start(), msgBuf->DataLength(), &args[strlen(args)], + MAX_PAF_TX_SSI_BUFLEN - strlen(args)); + VerifyOrReturnError(ret == CHIP_NO_ERROR, ret); + ChipLogProgress(DeviceLayer, "WiFi-PAF: ssi: [%s]", args); + wpa_fi_w1_wpa_supplicant1_interface_call_nantransmit_sync(mWpaSupplicant.iface, args, nullptr, &err.GetReceiver()); + ChipLogProgress(Controller, "WiFi-PAF: Outbound message (%lu) done", msgBuf->DataLength()); + return ret; +} + +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF void ConnectivityManagerImpl::_ConnectWiFiNetworkAsyncCallback(GObject * sourceObject, GAsyncResult * res) { @@ -1471,7 +1821,7 @@ CHIP_ERROR ConnectivityManagerImpl::GetConfiguredNetwork(NetworkCommissioning::N const gchar * networkPath = wpa_fi_w1_wpa_supplicant1_interface_get_current_network(mWpaSupplicant.iface); // wpa_supplicant DBus API: if network path of current network is "/", means no networks is currently selected. - if (strcmp(networkPath, "/") == 0) + if ((networkPath == nullptr) || (strcmp(networkPath, "/") == 0)) { return CHIP_ERROR_KEY_NOT_FOUND; } diff --git a/src/platform/Linux/ConnectivityManagerImpl.h b/src/platform/Linux/ConnectivityManagerImpl.h index ee5978faf6ff70..2025f228532961 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.h +++ b/src/platform/Linux/ConnectivityManagerImpl.h @@ -48,6 +48,9 @@ #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif #endif #include @@ -137,6 +140,17 @@ class ConnectivityManagerImpl final : public ConnectivityManager, const Crypto::P256Keypair & clientIdentityKeypair, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * connectCallback); #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + CHIP_ERROR _WiFiPAFConnect(const SetupDiscriminator & connDiscriminator, void * appState, OnConnectionCompleteFunct onSuccess, + OnConnectionErrorFunct onError); + CHIP_ERROR _WiFiPAFCancelConnect(); + void OnDiscoveryResult(gboolean success, GVariant * obj); + void OnNanReceive(GVariant * obj); + void OnNanSubscribeTerminated(gint term_subscribe_id, gint reason); + CHIP_ERROR _WiFiPAFSend(chip::System::PacketBufferHandle && msgBuf); + Transport::WiFiPAFBase * _GetWiFiPAF(); + void _SetWiFiPAF(Transport::WiFiPAFBase * pWiFiPAF); +#endif void PostNetworkConnect(); CHIP_ERROR CommitConfig(); @@ -215,6 +229,33 @@ class ConnectivityManagerImpl final : public ConnectivityManager, void _OnWpaInterfaceReady(GObject * sourceObject, GAsyncResult * res); void _OnWpaInterfaceProxyReady(GObject * sourceObject, GAsyncResult * res); void _OnWpaBssProxyReady(GObject * sourceObject, GAsyncResult * res); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + struct wpa_dbus_discov_info + { + uint32_t subscribe_id; + uint32_t peer_publish_id; + uint8_t peer_addr[6]; + uint32_t ssi_len; + }; + uint32_t mpresubscribe_id; + struct wpa_dbus_discov_info mpaf_info; + struct wpa_dbus_nanrx_info + { + uint32_t id; + uint32_t peer_id; + uint8_t peer_addr[6]; + uint32_t ssi_len; + }; + struct wpa_dbus_nanrx_info mpaf_nanrx_info; + + OnConnectionCompleteFunct mOnPafSubscribeComplete; + OnConnectionErrorFunct mOnPafSubscribeError; + Transport::WiFiPAFBase * pmWiFiPAF; + void * mAppState; + CHIP_ERROR _SetWiFiPAFAdvertisingEnabled(WiFiPAFAdvertiseParam & args); + CHIP_ERROR _WiFiPAFPublish(WiFiPAFAdvertiseParam & args); + CHIP_ERROR _WiFiPAFCancelPublish(); +#endif bool _GetBssInfo(const gchar * bssPath, NetworkCommissioning::WiFiScanResponse & result); diff --git a/src/platform/Linux/dbus/wpa/DBusWpaInterface.xml b/src/platform/Linux/dbus/wpa/DBusWpaInterface.xml index ef86bdd3b17032..721ca0033cca09 100644 --- a/src/platform/Linux/dbus/wpa/DBusWpaInterface.xml +++ b/src/platform/Linux/dbus/wpa/DBusWpaInterface.xml @@ -56,6 +56,23 @@ + + + + + + + + + + + + + + + + + @@ -92,6 +109,21 @@ + + + + + + + + + + + + + + + diff --git a/src/platform/device.gni b/src/platform/device.gni index 332b4b3ee85716..87e2eb12e8d0d2 100644 --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -23,6 +23,9 @@ declare_args() { # Substitute fake platform when building with chip_device_platform=auto. chip_fake_platform = false + + # Include wifi-paf to commission the device or not + chip_device_config_enable_wifipaf = false } if (chip_device_platform == "auto") { diff --git a/src/setup_payload/SetupPayload.cpp b/src/setup_payload/SetupPayload.cpp index 1ef4795d571e4d..9683da21f8a7f9 100644 --- a/src/setup_payload/SetupPayload.cpp +++ b/src/setup_payload/SetupPayload.cpp @@ -62,7 +62,7 @@ bool PayloadContents::isValidQRCodePayload(ValidationMode mode) const if (mode == ValidationMode::kProduce) { chip::RendezvousInformationFlags valid(RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kOnNetwork, - RendezvousInformationFlag::kSoftAP); + RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kWiFiPAF); VerifyOrReturnValue(rendezvousInformation.Value().HasOnly(valid), false); } diff --git a/src/setup_payload/SetupPayload.h b/src/setup_payload/SetupPayload.h index dc67206dd51867..3d5d101fbf4c6e 100644 --- a/src/setup_payload/SetupPayload.h +++ b/src/setup_payload/SetupPayload.h @@ -101,6 +101,7 @@ enum class RendezvousInformationFlag : uint8_t kSoftAP = 1 << 0, ///< Device supports Wi-Fi softAP kBLE = 1 << 1, ///< Device supports BLE kOnNetwork = 1 << 2, ///< Device supports Setup on network + kWiFiPAF = 1 << 3, ///< Device supports Wi-Fi Public Action Frame for discovery }; using RendezvousInformationFlags = chip::BitFlags; diff --git a/src/setup_payload/tests/TestQRCode.cpp b/src/setup_payload/tests/TestQRCode.cpp index 44c50d9e1e8f5b..e5d68227c2956e 100644 --- a/src/setup_payload/tests/TestQRCode.cpp +++ b/src/setup_payload/tests/TestQRCode.cpp @@ -53,6 +53,9 @@ TEST(TestQRCode, TestRendezvousFlags) inPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork); EXPECT_TRUE(CheckWriteRead(inPayload)); + inPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kWiFiPAF); + EXPECT_TRUE(CheckWriteRead(inPayload)); + inPayload.rendezvousInformation.SetValue( RendezvousInformationFlags(RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork)); EXPECT_TRUE(CheckWriteRead(inPayload)); @@ -61,9 +64,26 @@ TEST(TestQRCode, TestRendezvousFlags) RendezvousInformationFlags(RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kOnNetwork)); EXPECT_TRUE(CheckWriteRead(inPayload)); + inPayload.rendezvousInformation.SetValue( + RendezvousInformationFlags(RendezvousInformationFlag::kWiFiPAF, RendezvousInformationFlag::kOnNetwork)); + EXPECT_TRUE(CheckWriteRead(inPayload)); + inPayload.rendezvousInformation.SetValue(RendezvousInformationFlags( RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork)); EXPECT_TRUE(CheckWriteRead(inPayload)); + + inPayload.rendezvousInformation.SetValue(RendezvousInformationFlags( + RendezvousInformationFlag::kWiFiPAF, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork)); + EXPECT_TRUE(CheckWriteRead(inPayload)); + + inPayload.rendezvousInformation.SetValue(RendezvousInformationFlags( + RendezvousInformationFlag::kWiFiPAF, RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kOnNetwork)); + EXPECT_TRUE(CheckWriteRead(inPayload)); + + inPayload.rendezvousInformation.SetValue( + RendezvousInformationFlags(RendezvousInformationFlag::kWiFiPAF, RendezvousInformationFlag::kBLE, + RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork)); + EXPECT_TRUE(CheckWriteRead(inPayload)); } TEST(TestQRCode, TestCommissioningFlow) @@ -88,8 +108,9 @@ TEST(TestQRCode, TestMaximumValues) inPayload.vendorID = 0xFFFF; inPayload.productID = 0xFFFF; inPayload.commissioningFlow = CommissioningFlow::kCustom; - inPayload.rendezvousInformation.SetValue(RendezvousInformationFlags( - RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork)); + inPayload.rendezvousInformation.SetValue( + RendezvousInformationFlags(RendezvousInformationFlag::kWiFiPAF, RendezvousInformationFlag::kBLE, + RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork)); inPayload.discriminator.SetLongValue(static_cast((1 << kPayloadDiscriminatorFieldLengthInBits) - 1)); inPayload.setUpPINCode = static_cast((1 << kSetupPINCodeFieldLengthInBits) - 1); @@ -303,9 +324,10 @@ TEST(TestQRCode, TestSetupPayloadVerify) EXPECT_EQ(test_payload.isValidQRCodePayload(), false); // test invalid rendezvousInformation - test_payload = payload; - RendezvousInformationFlags invalid = RendezvousInformationFlags( - RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork); + test_payload = payload; + RendezvousInformationFlags invalid = + RendezvousInformationFlags(RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, + RendezvousInformationFlag::kOnNetwork, RendezvousInformationFlag::kWiFiPAF); invalid.SetRaw(static_cast(invalid.Raw() + 1)); test_payload.rendezvousInformation.SetValue(invalid); EXPECT_EQ(test_payload.isValidQRCodePayload(), false); diff --git a/src/transport/raw/BUILD.gn b/src/transport/raw/BUILD.gn index 3e8d3d4761dca3..f5593c012769e7 100644 --- a/src/transport/raw/BUILD.gn +++ b/src/transport/raw/BUILD.gn @@ -15,6 +15,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/ble/ble.gni") import("${chip_root}/src/inet/inet.gni") +import("${chip_root}/src/platform/device.gni") static_library("raw") { output_name = "libRawTransport" @@ -44,6 +45,12 @@ static_library("raw") { "BLE.h", ] } + if (chip_device_config_enable_wifipaf) { + sources += [ + "WiFiPAF.cpp", + "WiFiPAF.h", + ] + } cflags = [ "-Wconversion" ] diff --git a/src/transport/raw/PeerAddress.h b/src/transport/raw/PeerAddress.h index 64588bc64c062f..896648f76f537a 100644 --- a/src/transport/raw/PeerAddress.h +++ b/src/transport/raw/PeerAddress.h @@ -53,6 +53,7 @@ enum class Type : uint8_t kUdp, kBle, kTcp, + kWiFiPAF, }; /** @@ -64,6 +65,7 @@ class PeerAddress PeerAddress() : mIPAddress(Inet::IPAddress::Any), mTransportType(Type::kUndefined) {} PeerAddress(const Inet::IPAddress & addr, Type type) : mIPAddress(addr), mTransportType(type) {} PeerAddress(Type type) : mTransportType(type) {} + PeerAddress(Type type, NodeId remoteId) : mTransportType(type), mRemoteId(remoteId) {} PeerAddress(PeerAddress &&) = default; PeerAddress(const PeerAddress &) = default; @@ -77,6 +79,8 @@ class PeerAddress return *this; } + NodeId GetRemoteId() const { return mRemoteId; } + Type GetTransportType() const { return mTransportType; } PeerAddress & SetTransportType(Type type) { @@ -167,6 +171,9 @@ class PeerAddress #endif snprintf(buf, bufSize, "TCP:[%s%s]:%d", ip_addr, interface, mPort); break; + case Type::kWiFiPAF: + snprintf(buf, bufSize, "Wi-Fi PAF"); + break; case Type::kBle: // Note that BLE does not currently use any specific address. snprintf(buf, bufSize, "BLE"); @@ -209,6 +216,8 @@ class PeerAddress return TCP(addr).SetPort(port).SetInterface(interface); } + static PeerAddress WiFiPAF(NodeId remoteId) { return PeerAddress(Type::kWiFiPAF); } + static PeerAddress Multicast(chip::FabricId fabric, chip::GroupId group) { constexpr uint8_t scope = 0x05; // Site-Local @@ -237,6 +246,7 @@ class PeerAddress Type mTransportType = Type::kUndefined; uint16_t mPort = CHIP_PORT; ///< Relevant for UDP data sending. Inet::InterfaceId mInterface = Inet::InterfaceId::Null(); + NodeId mRemoteId = 0; }; } // namespace Transport diff --git a/src/transport/raw/WiFiPAF.cpp b/src/transport/raw/WiFiPAF.cpp new file mode 100644 index 00000000000000..97b465dd261e9b --- /dev/null +++ b/src/transport/raw/WiFiPAF.cpp @@ -0,0 +1,113 @@ +/* + * + * Copyright (c) 2024 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 + * This file implements the Matter Connection object that maintains a Wi-Fi PAF connection + * + */ + +#include +#include +#include +#include +#include +#include + +using namespace chip::System; + +namespace chip { +namespace Transport { + +WiFiPAFBase::~WiFiPAFBase() +{ + ClearState(); +} + +void WiFiPAFBase::ClearState() +{ + mState = State::kNotReady; +} + +CHIP_ERROR WiFiPAFBase::Init(const WiFiPAFListenParameters & param) +{ + ChipLogDetail(Inet, "WiFiPAFBase::Init - setting/overriding transport"); + VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE); + DeviceLayer::ConnectivityMgr().SetWiFiPAF(this); + mState = State::kInitialized; + + if (!DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted()) + { + ChipLogError(Inet, "Wi-Fi Management has not started, do it now."); + static constexpr useconds_t kWiFiStartCheckTimeUsec = WIFI_START_CHECK_TIME_USEC; + static constexpr uint8_t kWiFiStartCheckAttempts = WIFI_START_CHECK_ATTEMPTS; + DeviceLayer::ConnectivityMgrImpl().StartWiFiManagement(); + { + for (int cnt = 0; cnt < kWiFiStartCheckAttempts; cnt++) + { + if (DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted()) + { + break; + } + usleep(kWiFiStartCheckTimeUsec); + } + } + if (!DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted()) + { + ChipLogError(Inet, "Wi-Fi Management taking too long to start - device configuration will be reset."); + return CHIP_ERROR_INTERNAL; + } + ChipLogProgress(NotSpecified, "Wi-Fi Management is started"); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR WiFiPAFBase::SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf) +{ + ReturnErrorCodeIf(address.GetTransportType() != Type::kWiFiPAF, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE); + DeviceLayer::ConnectivityMgr().WiFiPAFSend(std::move(msgBuf)); + + return CHIP_NO_ERROR; +} + +void WiFiPAFBase::OnWiFiPAFMessageReceived(System::PacketBufferHandle && buffer) +{ + HandleMessageReceived(Transport::PeerAddress(Transport::Type::kWiFiPAF), std::move(buffer)); + return; +} + +CHIP_ERROR WiFiPAFBase::SendAfterConnect(System::PacketBufferHandle && msg) +{ + CHIP_ERROR err = CHIP_ERROR_NO_MEMORY; + + for (size_t i = 0; i < mPendingPacketsSize; i++) + { + if (mPendingPackets[i].IsNull()) + { + mPendingPackets[i] = std::move(msg); + err = CHIP_NO_ERROR; + break; + } + } + + return err; +} + +} // namespace Transport +} // namespace chip diff --git a/src/transport/raw/WiFiPAF.h b/src/transport/raw/WiFiPAF.h new file mode 100644 index 00000000000000..bd54d22cc3e26f --- /dev/null +++ b/src/transport/raw/WiFiPAF.h @@ -0,0 +1,115 @@ +/* + * + * Copyright (c) 2024 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 + * This file defines the Matter Connection object that maintains a Wi-Fi PAF connection. + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace chip { +namespace Transport { + +class WiFiPAFLayer +{ +public: + WiFiPAFLayer() = default; +}; +class WiFiPAFListenParameters; + +/** + * Implements a transport using Wi-Fi-PAF + */ +class DLL_EXPORT WiFiPAFBase : public Base +{ +public: + /** + * The State of the Wi-Fi-PAF connection + * + */ + enum class State + { + kNotReady = 0, /**< State before initialization. */ + kInitialized = 1, /**< State after class is connected and ready. */ + kConnected = 2, /**< Endpoint connected. */ + }; + WiFiPAFBase() = default; + WiFiPAFBase(System::PacketBufferHandle * packetBuffers, size_t packetBuffersSize) : + mPendingPackets(packetBuffers), mPendingPacketsSize(packetBuffersSize) + {} + ~WiFiPAFBase() override; + + /** + * Initialize a Wi-Fi-PAF transport + * + * @param param Wi-Fi-PAF configuration parameters for this transport + */ + CHIP_ERROR Init(const WiFiPAFListenParameters & param); + CHIP_ERROR SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf) override; + bool CanSendToPeer(const Transport::PeerAddress & address) override + { + return (mState != State::kNotReady) && (address.GetTransportType() == Type::kWiFiPAF); + } + void OnWiFiPAFMessageReceived(System::PacketBufferHandle && buffer); + void SetWiFiPAFState(State state) { mState = state; }; + State GetWiFiPAFState() { return mState; }; + +private: + void ClearState(); + /** + * Sends the specified message once a connection has been established. + * @param msg - what buffer to send once a connection has been established. + */ + CHIP_ERROR SendAfterConnect(System::PacketBufferHandle && msg); + State mState = State::kNotReady; + + System::PacketBufferHandle * mPendingPackets; + size_t mPendingPacketsSize; +}; + +template +class WiFiPAF : public WiFiPAFBase +{ +public: + WiFiPAF() : WiFiPAFBase(mPendingPackets, kPendingPacketSize) {} + +private: + System::PacketBufferHandle mPendingPackets[kPendingPacketSize]; +}; + +/** Defines parameters for setting up the Wi-Fi PAF transport */ +class WiFiPAFListenParameters +{ +public: + WiFiPAFListenParameters() = default; + explicit WiFiPAFListenParameters(WiFiPAFBase * layer) : mWiFiPAF(layer) {} + +private: + WiFiPAFBase * mWiFiPAF; +}; + +} // namespace Transport +} // namespace chip