1 // 2 // Copyright (c) 2010-2022 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using Antmicro.Renode.Peripherals; 10 using Antmicro.Renode.Peripherals.UART; 11 using Antmicro.Renode.Utilities; 12 using System.Linq; 13 using AntShell.Terminal; 14 using Antmicro.Renode.Core; 15 using Antmicro.Renode.Exceptions; 16 using Antmicro.Renode.Logging; 17 18 namespace Antmicro.Renode.UI 19 { 20 public class ConsoleWindowBackendAnalyzer : IAnalyzableBackendAnalyzer<UARTBackend>, IDisposable 21 { 22 // Default constructor is required for the showAnalyzer command. ConsoleWindowBackendAnalyzer()23 public ConsoleWindowBackendAnalyzer() : this(false) 24 { 25 } 26 ConsoleWindowBackendAnalyzer(bool isMonitorWindow)27 public ConsoleWindowBackendAnalyzer(bool isMonitorWindow) 28 { 29 IO = new IOProvider(); 30 this.isMonitorWindow = isMonitorWindow; 31 } 32 Dispose()33 public void Dispose() 34 { 35 if(provider is IDisposable disposableProvider) 36 { 37 disposableProvider.Dispose(); 38 } 39 } 40 AttachTo(UARTBackend backend)41 public void AttachTo(UARTBackend backend) 42 { 43 Backend = backend; 44 if(EmulationManager.Instance.CurrentEmulation.TryGetEmulationElementName(backend.UART, out var uartName)) 45 { 46 Name = uartName; 47 } 48 } 49 Show()50 public void Show() 51 { 52 var availableProviders = TypeManager.Instance.AutoLoadedTypes.Where(x => !x.IsAbstract && typeof(IConsoleBackendAnalyzerProvider).IsAssignableFrom(x)).ToDictionary(x => GetProviderName(x), x => x); 53 var preferredProvider = ConfigurationManager.Instance.Get("general", "terminal", "XTerm"); 54 55 foreach(var providerName in availableProviders.Keys.OrderByDescending(x => x == preferredProvider)) 56 { 57 var providerType = availableProviders[providerName]; 58 if(providerType.GetConstructor(new Type[0]) == null) 59 { 60 Logger.Log(LogLevel.Warning, "There is no default public constructor for {0} console backend analyzer provider. Skipping it.", providerName); 61 continue; 62 } 63 provider = (IConsoleBackendAnalyzerProvider)Activator.CreateInstance(availableProviders[providerName]); 64 provider.OnClose += OnClose; 65 if(!provider.TryOpen(Name, out IIOSource ioSource, isMonitorWindow)) 66 { 67 Logger.Log(LogLevel.Warning, "Could not open {0} console backend analyzer provider. Trying the next one.", providerName); 68 continue; 69 } 70 IO.Backend = ioSource; 71 if(Backend != null) 72 { 73 ((UARTBackend)Backend).BindAnalyzer(IO); 74 } 75 return; 76 } 77 78 throw new InvalidOperationException($"Could not start any console backend analyzer. Tried: {(string.Join(", ", availableProviders.Keys))}."); 79 } 80 Hide()81 public void Hide() 82 { 83 var p = provider; 84 if(p == null) 85 { 86 return; 87 } 88 89 if(Backend != null) 90 { 91 ((UARTBackend)Backend).UnbindAnalyzer(IO); 92 Backend = null; 93 } 94 p.Close(); 95 provider = null; 96 } 97 98 public string Name { get; private set; } 99 100 public IAnalyzableBackend Backend { get; private set; } 101 102 public IOProvider IO { get; private set; } 103 104 public event Action Quitted; 105 GetProviderName(Type type)106 private string GetProviderName(Type type) 107 { 108 var attribute = type.GetCustomAttributes(false).OfType<ConsoleBackendAnalyzerProviderAttribute>().SingleOrDefault(); 109 if(attribute != null) 110 { 111 return attribute.Name; 112 } 113 114 return type.Name.EndsWith("Provider", StringComparison.Ordinal) ? type.Name.Substring(0, type.Name.Length - 8) : type.Name; 115 } 116 OnClose()117 private void OnClose() 118 { 119 Quitted?.Invoke(); 120 } 121 122 private readonly bool isMonitorWindow; 123 private IConsoleBackendAnalyzerProvider provider; 124 } 125 } 126