diff --git a/examples/tv-casting-app/linux/main.cpp b/examples/tv-casting-app/linux/main.cpp
index 93d3e46be47d89..b1442c3657b1c3 100644
--- a/examples/tv-casting-app/linux/main.cpp
+++ b/examples/tv-casting-app/linux/main.cpp
@@ -17,26 +17,68 @@
  */
 
 #include <app/server/Mdns.h>
-#include <app/server/OnboardingCodesUtil.h>
 #include <app/server/Server.h>
 #include <controller/CHIPCommissionableNodeController.h>
 #include <platform/CHIPDeviceLayer.h>
 #include <platform/ConfigurationManager.h>
-#include <setup_payload/SetupPayload.h>
 #include <system/SystemLayer.h>
 #include <transport/raw/PeerAddress.h>
 
 using namespace chip;
+using namespace chip::Controller;
 
 #define TV_DEVICE_TYPE 35
 
-chip::Controller::CommissionableNodeController commissionableNodeController;
+CommissionableNodeController commissionableNodeController;
+chip::System::SocketWatchToken token;
 
-void RequestCommissioning(intptr_t commandArg)
+/**
+ * Enters commissioning mode, opens commissioning window, logs onboarding payload.
+ * If non-null selectedCommissioner is provided, sends user directed commissioning
+ * request to the selectedCommissioner and advertises self commissionable node over DNS-SD
+ */
+void PrepareForCommissioning(const Mdns::DiscoveredNodeData * selectedCommissioner = nullptr)
+{
+    // Enter commissioning mode, open commissioning window
+    InitServer();
+    ReturnOnFailure(OpenBasicCommissioningWindow(ResetFabrics::kYes, 3 * 60));
+
+    // Display onboarding payload
+    chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig();
+
+#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
+    if (selectedCommissioner != nullptr)
+    {
+        // Advertise self as Commissionable Node over mDNS
+        ReturnOnFailure(app::Mdns::AdvertiseCommissionableNode(app::Mdns::CommissioningMode::kEnabledBasic));
+
+        // Send User Directed commissioning request
+        ReturnOnFailure(SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(
+            selectedCommissioner->ipAddress[0], selectedCommissioner->port, selectedCommissioner->interfaceId[0])));
+    }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
+}
+
+/**
+ * Accepts user input of selected commissioner and calls PrepareForCommissioning with
+ * the selected commissioner
+ */
+void RequestUserDirectedCommisisioning(System::SocketEvents events, intptr_t data)
+{
+    // Accept user selection for commissioner to request commissioning from
+    int selectedCommissionerNumber = CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES;
+    scanf("%d", &selectedCommissionerNumber);
+    chip::DeviceLayer::SystemLayer.StopWatchingSocket(&token);
+
+    const Mdns::DiscoveredNodeData * selectedCommissioner =
+        commissionableNodeController.GetDiscoveredCommissioner(selectedCommissionerNumber - 1);
+    VerifyOrReturn(selectedCommissioner != nullptr, ChipLogError(Zcl, "No such commissioner!"));
+    PrepareForCommissioning(selectedCommissioner);
+}
+
+void InitCommissioningFlow(intptr_t commandArg)
 {
-    int commissionerCount = 0, selectedCommissionerNumber = CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES;
-    chip::SetupPayload payload;
-    const Mdns::DiscoveredNodeData * selectedCommissioner = nullptr;
+    int commissionerCount = 0;
 
     // Display discovered commissioner TVs to ask user to select one
     for (int i = 0; i < CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES; i++)
@@ -48,38 +90,25 @@ void RequestCommissioning(intptr_t commandArg)
             commissioner->LogDetail();
         }
     }
-    ChipLogProgress(Zcl, "%d commissioner(s) discovered", commissionerCount);
 
     if (commissionerCount > 0)
     {
-        ChipLogProgress(Zcl, "Choose a commissioner (by number# above) to request commissioning from: ");
-        scanf("%d", &selectedCommissionerNumber);
-        selectedCommissioner = commissionableNodeController.GetDiscoveredCommissioner(selectedCommissionerNumber - 1);
-        VerifyOrReturn(selectedCommissioner != nullptr, ChipLogError(Zcl, "No such commissioner!"));
+        ChipLogProgress(
+            Zcl, "%d commissioner(s) discovered. Select one (by number# above) to request commissioning from: ", commissionerCount);
+
+        // Setup for async/non-blocking user input from stdin
+        int flags = fcntl(0, F_GETFL, 0);
+        VerifyOrReturn(fcntl(0, F_SETFL, flags | O_NONBLOCK) == 0,
+                       ChipLogError(Zcl, "Could not set non-blocking mode for user input!"));
+        ReturnOnFailure(chip::DeviceLayer::SystemLayer.StartWatchingSocket(0, &token));
+        ReturnOnFailure(chip::DeviceLayer::SystemLayer.SetCallback(token, RequestUserDirectedCommisisioning, (intptr_t) NULL));
+        ReturnOnFailure(chip::DeviceLayer::SystemLayer.RequestCallbackOnPendingRead(token));
     }
     else
     {
         ChipLogError(Zcl, "No commissioner discovered, commissioning must be initiated manually!");
+        PrepareForCommissioning();
     }
-
-    // Enter commissioning mode, open commissioning window
-    InitServer();
-    ReturnOnFailure(OpenBasicCommissioningWindow(ResetFabrics::kYes, 3 * 60));
-
-    // Display onboarding payload
-    chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig();
-
-#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
-    if (selectedCommissioner != nullptr)
-    {
-        // Advertise self as Commissionable Node over mDNS
-        ReturnOnFailure(app::Mdns::AdvertiseCommissionableNode(app::Mdns::CommissioningMode::kEnabledBasic));
-
-        // Send User Directed commissioning request
-        ReturnOnFailure(SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(
-            selectedCommissioner->ipAddress[0], selectedCommissioner->port, selectedCommissioner->interfaceId[0])));
-    }
-#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
 }
 
 int main(int argc, char * argv[])
@@ -88,13 +117,15 @@ int main(int argc, char * argv[])
     SuccessOrExit(err = chip::Platform::MemoryInit());
     SuccessOrExit(err = chip::DeviceLayer::PlatformMgr().InitChipStack());
 
-    // Send discover commissioner TVs request
+    // Send discover commissioners request
     SuccessOrExit(err = commissionableNodeController.DiscoverCommissioners(
                       Mdns::DiscoveryFilter(Mdns::DiscoveryFilterType::kDeviceType, TV_DEVICE_TYPE)));
 
-    // Give commissioner TVs some time to respond and then ScheduleWork to get commissioned
+    // Give commissioners some time to respond and then ScheduleWork to initiate commissioning
     DeviceLayer::SystemLayer.StartTimer(
-        5 * 1000, [](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(RequestCommissioning); }, nullptr);
+        5 * 1000, [](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(InitCommissioningFlow); }, nullptr);
+
+    // TBD: Content casting commands
 
     DeviceLayer::PlatformMgr().RunEventLoop();
 exit: