/ src / core / heuristics.cc
heuristics.cc
  1  /*
  2   * heuristics.cc
  3   *
  4   *
  5   */
  6  
  7  #include "version.h"
  8  #include "sysfs.h"
  9  #include "jedec.h"
 10  #include "osutils.h"
 11  
 12  #include <stdlib.h>
 13  #include <regex.h>
 14  
 15  __ID("@(#) $Id$");
 16  
 17  string guessBusInfo(const string & info)
 18  {
 19                                                    // NVMe: "nvme"host"n"namespace
 20    if(matches(info, "^nvme[0-9]+n[0-9]+$"))
 21    {
 22      string s = info;
 23      size_t n = s.rfind("n");
 24      s[n] = ':';
 25      return "nvme@" + s.substr(4, string::npos);
 26    }
 27  
 28                                                    // SD/MMC: "mmc"host:address
 29    if(matches(info, "^mmc[0-9]+(:[[:xdigit:]]+)+$"))
 30    {
 31      return "mmc@" + info.substr(3, string::npos);
 32    }
 33  
 34                                                    // 2.6-style PCI
 35    if(matches(info,"^[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]\\.[[:xdigit:]]$"))
 36    {
 37      return "pci@" + info;
 38    }
 39                                                    // 2.4-style PCI
 40    if(matches(info,"^[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]\\.[[:xdigit:]]$"))
 41    {
 42      return "pci@0000:" + info;
 43    }
 44  
 45                                                    // USB: host-port[.port]:config.interface
 46    if(matches(info, "^[0-9]+-[0-9]+(\\.[0-9]+)*:[0-9]+\\.[0-9]+$"))
 47    {
 48      size_t colon = info.rfind(":");
 49      size_t dash = info.find("-");
 50  
 51      return "usb@" + info.substr(0, dash) + ":" + info.substr(dash+1, colon-dash-1);
 52    }
 53  
 54    if(matches(info, "^[[:xdigit:]]+-[0-9]+$"))     // Firewire: guid-function
 55    {
 56      size_t dash = info.find("-");
 57  
 58      return "firewire@" + info.substr(0, dash);
 59    }
 60  
 61  #if 1
 62  //#ifdef __hppa__
 63    if(matches(info, "^[0-9]+(:[0-9]+)*$"))         // PA-RISC: x:y:z:t corresponds to /x/y/z/t
 64    {
 65      string result = "parisc@";
 66  
 67      for(unsigned i=0; i<info.length(); i++)
 68        if(info[i] == ':')
 69          result += '/';
 70      else
 71        result += info[i];
 72      return result;
 73    }
 74  #endif
 75    return "";
 76  }
 77  
 78  
 79  static string guessParentBusInfo(const hwNode & child)
 80  {
 81    string sysfs_path = sysfs_finddevice(child.getLogicalName());
 82    vector < string > path;
 83    string result = "";
 84  
 85    if(sysfs_path == "") return "";
 86  
 87    splitlines(sysfs_path, path, '/');
 88  
 89    if(path.size()>1)
 90      path.pop_back();
 91    else
 92      return "";
 93  
 94    while((result=="") && (path.size()>1))
 95    {
 96      result = guessBusInfo(path[path.size()-1]);
 97      path.pop_back();
 98    }
 99    return result;
100  }
101  
102  
103  hwNode * guessParent(const hwNode & child, hwNode & base)
104  {
105    return base.findChildByBusInfo(guessParentBusInfo(child));
106  }
107  
108  static const char *disk_manufacturers[] =
109  {
110    "^ST(?!I\\ ).+", "Seagate",
111    "^STI\\ .+", "SimpleTech",
112    "^D...-.+", "IBM",
113    "^IBM.+", "IBM",
114    "^HITACHI.+", "Hitachi",
115    "^IC.+", "Hitachi",
116    "^HTS.+", "Hitachi",
117    "^FUJITSU.+", "Fujitsu",
118    "^MP.+", "Fujitsu",
119    "^TOSHIBA.+", "Toshiba",
120    "^MK.+", "Toshiba",
121    "^MAXTOR.+", "Maxtor",
122    "^Pioneer.+", "Pioneer",
123    "^PHILIPS.+", "Philips",
124    "^QUANTUM.+", "Quantum",
125    "FIREBALL.+", "Quantum",
126    "^WDC.+", "Western Digital",
127    "WD.+", "Western Digital",
128    "^VBOX.+", "VirtualBox",
129    NULL, NULL
130  };
131  
132  bool guessVendor(hwNode & device)
133  {
134    int i = 0;
135    bool result = false;
136  
137  
138    device.setVendor(jedec_resolve(device.getVendor()));
139  
140    if(device.getVendor() != "")
141      return false;
142  
143   
144    if(device.getClass() == hw::disk)
145      while (disk_manufacturers[i])
146      {
147        if (matches(device.getProduct().c_str(), disk_manufacturers[i], REG_ICASE))
148        {
149          device.setVendor(disk_manufacturers[i + 1]);
150          result = true;
151        }
152        i += 2;
153      }
154  
155    return result;
156  }
157  
158  
159  static string parsehex(const string & s)
160  {
161    unsigned int i = 0;
162    string result = "";
163  
164    if(matches(s,"^0x[[:xdigit:]][[:xdigit:]]+$"))
165    {
166      for(i=2; i<s.length(); i+=2)
167      {
168        string c = s.substr(i,2);
169        static char code[2];
170  
171        code[0] = strtol(c.c_str(), NULL, 16);
172        code[1] = '\0';
173        
174        if(code[0] < ' ') return s;
175        result += string(code);
176      }
177     }
178     else
179       return s;
180  
181    return result;
182  }
183  
184  bool guessProduct(hwNode & device)
185  {
186    string product = device.getProduct();
187  
188    if(product == "")
189      return false;
190  
191    device.setProduct(parsehex(product));
192  
193    return true;
194  }
195