diff --git a/examples/chip-tool/commands/pairing/Commands.h b/examples/chip-tool/commands/pairing/Commands.h index 41a35bb6bae6ad..d85b5a5b0802f3 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("wifi-paf", 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..a346b55e2813a4 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()); + 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..c222ad5f9cd5ff 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); + AddArgument("discriminator", 0, 4096, &mDiscriminator); + break; +#endif case PairingMode::AlreadyDiscovered: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index b92d76e613e618..f20cae3048c990 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -360,6 +360,8 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions, CHIP_ERROR err = CHIP_NO_ERROR; #if CONFIG_NETWORK_LAYER_BLE RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kBLE; +#elif CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kWiFiPAF; #else // CONFIG_NETWORK_LAYER_BLE RendezvousInformationFlag rendezvousFlags = RendezvousInformationFlag::kOnNetwork; #endif // CONFIG_NETWORK_LAYER_BLE @@ -465,6 +467,17 @@ 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::ConnectivityMgr().SetWiFiPAFAdvertisingEnabled(LinuxDeviceOptions::GetInstance().mWiFiPAF); + } + } +#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..5e32bf7eb4bfde 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 = 0x1028, +#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 + { "wifi-paf", kNoArgument, 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,11 @@ 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_WIFI && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF) + "\n" + " --wifi-paf\n" + " Enable Wi-Fi PAF via wpa_supplicant.\n" +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF #if CHIP_ENABLE_OPENTHREAD "\n" " --thread\n" @@ -588,6 +599,12 @@ 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; + 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..163ae916353dda 100644 --- a/examples/platform/linux/Options.h +++ b/examples/platform/linux/Options.h @@ -49,6 +49,9 @@ struct LinuxDeviceOptions bool wifiSupports5g = false; bool mWiFi = false; bool mThread = false; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + bool mWiFiPAF = false; +#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/Server.cpp b/src/app/server/Server.cpp index 5be815f0864c95..9633da87e063ef 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 d649e0fc923896..c199828ec4cecd 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 @@ -99,6 +102,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..bc7ad342bcb99e 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -591,8 +591,13 @@ CHIP_ERROR AutoCommissioner::StartCommissioning(DeviceCommissioner * commissione mCommissioner = commissioner; mCommissioneeDeviceProxy = proxy; mNeedsNetworkSetup = - mCommissioneeDeviceProxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress().GetTransportType() == - Transport::Type::kBle; + (mCommissioneeDeviceProxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress().GetTransportType() == + Transport::Type::kBle) +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + || (mCommissioneeDeviceProxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress().GetTransportType() == + Transport::Type::kWiFiPAF) +#endif + ; CHIP_ERROR err = CHIP_NO_ERROR; CommissioningStage nextStage = GetNextCommissioningStage(CommissioningStage::kSecurePairing, err); mCommissioner->PerformCommissioningStep(mCommissioneeDeviceProxy, nextStage, mParams, this, GetEndpoint(nextStage), diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 5212350c913696..1add5e05858f1f 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -66,6 +66,10 @@ #include #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +#include +#endif + #include #include @@ -730,6 +734,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(); + } +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF current = FindCommissioneeDevice(peerAddress); if (current != nullptr) @@ -804,6 +814,39 @@ 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"); + 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(NotSpecified, "Wi-Fi Management taking too long to start - device configuration will be reset."); + } + mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = params; + DeviceLayer::ConnectivityMgr().WiFiPAFConnect( + this, + OnWiFiPAFSubscribeComplete, + OnWiFiPAFSubscribeError + ); + ExitNow(CHIP_NO_ERROR); + } + ChipLogProgress(Controller, "WiFi-PAF: Request to subscrib the NAN-USD device complete"); + } #endif session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress(), params.GetMRPConfig()); VerifyOrExit(session.HasValue(), err = CHIP_ERROR_NO_MEMORY); @@ -872,6 +915,44 @@ 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 = static_cast(appState); + auto device = self->mDeviceInPASEEstablishment; + + ChipLogProgress(Controller, "WiFi-PAF: Subscription Completed!"); + if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kWiFiPAF) + { + auto remoteId = device->GetDeviceId(); + auto params = self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF; + + self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = RendezvousParameters(); + self->ReleaseCommissioneeDevice(device); + DeviceLayer::ConnectivityMgr().GetWiFiPAF()->SetWiFiPAFState(Transport::WiFiPAFBase::State::kConnected); + chip::DeviceLayer::StackLock stackLock; + LogErrorOnFailure(self->EstablishPASEConnection(remoteId, params)); + } +} + +void DeviceCommissioner::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err) +{ + auto self = static_cast(appState); + auto device = self->mDeviceInPASEEstablishment; + + ChipLogProgress(Controller, "WiFi-PAF: Subscription Error!"); + if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kWiFiPAF) + { + 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 1ab85ca0dc182b..c623b308057be5 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -846,6 +846,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 1ea0593d594993..d6dbec63a269a4 100644 --- a/src/controller/CHIPDeviceControllerSystemState.h +++ b/src/controller/CHIPDeviceControllerSystemState.h @@ -52,10 +52,17 @@ #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 +83,10 @@ using DeviceTransportMgr = #if INET_CONFIG_ENABLE_TCP_ENDPOINT , Transport::TCP +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + , + Transport::WiFiPAF /* WiFiPAF */ #endif >; @@ -93,6 +104,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..08c6041d5e7ca8 100644 --- a/src/controller/SetUpCodePairer.cpp +++ b/src/controller/SetUpCodePairer.cpp @@ -129,6 +129,17 @@ CHIP_ERROR SetUpCodePairer::Connect(SetupPayload & payload) } VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err || CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err, err); } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + 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); + } +#endif } // We always want to search on network because any node that has already been commissioned will use on-network regardless of the @@ -243,6 +254,19 @@ CHIP_ERROR SetUpCodePairer::StopConnectOverSoftAP() return CHIP_NO_ERROR; } +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +CHIP_ERROR SetUpCodePairer::StartDiscoverOverWiFiPAF(SetupPayload & payload) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR SetUpCodePairer::StopConnectOverWiFiPAF() +{ + mWaitingForDiscovery[kWiFiPAF] = false; + return CHIP_NO_ERROR; +} +#endif + bool SetUpCodePairer::ConnectToDiscoveredDevice() { if (mWaitingForPASE) diff --git a/src/controller/SetUpCodePairer.h b/src/controller/SetUpCodePairer.h index e177af7322d391..848fbfbb1400bc 100644 --- a/src/controller/SetUpCodePairer.h +++ b/src/controller/SetUpCodePairer.h @@ -111,6 +111,10 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate CHIP_ERROR StopConnectOverIP(); CHIP_ERROR StartDiscoverOverSoftAP(SetupPayload & payload); CHIP_ERROR StopConnectOverSoftAP(); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + CHIP_ERROR StartDiscoverOverWiFiPAF(SetupPayload & payload); + CHIP_ERROR StopConnectOverWiFiPAF(); +#endif // Returns whether we have kicked off a new connection attempt. bool ConnectToDiscoveredDevice(); @@ -150,6 +154,9 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate kBLETransport = 0, kIPTransport, kSoftAPTransport, +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + kWiFiPAF, +#endif kTransportTypeCount, }; diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 49a94d75c23fcc..65e3d6ee83ad22 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -425,6 +425,16 @@ #define CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME "wlan0" #endif +/** + * CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + * + * Name of the WiFi PAF/DNAN-USD + */ +#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..611285fba4d4f3 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -281,7 +281,10 @@ enum InternalEventTypes * This event should populate CHIPoBLEConnectionError structure. */ kCHIPoBLEConnectionError, - kCHIPoBLENotifyConfirm + kCHIPoBLENotifyConfirm, +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + kCHIPoWiFiPAFWriteReceived, +#endif }; static_assert(kEventTypeNotSet == 0, "kEventTypeNotSet must be defined as 0"); @@ -491,6 +494,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..bb7be41a5b871c 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,18 @@ class ConnectivityManager bool IsWiFiStationProvisioned(); void ClearWiFiStationProvision(); CHIP_ERROR GetAndLogWiFiStatsCounters(); +#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + CHIP_ERROR SetWiFiPAFAdvertisingEnabled(bool val); + + typedef void (*OnConnectionCompleteFunct)(void * appState); + typedef void (*OnConnectionErrorFunct)(void * appState, CHIP_ERROR err); + CHIP_ERROR WiFiPAFConnect(void * appState, + OnConnectionCompleteFunct onSuccess, + OnConnectionErrorFunct onError); + CHIP_ERROR WiFiPAFSend(chip::System::PacketBufferHandle && msgBuf); + Transport::WiFiPAFBase * GetWiFiPAF(); + void SetWiFiPAF(Transport::WiFiPAFBase * pmWiFiPAF); +#endif // WiFi AP methods WiFiAPMode GetWiFiAPMode(); @@ -407,6 +422,26 @@ inline CHIP_ERROR ConnectivityManager::GetAndLogWiFiStatsCounters() return static_cast(this)->_GetAndLogWiFiStatsCounters(); } +#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF +inline CHIP_ERROR ConnectivityManager::SetWiFiPAFAdvertisingEnabled(bool val) +{ + return static_cast(this)->_SetWiFiPAFAdvertisingEnabled(val); +} + +inline CHIP_ERROR ConnectivityManager::WiFiPAFConnect( + void * appState, + OnConnectionCompleteFunct onSuccess, + OnConnectionErrorFunct onError) +{ + return static_cast(this)->_WiFiPAFConnect(appState, onSuccess, onError); +} + +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 +486,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/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h b/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h index 24cc0032389280..4db7ea9bdb889d 100644 --- a/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h +++ b/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h @@ -77,6 +77,9 @@ class GenericConnectivityManagerImpl_WiFi bool _CanStartWiFiScan(); void _OnWiFiScanDone(); void _OnWiFiStationProvisionChange(); +#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF + CHIP_ERROR _SetWiFiPAFAdvertisingEnabled(bool val); +#endif // TODO ICD rework: ambiguous declaration of _SetPollingInterval when thread and wifi are both build together #if CHIP_CONFIG_ENABLE_ICD_SERVER && !CHIP_DEVICE_CONFIG_ENABLE_THREAD CHIP_ERROR _SetPollingInterval(System::Clock::Milliseconds32 pollingInterval); 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..312557fdba07ba 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -19,6 +19,7 @@ #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,15 @@ 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: kCHIPoWiFiPAFWriteReceived"); + _GetWiFiPAF()->OnWiFiPAFMessageReceived(System::PacketBufferHandle::Adopt(event->CHIPoWiFiPAFWriteReceived.Data)); + break; + } +#endif //CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF } #if CHIP_DEVICE_CONFIG_ENABLE_WPA @@ -797,6 +810,83 @@ 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 128 +#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::_SetWiFiPAFAdvertisingEnabled(bool val) +{ + CHIP_ERROR ret; + GAutoPtr err; + gchar args[MAX_PAF_PUBLISH_SSI_BUFLEN]; + gint publish_id; + + snprintf(args, sizeof(args), "service_name=%s srv_proto_type=%u ttl=%u ", + srv_name, NAN_SRV_PROTO_MATTER, NAM_PUBLISH_PERIOD); + + 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; + } + strcat(args, NAN_PUBLISH_SSI_TAG); + ret = chip::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: SetWiFiPAFAdvertisingEnabled(%d)", val); + 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; +} + +Transport::WiFiPAFBase * ConnectivityManagerImpl::_GetWiFiPAF() +{ + return pmWiFiPAF; +} + +void ConnectivityManagerImpl::_SetWiFiPAF(Transport::WiFiPAFBase * pWiFiPAF) +{ + pmWiFiPAF = pWiFiPAF; + return; +} +#endif + void ConnectivityManagerImpl::StartNonConcurrentWiFiManagement() { StartWiFiManagement(); @@ -1226,6 +1316,179 @@ 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; + } + + 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]); + if (mOnPafSubscribeComplete != nullptr) + { + mOnPafSubscribeComplete(mAppState); + } + + return; +} + +void ConnectivityManagerImpl::OnNanReceive(GVariant * obj) +{ + ChipLogProgress(Controller, "WiFi-PAF: OnNanReceive"); + + if (g_variant_n_children(obj) == 0) + { + return; + } + { + GAutoPtr dataValue(g_variant_lookup_value(obj, "nanrx_info", G_VARIANT_TYPE_BYTESTRING)); + size_t bufferLen; + auto buffer = g_variant_get_fixed_array(dataValue.get(), &bufferLen, sizeof(uint8_t)); + + memcpy(&mpaf_nanrx_info, buffer, 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) { + 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: [buflen: %lu], preparing rxbuf", 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); + } + } else { + ChipLogProgress(DeviceLayer, "WiFi-PAF: Skip, ssi length = %u", mpaf_nanrx_info.ssi_len); + } + + return; +} + + +CHIP_ERROR ConnectivityManagerImpl::_WiFiPAFConnect(void *appState, + OnConnectionCompleteFunct onSuccess, + OnConnectionErrorFunct onError) +{ + ChipLogProgress(Controller, "WiFi-PAF: Try to subscribe the NAN-USD devices"); + gchar args[MAX_PAF_SUBSCRIBE_SSI_BUFLEN]; + snprintf(args, sizeof(args), "service_name=%s srv_proto_type=%u ttl=%u ", + srv_name, NAN_SRV_PROTO_MATTER, NAM_SUBSCRIBE_PERIOD); + mAppState = appState; + GAutoPtr err; + + wpa_fi_w1_wpa_supplicant1_interface_call_nansubscribe(mWpaSupplicant.iface, + args, + nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return ; + }), + &err.GetReceiver()); + mOnPafSubscribeComplete = onSuccess; + g_signal_connect( + mWpaSupplicant.iface, "discovery-result", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, gboolean success, GVariant * obj, ConnectivityManagerImpl * self) { + return self->OnDiscoveryResult(success, obj); + }), + this); + + + 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()); + + g_signal_connect( + mWpaSupplicant.iface, "nan-receive", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * obj, ConnectivityManagerImpl * self) { + return self->OnNanReceive(obj); + }), + this); + + 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 +1734,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..54f29170d20d21 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(void * appState, + OnConnectionCompleteFunct onSuccess, + OnConnectionErrorFunct onError); + void OnDiscoveryResult(gboolean success, GVariant * obj); + void OnNanReceive(GVariant * obj); + + CHIP_ERROR _WiFiPAFSend(chip::System::PacketBufferHandle && msgBuf); + Transport::WiFiPAFBase * _GetWiFiPAF(); + void _SetWiFiPAF(Transport::WiFiPAFBase * pWiFiPAF); +#endif void PostNetworkConnect(); CHIP_ERROR CommitConfig(); @@ -215,6 +229,26 @@ 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]; + }; + 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; + Transport::WiFiPAFBase * pmWiFiPAF; + void * mAppState; + CHIP_ERROR _SetWiFiPAFAdvertisingEnabled(bool val); +#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..a9c2c0b51353e9 100644 --- a/src/platform/Linux/dbus/wpa/DBusWpaInterface.xml +++ b/src/platform/Linux/dbus/wpa/DBusWpaInterface.xml @@ -56,6 +56,16 @@ + + + + + + + + + + @@ -92,6 +102,13 @@ + + + + + + + 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/transport/raw/BUILD.gn b/src/transport/raw/BUILD.gn index 3e8d3d4761dca3..130d68f86152ff 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..da4f40fc130a8f 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, }; /** @@ -167,6 +168,9 @@ class PeerAddress #endif snprintf(buf, bufSize, "TCP:[%s%s]:%d", ip_addr, interface, mPort); break; + case Type::kWiFiPAF: + snprintf(buf, bufSize, "WiFiPAF"); + break; case Type::kBle: // Note that BLE does not currently use any specific address. snprintf(buf, bufSize, "BLE"); @@ -209,6 +213,8 @@ class PeerAddress return TCP(addr).SetPort(port).SetInterface(interface); } + static PeerAddress WiFiPAF() { return PeerAddress(Type::kWiFiPAF); } + static PeerAddress Multicast(chip::FabricId fabric, chip::GroupId group) { constexpr uint8_t scope = 0x05; // Site-Local diff --git a/src/transport/raw/WiFiPAF.cpp b/src/transport/raw/WiFiPAF.cpp new file mode 100644 index 00000000000000..53729b7dce9ff7 --- /dev/null +++ b/src/transport/raw/WiFiPAF.cpp @@ -0,0 +1,96 @@ +/* + * + * 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 CHIP Connection object that maintains a BLE connection. + * + */ + +//#include +#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; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR WiFiPAFBase::SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf) +{ + ChipLogProgress(NotSpecified, "=====> WiFiPAFBase::SendMessage()"); + ReturnErrorCodeIf(address.GetTransportType() != Type::kWiFiPAF, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE); + + DeviceLayer::ConnectivityMgr().WiFiPAFSend(std::move(msgBuf)); + + ChipLogProgress(NotSpecified, "<===== WiFiPAFBase::SendMessage()"); + 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..2f4e774e179173 --- /dev/null +++ b/src/transport/raw/WiFiPAF.h @@ -0,0 +1,118 @@ +/* + * + * 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 CHIP 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