Hardware/Mainboard/SuperIOHardware.cs
author moel.mich
Sat, 05 Jun 2010 11:15:16 +0000
changeset 132 680ed54e05ca
parent 130 80065ab20b84
child 133 9ad699538c89
permissions -rw-r--r--
Fixed Issue 23.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Drawing;
    41 using OpenHardwareMonitor.Hardware.LPC;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Mainboard {
    44   public class SuperIOHardware : Hardware {
    45 
    46     private ISuperIO superIO;
    47     private Image icon;
    48     protected readonly string name;
    49 
    50     private List<Sensor> voltages = new List<Sensor>();
    51     private List<Sensor> temperatures = new List<Sensor>();
    52     private List<Sensor> fans = new List<Sensor>();  
    53 
    54     public SuperIOHardware(ISuperIO superIO, Manufacturer manufacturer, 
    55       Model model) 
    56     {
    57       this.superIO = superIO;
    58       this.icon = Utilities.EmbeddedResources.GetImage("chip.png");
    59 
    60       switch (superIO.Chip) {
    61         case Chip.F71858: name = "Fintek F71858"; break;
    62         case Chip.F71862: name = "Fintek F71862"; break;
    63         case Chip.F71869: name = "Fintek F71869"; break;
    64         case Chip.F71882: name = "Fintek F71882"; break;
    65         case Chip.F71889ED: name = "Fintek F71889ED"; break;
    66         case Chip.F71889F: name = "Fintek F71889F"; break;
    67         case Chip.IT8712F: this.name = "ITE IT8712F"; break;
    68         case Chip.IT8716F: this.name = "ITE IT8716F"; break;
    69         case Chip.IT8718F: this.name = "ITE IT8718F"; break;
    70         case Chip.IT8720F: this.name = "ITE IT8720F"; break;
    71         case Chip.IT8726F: this.name = "ITE IT8726F"; break;
    72         case Chip.W83627DHG: this.name = "Winbond W83627DHG"; break;
    73         case Chip.W83627DHGP: this.name = "Winbond W83627DHG-P"; break;
    74         case Chip.W83627EHF: this.name = "Winbond W83627EHF"; break;
    75         case Chip.W83627HF: this.name = "Winbond W83627HF"; break;
    76         case Chip.W83627THF: this.name = "Winbond W83627THF"; break;
    77         case Chip.W83667HG: this.name = "Winbond W83667HG"; break;
    78         case Chip.W83667HGB: this.name = "Winbond W83667HG-B"; break;
    79         case Chip.W83687THF: this.name = "Winbond W83687THF"; break;
    80       }
    81 
    82       List<Voltage> v = new List<Voltage>();
    83       List<Temperature> t = new List<Temperature>();
    84       List<Fan> f = new List<Fan>();
    85 
    86       switch (superIO.Chip) {
    87         case Chip.IT8712F:
    88         case Chip.IT8716F:
    89         case Chip.IT8718F:
    90         case Chip.IT8720F:
    91         case Chip.IT8726F:
    92           switch (manufacturer) {
    93             case Manufacturer.DFI:
    94               switch (model) {
    95                 case Model.LP_BI_P45_T2RS_Elite:
    96                   v.Add(new Voltage("CPU VCore", 0));
    97                   v.Add(new Voltage("FSB VTT", 1));
    98                   v.Add(new Voltage("+3.3V", 2));
    99                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   100                   v.Add(new Voltage("+12V", 4, 30, 10, 0));
   101                   v.Add(new Voltage("NB Core", 5));
   102                   v.Add(new Voltage("VDIMM", 6));
   103                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
   104                   v.Add(new Voltage("VBat", 8));
   105                   t.Add(new Temperature("CPU", 0));
   106                   t.Add(new Temperature("System", 1));
   107                   t.Add(new Temperature("Chipset", 2));
   108                   f.Add(new Fan("Fan #1", 0));
   109                   f.Add(new Fan("Fan #2", 1));
   110                   f.Add(new Fan("Fan #3", 2));
   111                   break;
   112                 case Model.LP_DK_P55_T3eH9:
   113                   v.Add(new Voltage("CPU VCore", 0));
   114                   v.Add(new Voltage("VTT", 1));
   115                   v.Add(new Voltage("+3.3V", 2));
   116                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   117                   v.Add(new Voltage("+12V", 4, 30, 10, 0));
   118                   v.Add(new Voltage("CPU PLL", 5));
   119                   v.Add(new Voltage("DRAM", 6));
   120                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
   121                   v.Add(new Voltage("VBat", 8));
   122                   t.Add(new Temperature("Chipset", 0));
   123                   t.Add(new Temperature("CPU PWM", 1));
   124                   t.Add(new Temperature("CPU", 2));
   125                   f.Add(new Fan("Fan #1", 0));
   126                   f.Add(new Fan("Fan #2", 1));
   127                   f.Add(new Fan("Fan #3", 2));
   128                   break;
   129                 default:
   130                   v.Add(new Voltage("CPU VCore", 0));
   131                   v.Add(new Voltage("VTT", 1, true));
   132                   v.Add(new Voltage("+3.3V", 2, true));
   133                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0, true));
   134                   v.Add(new Voltage("+12V", 4, 30, 10, 0, true));
   135                   v.Add(new Voltage("Voltage #6", 5, true));
   136                   v.Add(new Voltage("DRAM", 6, true));
   137                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0, true));
   138                   v.Add(new Voltage("VBat", 8));
   139                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   140                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   141                   for (int i = 0; i < superIO.Fans.Length; i++)
   142                     f.Add(new Fan("Fan #" + (i + 1), i));
   143                   break;
   144               }
   145               break;
   146 
   147             case Manufacturer.Gigabyte:
   148               switch (model) {
   149                 case Model._965P_S3:
   150                   v.Add(new Voltage("CPU VCore", 0));
   151                   v.Add(new Voltage("DRAM", 1));
   152                   v.Add(new Voltage("+3.3V", 2));
   153                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   154                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
   155                   v.Add(new Voltage("VBat", 8));
   156                   t.Add(new Temperature("System", 0));
   157                   t.Add(new Temperature("CPU", 1));
   158                   f.Add(new Fan("CPU Fan", 0));
   159                   f.Add(new Fan("System Fan", 1));
   160                   break;
   161                 case Model.EP45_DS3R:
   162                 case Model.EP45_UD3R: 
   163                 case Model.X38_DS5:
   164                   v.Add(new Voltage("CPU VCore", 0));
   165                   v.Add(new Voltage("DRAM", 1));
   166                   v.Add(new Voltage("+3.3V", 2));
   167                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   168                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
   169                   v.Add(new Voltage("VBat", 8));
   170                   t.Add(new Temperature("System", 0));
   171                   t.Add(new Temperature("CPU", 1));
   172                   f.Add(new Fan("CPU Fan", 0));
   173                   f.Add(new Fan("System Fan #2", 1));
   174                   f.Add(new Fan("Power Fan", 2));
   175                   f.Add(new Fan("System Fan #1", 3));
   176                   break;
   177                 case Model.P35_DS3:
   178                   v.Add(new Voltage("CPU VCore", 0));
   179                   v.Add(new Voltage("DRAM", 1));
   180                   v.Add(new Voltage("+3.3V", 2));
   181                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   182                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
   183                   v.Add(new Voltage("VBat", 8));
   184                   t.Add(new Temperature("System", 0));
   185                   t.Add(new Temperature("CPU", 1));
   186                   f.Add(new Fan("CPU Fan", 0));
   187                   f.Add(new Fan("System Fan #1", 1));
   188                   f.Add(new Fan("System Fan #2", 2));
   189                   f.Add(new Fan("Power Fan", 3));
   190                   break;
   191                 case Model.GA_MA785GMT_UD2H:
   192                   v.Add(new Voltage("CPU VCore", 0));
   193                   v.Add(new Voltage("DRAM", 1));
   194                   v.Add(new Voltage("+3.3V", 2));
   195                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   196                   v.Add(new Voltage("+12V", 4, 27, 9.1f, 0));
   197                   v.Add(new Voltage("VBat", 8));
   198                   t.Add(new Temperature("System", 0));
   199                   t.Add(new Temperature("CPU", 1));
   200                   f.Add(new Fan("CPU Fan", 0));
   201                   f.Add(new Fan("System Fan", 1));
   202                   f.Add(new Fan("NB Fan", 2));
   203                   break;
   204                 default:
   205                   v.Add(new Voltage("CPU VCore", 0));
   206                   v.Add(new Voltage("DRAM", 1, true));
   207                   v.Add(new Voltage("+3.3V", 2, true));
   208                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0, true));
   209                   v.Add(new Voltage("Voltage #5", 4, true));
   210                   v.Add(new Voltage("Voltage #6", 5, true));
   211                   v.Add(new Voltage("Voltage #7", 6, true));
   212                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0, true));
   213                   v.Add(new Voltage("VBat", 8));
   214                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   215                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   216                   for (int i = 0; i < superIO.Fans.Length; i++)
   217                     f.Add(new Fan("Fan #" + (i + 1), i));
   218                   break;
   219               }
   220               break;
   221 
   222             default:
   223               v.Add(new Voltage("CPU VCore", 0));
   224               v.Add(new Voltage("Voltage #2", 1, true));
   225               v.Add(new Voltage("Voltage #3", 2, true));
   226               v.Add(new Voltage("Voltage #4", 3, true));
   227               v.Add(new Voltage("Voltage #5", 4, true));
   228               v.Add(new Voltage("Voltage #6", 5, true));
   229               v.Add(new Voltage("Voltage #7", 6, true));
   230               v.Add(new Voltage("Voltage #8", 7, true));
   231               v.Add(new Voltage("VBat", 8));
   232               for (int i = 0; i < superIO.Temperatures.Length; i++)
   233                 t.Add(new Temperature("Temperature #" + (i + 1), i));
   234               for (int i = 0; i < superIO.Fans.Length; i++)
   235                 f.Add(new Fan("Fan #" + (i + 1), i));
   236               break;
   237           }
   238           break;
   239           
   240         case Chip.F71858:
   241           v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   242           v.Add(new Voltage("VSB3V", 1, 150, 150, 0));
   243           v.Add(new Voltage("Battery", 2, 150, 150, 0));
   244           for (int i = 0; i < superIO.Temperatures.Length; i++)
   245             t.Add(new Temperature("Temperature #" + (i + 1), i));
   246           for (int i = 0; i < superIO.Fans.Length; i++)
   247             f.Add(new Fan("Fan #" + (i + 1), i));
   248           break;
   249         case Chip.F71862: 
   250         case Chip.F71869: 
   251         case Chip.F71882:
   252         case Chip.F71889ED: 
   253         case Chip.F71889F:
   254           switch (manufacturer) {
   255             case Manufacturer.EVGA:
   256               switch (model) {
   257                 case Model.X58_SLI_Classified:
   258                   v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   259                   v.Add(new Voltage("CPU VCore", 1, 47, 100, 0));
   260                   v.Add(new Voltage("DIMM", 2, 47, 100, 0));
   261                   v.Add(new Voltage("CPU VTT", 3, 24, 100, 0));
   262                   v.Add(new Voltage("IOH Vcore", 4, 24, 100, 0));
   263                   v.Add(new Voltage("+5V", 5, 51, 12, 0));
   264                   v.Add(new Voltage("+12V", 6, 56, 6.8f, 0));
   265                   v.Add(new Voltage("3VSB", 7, 150, 150, 0));
   266                   v.Add(new Voltage("VBat", 8, 150, 150, 0));
   267                   t.Add(new Temperature("CPU", 0));
   268                   t.Add(new Temperature("VREG", 1));
   269                   t.Add(new Temperature("System", 2));
   270                   f.Add(new Fan("CPU Fan", 0));
   271                   f.Add(new Fan("Power Fan", 1));
   272                   f.Add(new Fan("Chassis Fan", 2));
   273                   break;
   274                 default:
   275                   v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   276                   v.Add(new Voltage("CPU VCore", 1));
   277                   v.Add(new Voltage("Voltage #3", 2, true));
   278                   v.Add(new Voltage("Voltage #4", 3, true));
   279                   v.Add(new Voltage("Voltage #5", 4, true));
   280                   v.Add(new Voltage("Voltage #6", 5, true));
   281                   v.Add(new Voltage("Voltage #7", 6, true));
   282                   v.Add(new Voltage("VSB3V", 7, 150, 150, 0));
   283                   v.Add(new Voltage("VBat", 8, 150, 150, 0));
   284                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   285                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   286                   for (int i = 0; i < superIO.Fans.Length; i++)
   287                     f.Add(new Fan("Fan #" + (i + 1), i));
   288                   break;
   289               }
   290               break;
   291             default:
   292               v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   293               v.Add(new Voltage("CPU VCore", 1));
   294               v.Add(new Voltage("Voltage #3", 2, true));
   295               v.Add(new Voltage("Voltage #4", 3, true));
   296               v.Add(new Voltage("Voltage #5", 4, true));
   297               v.Add(new Voltage("Voltage #6", 5, true));
   298               v.Add(new Voltage("Voltage #7", 6, true));
   299               v.Add(new Voltage("VSB3V", 7, 150, 150, 0));
   300               v.Add(new Voltage("VBat", 8, 150, 150, 0));
   301               for (int i = 0; i < superIO.Temperatures.Length; i++)
   302                 t.Add(new Temperature("Temperature #" + (i + 1), i));
   303               for (int i = 0; i < superIO.Fans.Length; i++)
   304                 f.Add(new Fan("Fan #" + (i + 1), i));
   305               break;
   306           }
   307           break;
   308 
   309         case Chip.W83627EHF:          
   310           v.Add(new Voltage("CPU VCore", 0));
   311           v.Add(new Voltage("Voltage #2", 1, true));
   312           v.Add(new Voltage("AVCC", 2, 34, 34, 0));
   313           v.Add(new Voltage("3VCC", 3, 34, 34, 0));
   314           v.Add(new Voltage("Voltage #5", 4, true));
   315           v.Add(new Voltage("Voltage #6", 5, true));
   316           v.Add(new Voltage("Voltage #7", 6, true));
   317           v.Add(new Voltage("3VSB", 7, 34, 34, 0));
   318           v.Add(new Voltage("VBAT", 8, 34, 34, 0));
   319           v.Add(new Voltage("Voltage #10", 9, true));
   320           t.Add(new Temperature("CPU", 0));
   321           t.Add(new Temperature("Auxiliary", 1));
   322           t.Add(new Temperature("System", 2));
   323           f.Add(new Fan("System", 0));
   324           f.Add(new Fan("CPU", 1));
   325           f.Add(new Fan("Auxiliary", 2));
   326           f.Add(new Fan("CPU #2", 3));
   327           f.Add(new Fan("Auxiliary #2", 4));
   328           break;
   329         case Chip.W83627DHG: 
   330         case Chip.W83627DHGP:                      
   331         case Chip.W83667HG:
   332         case Chip.W83667HGB:
   333           v.Add(new Voltage("CPU VCore", 0));
   334           v.Add(new Voltage("Voltage #2", 1, true));
   335           v.Add(new Voltage("AVCC", 2, 34, 34, 0));
   336           v.Add(new Voltage("3VCC", 3, 34, 34, 0));
   337           v.Add(new Voltage("Voltage #5", 4, true));
   338           v.Add(new Voltage("Voltage #6", 5, true));
   339           v.Add(new Voltage("Voltage #7", 6, true));
   340           v.Add(new Voltage("3VSB", 7, 34, 34, 0));
   341           v.Add(new Voltage("VBAT", 8, 34, 34, 0));
   342           t.Add(new Temperature("CPU", 0));
   343           t.Add(new Temperature("Auxiliary", 1));
   344           t.Add(new Temperature("System", 2));
   345           f.Add(new Fan("System", 0));
   346           f.Add(new Fan("CPU", 1));
   347           f.Add(new Fan("Auxiliary", 2));
   348           f.Add(new Fan("CPU #2", 3));
   349           f.Add(new Fan("Auxiliary #2", 4));            
   350           break;
   351         case Chip.W83627HF: 
   352         case Chip.W83627THF: 
   353         case Chip.W83687THF:
   354           v.Add(new Voltage("CPU VCore", 0));
   355           v.Add(new Voltage("Voltage #2", 1, true));
   356           v.Add(new Voltage("Voltage #3", 2, true));
   357           v.Add(new Voltage("AVCC", 3, 34, 51, 0));
   358           v.Add(new Voltage("Voltage #5", 4, true));
   359           v.Add(new Voltage("5VSB", 5, 34, 51, 0));
   360           v.Add(new Voltage("VBAT", 6));
   361           t.Add(new Temperature("CPU", 0));
   362           t.Add(new Temperature("Auxiliary", 1));
   363           t.Add(new Temperature("System", 2));
   364           f.Add(new Fan("System", 0));
   365           f.Add(new Fan("CPU", 1));
   366           f.Add(new Fan("Auxiliary", 2));
   367           break;
   368         default:
   369           for (int i = 0; i < superIO.Voltages.Length; i++)
   370             v.Add(new Voltage("Voltage #" + (i + 1), i, true));
   371           for (int i = 0; i < superIO.Temperatures.Length; i++)
   372             t.Add(new Temperature("Temperature #" + (i + 1), i));
   373           for (int i = 0; i < superIO.Fans.Length; i++)
   374             f.Add(new Fan("Fan #" + (i + 1), i));
   375           break;
   376       }
   377 
   378       string formula = "Voltage = value + (value - Vf) * Ri / Rf.";
   379       foreach (Voltage voltage in v) 
   380         if (voltage.Index < superIO.Voltages.Length) {
   381           Sensor sensor = new Sensor(voltage.Name, voltage.Index, 
   382             voltage.Hidden, null, SensorType.Voltage, this, 
   383             new ParameterDescription[] {
   384             new ParameterDescription("Ri [kΩ]", "Input resistance.\n" + 
   385               formula, voltage.Ri),
   386             new ParameterDescription("Rf [kΩ]", "Reference resistance.\n" + 
   387               formula, voltage.Rf),
   388             new ParameterDescription("Vf [V]", "Reference voltage.\n" + 
   389               formula, voltage.Vf)
   390             });
   391           voltages.Add(sensor);
   392       }
   393 
   394       foreach (Temperature temperature in t) 
   395         if (temperature.Index < superIO.Temperatures.Length) {
   396         Sensor sensor = new Sensor(temperature.Name, temperature.Index, null,
   397           SensorType.Temperature, this, new ParameterDescription[] {
   398           new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
   399         });
   400         temperatures.Add(sensor);
   401       }
   402 
   403       foreach (Fan fan in f)
   404         if (fan.Index < superIO.Fans.Length) {
   405           Sensor sensor = new Sensor(fan.Name, fan.Index, null, SensorType.Fan,
   406             this, null);
   407           fans.Add(sensor);
   408         }
   409     }
   410 
   411     public override Identifier Identifier {
   412       get { return new Identifier("lpc", superIO.Chip.ToString().ToLower()); }
   413     }
   414 
   415     public override Image Icon {
   416       get { return icon; }
   417     }
   418 
   419     public override string Name {
   420       get { return name; }
   421     }
   422 
   423     public override string GetReport() {
   424       return superIO.GetReport();
   425     }
   426 
   427     public override void Update() {
   428       superIO.Update();
   429 
   430       foreach (Sensor sensor in voltages) {
   431         float? value = superIO.Voltages[sensor.Index];
   432         if (value.HasValue) {
   433           sensor.Value = value + (value - sensor.Parameters[2].Value) *
   434             sensor.Parameters[0].Value / sensor.Parameters[1].Value;
   435           ActivateSensor(sensor);
   436         }
   437       }
   438 
   439       foreach (Sensor sensor in temperatures) {
   440         float? value = superIO.Temperatures[sensor.Index];
   441         if (value.HasValue) {
   442           sensor.Value = value + sensor.Parameters[0].Value;
   443           ActivateSensor(sensor);
   444         }
   445       }
   446 
   447       foreach (Sensor sensor in fans) {
   448         float? value = superIO.Fans[sensor.Index];
   449         if (value.HasValue) {
   450           sensor.Value = value;
   451           if (value.Value > 0)
   452             ActivateSensor(sensor);
   453         }
   454       }
   455     }
   456 
   457     private class Voltage {
   458       public readonly string Name;
   459       public readonly int Index;
   460       public readonly float Ri;
   461       public readonly float Rf;
   462       public readonly float Vf;
   463       public readonly bool Hidden;
   464 
   465       public Voltage(string name, int index) :
   466         this(name, index, 0, 1, 0, false) { }
   467 
   468       public Voltage(string name, int index, bool hidden) :
   469         this(name, index, 0, 1, 0, hidden) { }
   470 
   471       public Voltage(string name, int index, float ri, float rf, float vf) :
   472         this(name, index, ri, rf, vf, false) { }
   473 
   474       public Voltage(string name, int index, float ri, float rf, float vf,
   475         bool hidden) {
   476         this.Name = name;
   477         this.Index = index;
   478         this.Ri = ri;
   479         this.Rf = rf;
   480         this.Vf = vf;
   481         this.Hidden = hidden;
   482       }
   483     }
   484 
   485     private class Temperature {
   486       public readonly string Name;
   487       public readonly int Index;
   488 
   489       public Temperature(string name, int index) {
   490         this.Name = name;
   491         this.Index = index;
   492       }
   493     }
   494 
   495     private class Fan {
   496       public readonly string Name;
   497       public readonly int Index;
   498 
   499       public Fan(string name, int index) {
   500         this.Name = name;
   501         this.Index = index;
   502       }
   503     }
   504   }
   505 }