diff --git a/app-runner/Private/DeviceProviders/SwitchProvider.ps1 b/app-runner/Private/DeviceProviders/SwitchProvider.ps1 index 5e0c819..9cd07df 100644 --- a/app-runner/Private/DeviceProviders/SwitchProvider.ps1 +++ b/app-runner/Private/DeviceProviders/SwitchProvider.ps1 @@ -17,6 +17,7 @@ class SwitchProvider : DeviceProvider { [string]$TargetControlTool = 'ControlTarget.exe' [string]$ApplicationRunnerTool = 'RunOnTarget.exe' [string]$Target = $null # Stores the target device identifier for commands that need explicit --target + [string]$TargetPlatform = $null # Target Manager platform: 'NX' or 'Ounce', resolved from target serial SwitchProvider() { $this.Platform = 'Switch' @@ -42,9 +43,9 @@ class SwitchProvider : DeviceProvider { 'poweroff' = @($this.TargetControlTool, 'power-off') 'press-power-button' = @($this.TargetControlTool, 'press-power-button') 'reset' = @($this.TargetControlTool, 'reset') - 'getstatus' = @($this.TargetControlTool, 'get-default --detail --json', { $input | ConvertFrom-Json }) + 'getstatus' = @($this.TargetControlTool, 'get-default --detail --platform {0} --json', { $input | ConvertFrom-Json }) 'get-default-target' = @($this.TargetControlTool, 'get-default --json', { $input | ConvertFrom-Json }) - 'set-default-target' = @($this.TargetControlTool, 'set-default --target "{0}"') + 'set-default-target' = @($this.TargetControlTool, 'set-default --target "{0}" --platform {1}') 'list-target' = @($this.TargetControlTool, 'list-target --json', { $input | ConvertFrom-Json }) 'detect-target' = @($this.TargetControlTool, 'detect-target --json', { $input | ConvertFrom-Json }) 'register-target' = @($this.TargetControlTool, 'register --target "{0}"') @@ -66,11 +67,57 @@ class SwitchProvider : DeviceProvider { if (-not [string]::IsNullOrEmpty($target)) { Write-Debug "$($this.Platform): Setting target device: $target" $this.Target = $target - $this.InvokeCommand('set-default-target', @($target)) + + # Target Manager 2 requires the platform to be specified explicitly. + # Platform can be inferred from the target name (HAL* targets are Ounce/Switch 2, others are NX/Switch 1). + $this.TargetPlatform = if ($target -match '^HAL') { 'Ounce' } else { 'NX' } + Write-Debug "$($this.Platform): Using Target Manager platform: $($this.TargetPlatform)" + + # Update device-control commands to include --target so they operate on the correct device + # when multiple targets (NX and Ounce) are registered in Target Manager. + $targetArg = " --target `"$target`"" + $this.Commands['connect'] = @($this.TargetControlTool, "connect --force$targetArg") + $this.Commands['disconnect'] = @($this.TargetControlTool, "disconnect$targetArg") + $this.Commands['poweron'] = @($this.TargetControlTool, "power-on$targetArg") + $this.Commands['poweroff'] = @($this.TargetControlTool, "power-off$targetArg") + $this.Commands['press-power-button'] = @($this.TargetControlTool, "press-power-button$targetArg") + $this.Commands['reset'] = @($this.TargetControlTool, "reset$targetArg") + + $this.InvokeCommand('set-default-target', @($target, $this.TargetPlatform)) } return $this.Connect() } + # Override DetectAndSetDefaultTarget to skip auto-detection when target was explicitly set in Connect + [void] DetectAndSetDefaultTarget() { + if (-not [string]::IsNullOrEmpty($this.Target)) { + Write-Debug "$($this.Platform): Target explicitly set to $($this.Target), skipping auto-detection" + return + } + ([DeviceProvider] $this).DetectAndSetDefaultTarget() + } + + # Override GetDeviceStatus to include `--platform` arg when querying device status so that it works correctly when multiple platforms are registered + [hashtable] GetDeviceStatus() { + Write-Debug "$($this.Platform): Getting device status" + + $platform = if ($this.TargetPlatform) { $this.TargetPlatform } else { 'NX' } + $result = $this.InvokeCommand('getstatus', @($platform)) + + return @{ + Platform = $this.Platform + Status = 'Online' + StatusData = $result + Timestamp = Get-Date + } + } + + [bool] TestConnection() { + Write-Debug "$($this.Platform): Testing connection to device" + $this.GetDeviceStatus() + return $true + } + # Override Connect to provide Switch specific wakeup [hashtable] Connect() { Write-Debug 'Connecting to Switch Devkit...' @@ -99,29 +146,49 @@ class SwitchProvider : DeviceProvider { } } + # Recovery steps are best-effort: if one fails, continue to the next switch ($i) { 0 { - Write-Warning 'Attempting to wake up the Devkit from sleep...' - $this.InvokeCommand('press-power-button', @()) + try { + Write-Warning 'Attempting to wake up the Devkit from sleep...' + $this.InvokeCommand('press-power-button', @()) + } catch { + Write-Warning "Failed to wake up Devkit: $_" + } } 1 { - Write-Warning 'Attempting to start the Devkit...' - $this.StartDevice() + try { + Write-Warning 'Attempting to start the Devkit...' + $this.StartDevice() + } catch { + Write-Warning "Failed to start Devkit: $_" + } } 2 { - Write-Warning 'Attempting to reboot the Devkit...' - $job2 = Start-Job { - ControlTarget power-off - Start-Sleep -Seconds 5 - ControlTarget power-on + try { + Write-Warning 'Attempting to reboot the Devkit...' + $powerOffCmd = $this.BuildCommand('poweroff', @()).Command + $powerOnCmd = $this.BuildCommand('poweron', @()).Command + $job2 = Start-Job { + param($offCmd, $onCmd) + Invoke-Expression $offCmd + Start-Sleep -Seconds 5 + Invoke-Expression $onCmd + } -ArgumentList $powerOffCmd, $powerOnCmd + Wait-Job $job2 -Timeout 20 | Out-Null + } catch { + Write-Warning "Failed to reboot Devkit: $_" } - Wait-Job $job2 -Timeout 20 | Out-Null } 3 { if ($info.IpAddress -ne $null) { Write-Warning 'Attempting to reboot host bridge...' - Invoke-WebRequest -Uri "http://$($info.IpAddress)/cgi-bin/config?reboot" - $nextTimeout = 300 # This takes a long time so wait longer next time + try { + Invoke-WebRequest -Uri "http://$($info.IpAddress)/cgi-bin/config?reboot" + $nextTimeout = 300 # This takes a long time so wait longer next time + } catch { + Write-Warning "Failed to reboot host bridge: $_" + } } } } @@ -132,6 +199,12 @@ class SwitchProvider : DeviceProvider { throw 'Failed to connect to the Switch Devkit.' } + # Verify the device is actually connected after recovery attempts + $finalStatus = $this.GetDeviceStatus().StatusData + if ("$($finalStatus.Status)" -ne 'Connected') { + throw "Failed to connect to the Switch Devkit. Device status: $($finalStatus.Status)" + } + Write-Debug 'Successfully connected to the Switch Devkit.' return $this.CreateSessionInfo() }