/ src / core / hw.cc
hw.cc
   1  #define _XOPEN_SOURCE
   2  #include "hw.h"
   3  #include "osutils.h"
   4  #include "version.h"
   5  #include "config.h"
   6  #include "options.h"
   7  #include "heuristics.h"
   8  #include "dump.h"
   9  #include "db.h"
  10  #include <cstring>
  11  #include <vector>
  12  #include <map>
  13  #include <sstream>
  14  #include <stdlib.h>
  15  #include <stdio.h>
  16  #include <string.h>
  17  #include <ctype.h>
  18  #include <limits.h>
  19  #include <unistd.h>
  20  #include <limits.h>
  21  #include <sys/utsname.h>
  22  
  23  using namespace hw;
  24  
  25  __ID("@(#) $Id$");
  26  
  27  struct hwNode_i
  28  {
  29    hwClass deviceclass;
  30    string id, vendor, product, version, date, serial, slot, handle, description,
  31      businfo, physid, dev, modalias, subvendor, subproduct;
  32    bool enabled;
  33    bool claimed;
  34    unsigned long long start;
  35    unsigned long long size;
  36    unsigned long long capacity;
  37    unsigned long long clock;
  38    unsigned int width;
  39    vector < hwNode > children;
  40    vector < string > attracted;
  41    vector < string > features;
  42    vector < string > logicalnames;
  43    map < string, string > features_descriptions;
  44    vector < resource > resources;
  45    map < string, string > config;
  46    map < string, value > hints;
  47  };
  48  
  49  string hw::strip(const string & s)
  50  {
  51    string result = s;
  52    size_t i = result.find('\0');
  53  
  54    if(i != string::npos)
  55      result = result.substr(0, i);
  56  
  57    while ((result.length() > 0) && ((uint8_t)result[0] <= ' '))
  58      result.erase(0, 1);
  59    while ((result.length() > 0) && ((uint8_t)result[result.length() - 1] <= ' '))
  60      result.erase(result.length() - 1);
  61  
  62    for (i = 0; i < result.length(); i++)
  63      if ((uint8_t)result[i] < ' ')
  64      {
  65        result.erase(i, 1);
  66        i--;
  67      }
  68  
  69    result = utf8_sanitize(result);
  70  
  71    return result;
  72  }
  73  
  74  string hw::asString(long n)
  75  {
  76    char buffer[256];
  77  
  78    snprintf(buffer, sizeof(buffer), "%ld", n);
  79    return string(buffer);
  80  }
  81  
  82  static string cleanupId(const string & id)
  83  {
  84    string result = strip(id);
  85  
  86    for (unsigned int i = 0; i < result.length(); i++)
  87    {
  88      result[i] = tolower(result[i]);
  89      if (!strchr("0123456789abcdefghijklmnopqrstuvwxyz_.:-", result[i]))
  90        result[i] = '_';
  91    }
  92  
  93    return result;
  94  }
  95  
  96  
  97  hwNode::hwNode(const string & id,
  98  hwClass c,
  99  const string & vendor,
 100  const string & product, const string & version)
 101  {
 102    This = NULL;
 103    This = new hwNode_i;
 104  
 105    if (!This)
 106      return;
 107  
 108    This->deviceclass = c;
 109    This->id = cleanupId(id);
 110    This->vendor = strip(vendor);
 111    This->product = strip(product);
 112    This->version = strip(version);
 113    This->start = 0;
 114    This->size = 0;
 115    This->capacity = 0;
 116    This->clock = 0;
 117    This->width = 0;
 118    This->enabled = true;
 119    This->claimed = false;
 120    This->handle = string("");
 121    This->description = string("");
 122    This->businfo = string("");
 123    This->physid = string("");
 124    This->dev = string("");
 125  }
 126  
 127  
 128  hwNode::hwNode(const hwNode & o)
 129  {
 130    This = NULL;
 131    This = new hwNode_i;
 132  
 133    if (!This)
 134      return;
 135  
 136    if (o.This)
 137      (*This) = (*o.This);
 138  }
 139  
 140  
 141  hwNode::~hwNode()
 142  {
 143    if (This)
 144      delete This;
 145  }
 146  
 147  
 148  hwNode & hwNode::operator = (const hwNode & o)
 149  {
 150    if (this == &o)
 151      return *this;                                 // self-affectation
 152  
 153    if (This)
 154      delete This;
 155    This = NULL;
 156    This = new hwNode_i;
 157  
 158    if (!This)
 159      return *this;
 160  
 161    if (o.This)
 162      (*This) = (*o.This);
 163  
 164    return *this;
 165  }
 166  
 167  
 168  hwClass hwNode::getClass() const
 169  {
 170    if (This)
 171      return This->deviceclass;
 172    else
 173      return hw::generic;
 174  }
 175  
 176  
 177  const char *hwNode::getClassName() const
 178  {
 179    if (This)
 180    {
 181      switch (This->deviceclass)
 182      {
 183        case processor:
 184          return "processor";
 185  
 186        case memory:
 187          return "memory";
 188  
 189        case address:
 190          return "address";
 191  
 192        case storage:
 193          return "storage";
 194  
 195        case disk:
 196          return "disk";
 197  
 198        case tape:
 199          return "tape";
 200  
 201        case hw::system:
 202          return "system";
 203  
 204        case bridge:
 205          return "bridge";
 206  
 207        case bus:
 208          return "bus";
 209  
 210        case network:
 211          return "network";
 212  
 213        case display:
 214          return "display";
 215  
 216        case input:
 217          return "input";
 218  
 219        case printer:
 220          return "printer";
 221  
 222        case multimedia:
 223          return "multimedia";
 224  
 225        case communication:
 226          return "communication";
 227  
 228        case power:
 229          return "power";
 230  
 231        case volume:
 232          return "volume";
 233  
 234        case accelerator:
 235         return "accelerator";
 236  
 237        default:
 238          return "generic";
 239      }
 240    }
 241    else
 242      return "generic";
 243  }
 244  
 245  
 246  void hwNode::setClass(hwClass c)
 247  {
 248    if (!This)
 249      return;
 250  
 251    This->deviceclass = c;
 252  }
 253  
 254  
 255  bool hwNode::enabled() const
 256  {
 257    if (!This)
 258      return false;
 259  
 260    return (This->enabled);
 261  }
 262  
 263  
 264  bool hwNode::disabled() const
 265  {
 266    if (!This)
 267      return true;
 268  
 269    return !(This->enabled);
 270  }
 271  
 272  
 273  void hwNode::enable()
 274  {
 275    if (!This)
 276      return;
 277  
 278    This->enabled = true;
 279  }
 280  
 281  
 282  void hwNode::disable()
 283  {
 284    if (!This)
 285      return;
 286  
 287    This->enabled = false;
 288  }
 289  
 290  
 291  bool hwNode::claimed() const
 292  {
 293    if (!This)
 294      return false;
 295  
 296    if (This->claimed)
 297      return true;
 298  
 299    for (unsigned int i = 0; i < This->children.size(); i++)
 300      if (This->children[i].claimed())
 301    {
 302      This->claimed = true;
 303      return true;
 304    }
 305  
 306    return false;
 307  }
 308  
 309  
 310  void hwNode::claim(bool claimchildren)
 311  {
 312    if (!This)
 313      return;
 314  
 315    This->claimed = true;
 316  
 317    if (!claimchildren)
 318      return;
 319  
 320    for (unsigned int i = 0; i < This->children.size(); i++)
 321      This->children[i].claim(claimchildren);
 322  }
 323  
 324  
 325  void hwNode::unclaim()
 326  {
 327    if (!This)
 328      return;
 329  
 330    This->claimed = false;
 331  }
 332  
 333  
 334  string hwNode::getId() const
 335  {
 336    if (This)
 337      return This->id;
 338    else
 339      return "";
 340  }
 341  
 342  
 343  void hwNode::setId(const string & id)
 344  {
 345    if (!This)
 346      return;
 347  
 348    This->id = cleanupId(id);
 349  }
 350  
 351  
 352  void hwNode::setHandle(const string & handle)
 353  {
 354    if (!This)
 355      return;
 356  
 357    This->handle = handle;
 358  }
 359  
 360  
 361  string hwNode::getHandle() const
 362  {
 363    if (This)
 364      return This->handle;
 365    else
 366      return "";
 367  }
 368  
 369  
 370  string hwNode::getDescription() const
 371  {
 372    if (This)
 373      return This->description;
 374    else
 375      return "";
 376  }
 377  
 378  
 379  void hwNode::setDescription(const string & description)
 380  {
 381    if (This)
 382      This->description = strip(description);
 383  }
 384  
 385  
 386  string hwNode::getVendor() const
 387  {
 388    if (This)
 389      return This->vendor;
 390    else
 391      return "";
 392  }
 393  
 394  
 395  void hwNode::setVendor(const string & vendor)
 396  {
 397    if (This)
 398      This->vendor = strip(vendor);
 399  }
 400  
 401  
 402  string hwNode::getSubVendor() const
 403  {
 404    if (This)
 405      return This->subvendor;
 406    else
 407      return "";
 408  }
 409  
 410  
 411  void hwNode::setSubVendor(const string & subvendor)
 412  {
 413    if (This)
 414      This->subvendor = strip(subvendor);
 415  }
 416  
 417  
 418  string hwNode::getProduct() const
 419  {
 420    if (This)
 421      return This->product;
 422    else
 423      return "";
 424  }
 425  
 426  
 427  void hwNode::setProduct(const string & product)
 428  {
 429    if (This)
 430      This->product = strip(product);
 431  }
 432  
 433  
 434  string hwNode::getSubProduct() const
 435  {
 436    if (This)
 437      return This->subproduct;
 438    else
 439      return "";
 440  }
 441  
 442  
 443  void hwNode::setSubProduct(const string & subproduct)
 444  {
 445    if (This)
 446      This->subproduct = strip(subproduct);
 447  }
 448  
 449  
 450  string hwNode::getVersion() const
 451  {
 452    if (This)
 453      return This->version;
 454    else
 455      return "";
 456  }
 457  
 458  
 459  void hwNode::setVersion(const string & version)
 460  {
 461    if (This)
 462      This->version = strip(version);
 463  }
 464  
 465  string hwNode::getDate() const
 466  {
 467    if (This)
 468      return This->date;
 469    else
 470      return "";
 471  }
 472  
 473  
 474  void hwNode::setDate(const string & s)
 475  {
 476    if (This)
 477      This->date = strip(s);
 478  }
 479  
 480  
 481  string hwNode::getSerial() const
 482  {
 483    if (This)
 484      return This->serial;
 485    else
 486      return "";
 487  }
 488  
 489  
 490  void hwNode::setSerial(const string & serial)
 491  {
 492    if(serial == "00000000-0000-0000-0000-000000000000")
 493      return;
 494  
 495    if (This)
 496      This->serial = strip(serial);
 497  }
 498  
 499  
 500  string hwNode::getSlot() const
 501  {
 502    if (This)
 503      return This->slot;
 504    else
 505      return "";
 506  }
 507  
 508  
 509  void hwNode::setSlot(const string & slot)
 510  {
 511    if (This)
 512      This->slot = strip(slot);
 513  }
 514  
 515  
 516  string hwNode::getModalias() const
 517  {
 518    if (This)
 519      return This->modalias;
 520    else
 521      return "";
 522  }
 523  
 524  
 525  void hwNode::setModalias(const string & modalias)
 526  {
 527    if (This)
 528      This->modalias = strip(modalias);
 529  }
 530  
 531  
 532  unsigned long long hwNode::getStart() const
 533  {
 534    if (This)
 535      return This->start;
 536    else
 537      return 0;
 538  }
 539  
 540  
 541  void hwNode::setStart(unsigned long long start)
 542  {
 543    if (This)
 544      This->start = start;
 545  }
 546  
 547  
 548  unsigned long long hwNode::getSize() const
 549  {
 550    if (This)
 551      return This->size;
 552    else
 553      return 0;
 554  }
 555  
 556  
 557  void hwNode::setSize(unsigned long long size)
 558  {
 559    if (This)
 560      This->size = size;
 561  }
 562  
 563  
 564  unsigned long long hwNode::getCapacity() const
 565  {
 566    if (This)
 567      return This->capacity;
 568    else
 569      return 0;
 570  }
 571  
 572  
 573  void hwNode::setCapacity(unsigned long long capacity)
 574  {
 575    if (This)
 576      This->capacity = capacity;
 577  }
 578  
 579  
 580  unsigned long long hwNode::getClock() const
 581  {
 582    if (This)
 583      return This->clock;
 584    else
 585      return 0;
 586  }
 587  
 588  
 589  void hwNode::setClock(unsigned long long clock)
 590  {
 591    if (This)
 592      This->clock = clock;
 593  }
 594  
 595  
 596  unsigned int hwNode::countChildren(hw::hwClass c) const
 597  {
 598    unsigned int count = 0;
 599  
 600    if (!This)
 601      return 0;
 602  
 603    if (c == hw::generic)
 604      return This->children.size();
 605  
 606    for (unsigned int i = 0; i < This->children.size(); i++)
 607      if (This->children[i].getClass() == c)
 608        count++;
 609  
 610    return count;
 611  }
 612  
 613  
 614  hwNode *hwNode::getChild(unsigned int i)
 615  {
 616    if (!This)
 617      return NULL;
 618  
 619    if (i >= This->children.size())
 620      return NULL;
 621    else
 622      return &(This->children[i]);
 623  }
 624  
 625  
 626  hwNode *hwNode::getChildByPhysId(const string & physid)
 627  {
 628    if (physid == "" || !This)
 629      return NULL;
 630  
 631    for (unsigned int i = 0; i < This->children.size(); i++)
 632    {
 633      if (This->children[i].getPhysId() == physid)
 634        return &(This->children[i]);
 635    }
 636  
 637    return NULL;
 638  }
 639  
 640  
 641  hwNode *hwNode::getChildByPhysId(long physid)
 642  {
 643    char buffer[20];
 644    if (!This)
 645      return NULL;
 646  
 647    snprintf(buffer, sizeof(buffer), "%lx", physid);
 648  
 649    for (unsigned int i = 0; i < This->children.size(); i++)
 650    {
 651      if (This->children[i].getPhysId() == string(buffer))
 652        return &(This->children[i]);
 653    }
 654  
 655    return NULL;
 656  }
 657  
 658  
 659  hwNode *hwNode::getChild(const string & id)
 660  {
 661    string baseid = id, path = "";
 662    size_t pos = 0;
 663  
 664    if (!This)
 665      return NULL;
 666  
 667    pos = id.find('/');
 668    if (pos != string::npos)
 669    {
 670      baseid = id.substr(0, pos);
 671      if (pos < id.length() - 1)
 672        path = id.substr(pos + 1);
 673    }
 674  
 675    for (unsigned int i = 0; i < This->children.size(); i++)
 676      if (This->children[i].getId() == cleanupId(baseid))
 677    {
 678      if (path == "")
 679        return &(This->children[i]);
 680      else
 681        return This->children[i].getChild(path);
 682    }
 683    return NULL;
 684  }
 685  
 686  
 687  hwNode *hwNode::findChild(bool(*matchfunction) (const hwNode &))
 688  {
 689    if (!This)
 690      return NULL;
 691  
 692    if (matchfunction(*this))
 693      return this;
 694  
 695    for (unsigned int i = 0; i < This->children.size(); i++)
 696    {
 697      hwNode *result = This->children[i].findChild(matchfunction);
 698  
 699      if (result)
 700        return result;
 701    }
 702  
 703    return NULL;
 704  }
 705  
 706  
 707  hwNode *hwNode::findChildByHandle(const string & handle)
 708  {
 709    if (!This)
 710      return NULL;
 711  
 712    if (This->handle == handle)
 713      return this;
 714  
 715    for (unsigned int i = 0; i < This->children.size(); i++)
 716    {
 717      hwNode *result = This->children[i].findChildByHandle(handle);
 718  
 719      if (result)
 720        return result;
 721    }
 722  
 723    return NULL;
 724  }
 725  
 726  
 727  hwNode *hwNode::findChildByLogicalName(const string & name)
 728  {
 729    unsigned int i = 0;
 730  
 731    if (!This)
 732      return NULL;
 733  
 734    for (i = 0; i < This->logicalnames.size(); i++)
 735      if (This->logicalnames[i] == name)
 736        return this;
 737  
 738    for (i = 0; i < This->children.size(); i++)
 739    {
 740      hwNode *result = This->children[i].findChildByLogicalName(name);
 741  
 742      if (result)
 743        return result;
 744    }
 745  
 746    return NULL;
 747  }
 748  
 749  
 750  hwNode *hwNode::findChildByBusInfo(const string & businfo)
 751  {
 752    if (!This)
 753      return NULL;
 754  
 755    if (strip(businfo) == "")
 756      return NULL;
 757  
 758    if (lowercase(strip(This->businfo)) == lowercase(strip(businfo)))
 759      return this;
 760  
 761    for (unsigned int i = 0; i < This->children.size(); i++)
 762    {
 763      hwNode *result = This->children[i].findChildByBusInfo(businfo);
 764  
 765      if (result)
 766        return result;
 767    }
 768  
 769    return NULL;
 770  }
 771  
 772  
 773  hwNode *hwNode::findChildByResource(const hw::resource & r)
 774  {
 775    if (!This)
 776      return NULL;
 777  
 778    if (this->usesResource(r))
 779      return this;
 780  
 781    for (unsigned int i = 0; i < This->children.size(); i++)
 782    {
 783      hwNode *result = This->children[i].findChildByResource(r);
 784  
 785      if (result)
 786        return result;
 787    }
 788  
 789    return NULL;
 790  }
 791  
 792  
 793  static string generateId(const string & radical,
 794  int count)
 795  {
 796    char buffer[10];
 797  
 798    snprintf(buffer, sizeof(buffer), "%d", count);
 799  
 800    return radical + ":" + string(buffer);
 801  }
 802  
 803  
 804  hwNode *hwNode::addChild(const hwNode & node)
 805  {
 806    hwNode *existing = NULL;
 807    hwNode *samephysid = NULL;
 808    string id = node.getId();
 809    int count = 0;
 810  
 811    if (!This)
 812      return NULL;
 813  
 814  // first see if the new node is attracted by one of our children
 815    for (unsigned int i = 0; i < This->children.size(); i++)
 816      if (This->children[i].attractsNode(node))
 817        return This->children[i].addChild(node);
 818  
 819  // find if another child already has the same physical id
 820  // in that case, we remove BOTH physical ids and let auto-allocation proceed
 821    if (node.getPhysId() != "")
 822      samephysid = getChildByPhysId(node.getPhysId());
 823    if (samephysid)
 824    {
 825      samephysid->setPhysId("");
 826    }
 827  
 828    existing = getChild(id);
 829    if (existing)                                   // first rename existing instance
 830    {
 831      while (getChild(generateId(id, count)))       // find a usable name
 832        count++;
 833  
 834      existing->setId(generateId(id, count));       // rename
 835    }
 836  
 837    while (getChild(generateId(id, count)))
 838      count++;
 839  
 840    This->children.push_back(node);
 841    if (existing || getChild(generateId(id, 0)))
 842      This->children.back().setId(generateId(id, count));
 843  
 844    if (samephysid)
 845      This->children.back().setPhysId("");
 846  
 847    return &(This->children.back());
 848  //return getChild(This->children.back().getId());
 849  }
 850  
 851  
 852  void hwNode::attractHandle(const string & handle)
 853  {
 854    if (!This)
 855      return;
 856  
 857    This->attracted.push_back(handle);
 858  }
 859  
 860  
 861  bool hwNode::attractsHandle(const string & handle) const
 862  {
 863    unsigned int i = 0;
 864    if (handle == "" || !This)
 865      return false;
 866  
 867    for (i = 0; i < This->attracted.size(); i++)
 868      if (This->attracted[i] == handle)
 869        return true;
 870  
 871    for (i = 0; i < This->children.size(); i++)
 872      if (This->children[i].attractsHandle(handle))
 873        return true;
 874  
 875    return false;
 876  }
 877  
 878  
 879  bool hwNode::attractsNode(const hwNode & node) const
 880  {
 881    if (!This || !node.This)
 882      return false;
 883  
 884    return attractsHandle(node.This->handle);
 885  }
 886  
 887  
 888  bool hwNode::isCapable(const string & feature) const
 889  {
 890    string featureid = cleanupId(feature);
 891  
 892    if (!This)
 893      return false;
 894  
 895    for (unsigned int i = 0; i < This->features.size(); i++)
 896      if (This->features[i] == featureid)
 897        return true;
 898  
 899    return false;
 900  }
 901  
 902  
 903  void hwNode::addCapability(const string & feature,
 904  const string & description)
 905  {
 906    string features = feature;
 907  
 908    if (!This)
 909      return;
 910  
 911    if (description != "")
 912      This->features_descriptions[cleanupId(feature)] = strip(description);
 913  
 914    while (features.length() > 0)
 915    {
 916      size_t pos = features.find('\0');
 917  
 918      if (pos == string::npos)
 919      {
 920        if (!isCapable(cleanupId(features)))
 921          This->features.push_back(cleanupId(features));
 922        features = "";
 923      }
 924      else
 925      {
 926        string featureid = cleanupId(features.substr(0, pos));
 927        if (!isCapable(featureid))
 928          This->features.push_back(featureid);
 929        features = features.substr(pos + 1);
 930      }
 931    }
 932  }
 933  
 934  
 935  void hwNode::describeCapability(const string & feature,
 936  const string & description)
 937  {
 938    if (!This)
 939      return;
 940  
 941    if (!isCapable(feature))
 942      return;
 943  
 944    This->features_descriptions[cleanupId(feature)] = strip(description);
 945  }
 946  
 947  
 948  string hwNode::getCapabilities() const
 949  {
 950    string result = "";
 951  
 952    if (!This)
 953      return "";
 954  
 955    for (unsigned int i = 0; i < This->features.size(); i++)
 956      result += This->features[i] + " ";
 957  
 958    return strip(result);
 959  }
 960  
 961  
 962  vector < string > hwNode::getCapabilitiesList() const
 963  {
 964    vector < string > result;
 965  
 966    if (!This)
 967      return result;
 968  
 969    for (unsigned int i = 0; i < This->features.size(); i++)
 970      result.push_back(This->features[i]);
 971  
 972    return result;
 973  }
 974  
 975  
 976  string hwNode::getCapabilityDescription(const string & feature) const
 977  {
 978    string featureid = cleanupId(feature);
 979  
 980    if (!isCapable(feature))
 981      return "";
 982  
 983    if (!This)
 984      return "";
 985  
 986    if (This->features_descriptions.find(featureid) ==
 987      This->features_descriptions.end())
 988      return "";
 989  
 990    return This->features_descriptions[featureid];
 991  }
 992  
 993  
 994  void hwNode::setConfig(const string & key,
 995  const string & value)
 996  {
 997    if (!This)
 998      return;
 999  
1000    This->config[key] = strip(value);
1001    if (strip(value) == "")
1002      This->config.erase(This->config.find(key));
1003  }
1004  
1005  
1006  void hwNode::setConfig(const string & key,
1007  unsigned long long value)
1008  {
1009    if (!This)
1010      return;
1011  
1012    This->config[key] = tostring(value);
1013  }
1014  
1015  
1016  string hwNode::getConfig(const string & key) const
1017  {
1018    if (!This)
1019      return "";
1020  
1021    if (This->config.find(key) == This->config.end())
1022      return "";
1023  
1024    return This->config[key];
1025  }
1026  
1027  
1028  vector < string > hwNode::getConfigKeys() const
1029  {
1030    vector < string > result;
1031  
1032    if (!This)
1033      return result;
1034  
1035    for (map < string, string >::iterator i = This->config.begin();
1036      i != This->config.end(); i++)
1037    result.push_back(i->first);
1038  
1039    return result;
1040  }
1041  
1042  vector < string > hwNode::getConfigValues(const string & separator) const
1043  {
1044    vector < string > result;
1045  
1046    if (!This)
1047      return result;
1048  
1049    for (map < string, string >::iterator i = This->config.begin();
1050      i != This->config.end(); i++)
1051    result.push_back(i->first + separator + i->second);
1052  
1053    return result;
1054  }
1055  
1056  
1057  string hwNode::getLogicalName() const
1058  {
1059    if (This && (This->logicalnames.size()>0))
1060      return This->logicalnames[0];
1061    else
1062      return "";
1063  }
1064  
1065  
1066  vector<string> hwNode::getLogicalNames() const
1067  {
1068    if (This)
1069      return This->logicalnames;
1070    else
1071      return vector<string>();
1072  }
1073  
1074  
1075  void hwNode::setLogicalName(const string & name)
1076  {
1077    string n = strip(name);
1078  
1079    if (This)
1080    {
1081      for (unsigned i = 0; i < This->logicalnames.size(); i++)
1082        if (This->logicalnames[i] == n || This->logicalnames[i] == "/dev/" + n)
1083          return;                                   // nothing to add, this logical name already exists
1084      if ((name[0] != '/') && exists("/dev/" + n))
1085      {
1086        This->logicalnames.push_back("/dev/" + n);
1087      }
1088      else
1089        This->logicalnames.push_back((n[0]=='/')?n:shortname(n));
1090  
1091      if(This->dev == "")
1092        This->dev = get_devid(n);
1093    }
1094  }
1095  
1096  
1097  string hwNode::getDev() const
1098  {
1099    if (This)
1100      return This->dev;
1101    else
1102      return "";
1103  }
1104  
1105  
1106  void hwNode::setDev(const string & s)
1107  {
1108    if (This)
1109    {
1110      string devid = strip(s);
1111      unsigned int i = 0;
1112  
1113      while((i<devid.length()) && isdigit(devid[i])) i++;
1114      if(i>=devid.length()) return;
1115      if(devid[i] != ':') return;
1116      i++;
1117      while((i<devid.length()) && isdigit(devid[i])) i++;
1118      if(i!=devid.length()) return;
1119  
1120      This->dev = devid;
1121    }
1122  }
1123  
1124  
1125  string hwNode::getBusInfo() const
1126  {
1127    if (This)
1128      return This->businfo;
1129    else
1130      return "";
1131  }
1132  
1133  
1134  void hwNode::setBusInfo(const string & businfo)
1135  {
1136    if (This)
1137    {
1138      if (businfo.find('@') != string::npos)
1139        This->businfo = strip(businfo);
1140      else
1141        This->businfo = guessBusInfo(strip(businfo));
1142    }
1143  }
1144  
1145  
1146  string hwNode::getPhysId() const
1147  {
1148    if (This)
1149      return This->physid;
1150    else
1151      return "";
1152  }
1153  
1154  
1155  void hwNode::setPhysId(long physid)
1156  {
1157    if (This)
1158    {
1159      char buffer[20];
1160  
1161      snprintf(buffer, sizeof(buffer), "%lx", physid);
1162      This->physid = string(buffer);
1163    }
1164  }
1165  
1166  
1167  void hwNode::setPhysId(unsigned physid1,
1168  unsigned physid2)
1169  {
1170    if (This)
1171    {
1172      char buffer[40];
1173  
1174      if (physid2 != 0)
1175        snprintf(buffer, sizeof(buffer), "%x.%x", physid1, physid2);
1176      else
1177        snprintf(buffer, sizeof(buffer), "%x", physid1);
1178      This->physid = string(buffer);
1179    }
1180  }
1181  
1182  
1183  void hwNode::setPhysId(unsigned physid1,
1184  unsigned physid2,
1185  unsigned physid3)
1186  {
1187    if (This)
1188    {
1189      char buffer[40];
1190  
1191      snprintf(buffer, sizeof(buffer), "%x.%x.%x", physid1, physid2, physid3);
1192      This->physid = string(buffer);
1193    }
1194  }
1195  
1196  
1197  void hwNode::setPhysId(const string & physid)
1198  {
1199    if (This)
1200    {
1201      This->physid = strip(physid);
1202  
1203      while ((This->physid.length() > 1) && (This->physid[0] == '0'))
1204        This->physid.erase(0, 1);
1205    }
1206  }
1207  
1208  
1209  void hwNode::assignPhysIds()
1210  {
1211    if (!This)
1212      return;
1213  
1214    for (unsigned int i = 0; i < This->children.size(); i++)
1215    {
1216      long curid = 0;
1217  
1218      if (This->children[i].getClass() == hw::bridge)
1219        curid = 0x100;
1220  
1221      if (This->children[i].getPhysId() == "")
1222      {
1223        while (getChildByPhysId(curid))
1224          curid++;
1225  
1226        This->children[i].setPhysId(curid);
1227      }
1228  
1229      This->children[i].assignPhysIds();
1230    }
1231  }
1232  
1233  
1234  void hwNode::fixInconsistencies()
1235  {
1236    if (!This)
1237      return;
1238  
1239    if (getCapacity() < getSize())
1240      setCapacity(0);
1241  
1242    guessProduct(*this);
1243    guessVendor(*this);
1244  
1245    if(getLogicalName() != "")
1246      claim();
1247  
1248    for (unsigned int i = 0; i < This->children.size(); i++)
1249      This->children[i].fixInconsistencies();
1250  }
1251  
1252  
1253  void hwNode::merge(const hwNode & node)
1254  {
1255    if (!This)
1256      return;
1257    if (!node.This)
1258      return;
1259  
1260    if (This->deviceclass == hw::generic)
1261      This->deviceclass = node.getClass();
1262    if (This->vendor == "")
1263      This->vendor = node.getVendor();
1264    if (This->product == "")
1265      This->product = node.getProduct();
1266    if (This->version == "")
1267      This->version = node.getVersion();
1268    if (This->serial == "")
1269      This->serial = node.getSerial();
1270    if (This->start == 0)
1271      This->start = node.getStart();
1272    if (This->size == 0)
1273      This->size = node.getSize();
1274    if (This->capacity == 0)
1275      This->capacity = node.getCapacity();
1276    if (This->clock == 0)
1277      This->clock = node.getClock();
1278    if (This->width == 0)
1279      This->width = node.getWidth();
1280    if (node.enabled())
1281      enable();
1282    else
1283      disable();
1284    if (node.claimed())
1285      claim();
1286    if (This->handle == "")
1287      This->handle = node.getHandle();
1288    if (This->description == "")
1289      This->description = node.getDescription();
1290    for (unsigned int i = 0; i < node.This->logicalnames.size(); i++)
1291      setLogicalName(node.This->logicalnames[i]);
1292    if (This->businfo == "")
1293      This->businfo = node.getBusInfo();
1294    if (This->physid == "")
1295      This->physid = node.getPhysId();
1296  
1297    for (unsigned int i = 0; i < node.This->features.size(); i++)
1298      addCapability(node.This->features[i]);
1299    for (map < string, string >::iterator i = node.This->features_descriptions.begin();
1300      i != node.This->features_descriptions.end(); i++)
1301    describeCapability(i->first, i->second);
1302  
1303    for (map < string, string >::iterator i = node.This->config.begin();
1304      i != node.This->config.end(); i++)
1305    setConfig(i->first, i->second);
1306  
1307    for (map < string, value >::iterator i = node.This->hints.begin();
1308      i != node.This->hints.end(); i++)
1309    addHint(i->first, i->second);
1310  }
1311  
1312  
1313  void hwNode::addResource(const resource & r)
1314  {
1315    if (!This)
1316      return;
1317  
1318    This->resources.push_back(r);
1319  }
1320  
1321  
1322  bool hwNode::usesResource(const resource & r) const
1323  {
1324    if (!This)
1325      return false;
1326  
1327    for (size_t i = 0; i < This->resources.size(); i++)
1328      if (r == This->resources[i])
1329        return true;
1330  
1331    return false;
1332  }
1333  
1334  
1335  vector < string > hwNode::getResources(const string & separator) const
1336  {
1337    vector < string > result;
1338  
1339    if (!This)
1340      return result;
1341  
1342    for (vector < resource >::iterator i = This->resources.begin();
1343      i != This->resources.end(); i++)
1344    result.push_back(i->asString(separator));
1345  
1346    return result;
1347  }
1348  
1349  
1350  void hwNode::setWidth(unsigned int width)
1351  {
1352    if(This)
1353      This->width = width;
1354  }
1355  
1356  
1357  unsigned int hwNode::getWidth() const
1358  {
1359    if(This)
1360      return This->width;
1361    else
1362      return 0;
1363  }
1364  
1365  
1366  void hwNode::addHint(const string & id, const value & v)
1367  {
1368    if(This)
1369      This->hints[id] = v;
1370  }
1371  
1372  
1373  value hwNode::getHint(const string & id) const
1374  {
1375    if(!This)
1376      return value();
1377  
1378    return This->hints[id];
1379  }
1380  
1381  vector < string > hwNode::getHints() const
1382  {
1383    vector < string > result;
1384  
1385    if (!This)
1386      return result;
1387  
1388    for (map < string, value >::iterator i = This->hints.begin();
1389      i != This->hints.end(); i++)
1390    result.push_back(i->first);
1391  
1392    return result;
1393  }
1394  
1395  string hwNode::asJSON(unsigned level)
1396  {
1397    vector < string > config;
1398    vector < string > resources;
1399    ostringstream out;
1400  
1401    if(!This) return "";
1402  
1403    config = getConfigKeys();
1404    resources = getResources("\" value=\"");
1405  
1406    if (::enabled("output:list") && level == 0)
1407    {
1408      out << "[" << endl;
1409    }
1410  
1411    if(visible(getClassName()))
1412    {
1413      out << spaces(2*level) << "{" << endl;
1414      out << spaces(2*level+2) << "\"id\" : \"" << getId() << "\"," << endl;
1415      out << spaces(2*level+2) << "\"class\" : \"" << getClassName() << "\"";
1416  
1417      if (disabled())
1418        out << "," << endl << spaces(2*level+2) << "\"disabled\" : true";
1419      if (claimed())
1420        out << "," << endl << spaces(2*level+2) << "\"claimed\" : true";
1421  
1422      if(getHandle() != "")
1423        out << "," << endl << spaces(2*level+2) << "\"handle\" : \"" << getHandle() << "\"";
1424  
1425      if (getDescription() != "")
1426      {
1427        out << "," << endl;
1428        out << spaces(2*level+2);
1429        out << "\"description\" : \"";
1430        out << escapeJSON(getDescription());
1431        out << "\"";
1432      }
1433  
1434      if (getProduct() != "")
1435      {
1436        out << "," << endl;
1437        out << spaces(2*level+2);
1438        out << "\"product\" : \"";
1439        out << escapeJSON(getProduct());
1440        out << "\"";
1441      }
1442  
1443      if (getVendor() != "")
1444      {
1445        out << "," << endl;
1446        out << spaces(2*level+2);
1447        out << "\"vendor\" : \"";
1448        out << escapeJSON(getVendor());
1449        out << "\"";
1450      }
1451  
1452      if (getPhysId() != "")
1453      {
1454        out << "," << endl;
1455        out << spaces(2*level+2);
1456        out << "\"physid\" : \"";
1457        out << getPhysId();
1458        out << "\"";
1459      }
1460  
1461      if (getBusInfo() != "")
1462      {
1463        out << "," << endl;
1464        out << spaces(2*level+2);
1465        out << "\"businfo\" : \"";
1466        out << escapeJSON(getBusInfo());
1467        out << "\"";
1468      }
1469  
1470      if (getLogicalName() != "")
1471      {
1472        vector<string> logicalnames = getLogicalNames();
1473  
1474        out << "," << endl;
1475        out << spaces(2*level+2);
1476        out << "\"logicalname\" : ";
1477        if(logicalnames.size() > 1)
1478        {
1479          out << "[";
1480          for(unsigned int i = 0; i<logicalnames.size(); i++)
1481          {
1482            if(i) out << ", ";
1483            out << "\"" << logicalnames[i] << "\"";
1484          }
1485          out << "]";
1486        }
1487        else
1488          out << "\"" << escapeJSON(getLogicalName()) << "\"";
1489      }
1490  
1491      if (getDev() != "")
1492      {
1493        out << "," << endl;
1494        out << spaces(2*level+2);
1495        out << "\"dev\" : \"";
1496        out << escapeJSON(getDev());
1497        out << "\"";
1498      }
1499  
1500      if (getVersion() != "")
1501      {
1502        out << "," << endl;
1503        out << spaces(2*level+2);
1504        out << "\"version\" : \"";
1505        out << escapeJSON(getVersion());
1506        out << "\"";
1507      }
1508  
1509      if (getDate() != "")
1510      {
1511        out << "," << endl;
1512        out << spaces(2*level+2);
1513        out << "\"date\" : \"";
1514        out << escapeJSON(getDate());
1515        out << "\"";
1516      }
1517  
1518      if (getSerial() != "")
1519      {
1520        out << "," << endl;
1521        out << spaces(2*level+2);
1522        out << "\"serial\" : \"";
1523        out << (::enabled("output:sanitize")?REMOVED:escapeJSON(getSerial()));
1524        out << "\"";
1525      }
1526  
1527      if (getSlot() != "")
1528      {
1529        out << "," << endl;
1530        out << spaces(2*level+2);
1531        out << "\"slot\" : \"";
1532        out << escapeJSON(getSlot());
1533        out << "\"";
1534      }
1535  
1536      if ((getSize() > 0) || (getCapacity() > 0))
1537        switch (getClass())
1538        {
1539          case hw::memory:
1540          case hw::address:
1541          case hw::storage:
1542          case hw::disk:
1543          case hw::display:
1544            out << "," << endl << spaces(2*level+2) << "\"units\" : \"bytes\"";
1545            break;
1546  
1547          case hw::processor:
1548          case hw::bus:
1549          case hw::system:
1550            out << "," << endl << spaces(2*level+2) << "\"units\" : \"Hz\"";
1551            break;
1552  
1553          case hw::power:
1554            out << "," << endl << spaces(2*level+2) << "\"units\" : \"mWh\"";
1555            break;
1556  
1557          case hw::network:
1558            out << "," << endl << spaces(2*level+2) << "\"units\" : \"bit/s\"";
1559            break;
1560  
1561          default:
1562            break;
1563        }
1564  
1565      if (getSize() > 0)
1566      {
1567        out << "," << endl;
1568        out << spaces(2*level+2);
1569        out << "\"size\" : ";
1570        out << getSize();
1571      }
1572  
1573      if (getCapacity() > 0)
1574      {
1575        out << "," << endl;
1576        out << spaces(2*level+2);
1577        out << "\"capacity\" : ";
1578        out << getCapacity();
1579      }
1580  
1581      if (getWidth() > 0)
1582      {
1583        out << "," << endl;
1584        out << spaces(2*level+2);
1585        out << "\"width\" : ";
1586        out << getWidth();
1587      }
1588  
1589      if (getClock() > 0)
1590      {
1591        out << "," << endl;
1592        out << spaces(2*level+2);
1593        out << "\"clock\" : ";
1594        out << getClock();
1595      }
1596  
1597      if (config.size() > 0)
1598      {
1599        out << "," << endl;
1600        out << spaces(2*level+2);
1601        out << "\"configuration\" : {" << endl;
1602        for (unsigned int j = 0; j < config.size(); j++)
1603        {
1604          if(j) out << "," << endl;
1605          out << spaces(2*level+4);
1606          out << "\"" << escapeJSON(config[j]) << "\" : \"" << escapeJSON(getConfig(config[j])) << "\"";
1607        }
1608        out << endl << spaces(2*level+2);
1609        out << "}";
1610      }
1611      config.clear();
1612  
1613      splitlines(getCapabilities(), config, ' ');
1614      if (config.size() > 0)
1615      {
1616        out << "," << endl;
1617        out << spaces(2*level+2);
1618        out << "\"capabilities\" : {" << endl;
1619        for (unsigned int j = 0; j < config.size(); j++)
1620        {
1621          if(j) out << "," << endl;
1622          out << spaces(2*level+4);
1623          out << "\"" << escapeJSON(config[j]) << "\" : ";
1624          if (getCapabilityDescription(config[j]) == "")
1625          {
1626            out << "true";
1627          }
1628          else
1629          {
1630            out << "\"";
1631            out << escapeJSON(getCapabilityDescription(config[j]));
1632            out << "\"";
1633          }
1634        }
1635        out << endl << spaces(2*level+2);
1636        out << "}";
1637      }
1638      config.clear();
1639  
1640      if (0 && resources.size() > 0)
1641      {
1642        out << spaces(2*level+1);
1643        out << "<resources>" << endl;
1644        for (unsigned int j = 0; j < resources.size(); j++)
1645        {
1646          out << spaces(2*level+2);
1647          out << "<resource type=\"" << escapeJSON(resources[j]) << "\" />";
1648          out << endl;
1649        }
1650        out << spaces(2*level+1);
1651        out << "</resources>" << endl;
1652      }
1653      resources.clear();
1654    }
1655  
1656    if(!::enabled("output:list") && countChildren()>0)
1657    {
1658      out << "," << endl;
1659      out << spaces(2*level+2);
1660      out << "\"children\" : [";
1661      for (unsigned int i = 0; i < countChildren(); i++)
1662      {
1663        out << getChild(i)->asJSON(visible(getClassName()) ? level + 2 : 1);
1664        if (visible(getChild(i)->getClassName()) && i<countChildren()-1)
1665        {
1666          out << "," << endl;
1667        }
1668      }
1669      out << "]";
1670    }
1671  
1672    if(visible(getClassName()))
1673    {
1674      out << endl << spaces(2*level);
1675      out << "}";
1676    }
1677  
1678    if(::enabled("output:list") && countChildren()>0)
1679    {
1680      bool needcomma = visible(getClassName());
1681      for (unsigned int i = 0; i < countChildren(); i++)
1682        {
1683          string json = getChild(i)->asJSON(visible(getClassName()) ? level + 2 : 1);
1684  
1685          if(needcomma && strip(json)!="")
1686            out << "," << endl;
1687          out << getChild(i)->asJSON(visible(getClassName()) ? level + 2 : 1);
1688          needcomma |= strip(json)!="";
1689        }
1690    }
1691  
1692    if (::enabled("output:list") && level == 0)
1693    {
1694      out << endl << "]" << endl;
1695    }
1696  
1697    return out.str();
1698  }
1699  
1700  string hwNode::asXML(unsigned level)
1701  {
1702    vector < string > config;
1703    vector < string > resources;
1704    ostringstream out;
1705  
1706    if(!This) return "";
1707  
1708    config = getConfigKeys();
1709    resources = getResources("\" value=\"");
1710  
1711    if (level == 0)
1712    {
1713      struct utsname un;
1714  
1715      out << "<?xml version=\"1.0\" standalone=\"yes\" ?>" << endl;
1716      out << _("<!-- generated by lshw-") << getpackageversion() << " -->" <<
1717    #if defined(__GNUC__) && defined(__VERSION__)
1718        endl << "<!-- GCC " << escapecomment(__VERSION__) << " -->" <<
1719    #endif
1720        endl;
1721  
1722      if(uname(&un) == 0)
1723        out << "<!-- " << escapecomment(un.sysname) << " " << escapecomment(un.release) << " " << escapecomment(un.version) << " " << escapecomment(un.machine) << " -->" << endl;
1724    #if defined(__GLIBC__) && defined(_CS_GNU_LIBC_VERSION)
1725      char version[PATH_MAX];
1726  
1727        if(confstr(_CS_GNU_LIBC_VERSION, version, sizeof(version))>0)
1728          out << "<!-- GNU libc " << __GLIBC__ << " (" << escapecomment(version) << ") -->" << endl;
1729    #endif
1730      if (geteuid() != 0)
1731        out << _("<!-- WARNING: not running as root -->") << endl;
1732  
1733      if(::enabled("output:list"))
1734        out << "<list>" << endl;
1735  
1736    }
1737  
1738    if(visible(getClassName()))
1739    {
1740      out << spaces(2*level);
1741      out << "<node id=\"" << getId() << "\"";
1742      if (disabled())
1743        out << " disabled=\"true\"";
1744      if (claimed())
1745        out << " claimed=\"true\"";
1746  
1747      out << " class=\"" << getClassName() << "\"";
1748      if(getHandle()!="") out << " handle=\"" << escape(getHandle()) << "\"";
1749      if(getModalias()!="") out << " modalias=\"" << escape(getModalias()) << "\"";
1750      out << ">" << endl;
1751  
1752      if (getDescription() != "")
1753      {
1754        out << spaces(2*level+1);
1755        out << "<description>";
1756        out << escape(getDescription());
1757        out << "</description>";
1758        out << endl;
1759      }
1760  
1761      if (getProduct() != "")
1762      {
1763        out << spaces(2*level+1);
1764        out << "<product>";
1765        out << escape(getProduct());
1766        out << "</product>";
1767        out << endl;
1768      }
1769  
1770      if (getVendor() != "")
1771      {
1772        out << spaces(2*level+1);
1773        out << "<vendor>";
1774        out << escape(getVendor());
1775        out << "</vendor>";
1776        out << endl;
1777      }
1778  
1779      if (getPhysId() != "")
1780      {
1781        out << spaces(2*level+1);
1782        out << "<physid>";
1783        out << getPhysId();
1784        out << "</physid>";
1785        out << endl;
1786      }
1787  
1788      if (getSubProduct() != "")
1789      {
1790        out << spaces(2*level+1);
1791        out << "<subproduct>";
1792        out << escape(getSubProduct());
1793        out << "</subproduct>";
1794        out << endl;
1795      }
1796  
1797      if (getSubVendor() != "")
1798      {
1799        out << spaces(2*level+1);
1800        out << "<subvendor>";
1801        out << escape(getSubVendor());
1802        out << "</subvendor>";
1803        out << endl;
1804      }
1805  
1806      if (getBusInfo() != "")
1807      {
1808        out << spaces(2*level+1);
1809        out << "<businfo>";
1810        out << escape(getBusInfo());
1811        out << "</businfo>";
1812        out << endl;
1813      }
1814  
1815      if (getLogicalName() != "")
1816      {
1817        vector<string> logicalnames = getLogicalNames();
1818  
1819        for(unsigned int i = 0; i<logicalnames.size(); i++)
1820        {
1821          out << spaces(2*level+1);
1822          out << "<logicalname>";
1823          out << logicalnames[i];
1824          out << "</logicalname>";
1825          out << endl;
1826        }
1827      }
1828  
1829      if (getDev() != "")
1830      {
1831        out << spaces(2*level+1);
1832        out << "<dev>";
1833        out << escape(getDev());
1834        out << "</dev>";
1835        out << endl;
1836      }
1837  
1838      if (getVersion() != "")
1839      {
1840        out << spaces(2*level+1);
1841        out << "<version>";
1842        out << escape(getVersion());
1843        out << "</version>";
1844        out << endl;
1845      }
1846  
1847      if (getDate() != "")
1848      {
1849        out << spaces(2*level+1);
1850        out << "<date>";
1851        out << escape(getDate());
1852        out << "</date>";
1853        out << endl;
1854      }
1855  
1856      if (getSerial() != "")
1857      {
1858        out << spaces(2*level+1);
1859        out << "<serial>";
1860        out << (::enabled("output:sanitize")?REMOVED:escape(getSerial()));
1861        out << "</serial>";
1862        out << endl;
1863      }
1864  
1865      if (getSlot() != "")
1866      {
1867        out << spaces(2*level+1);
1868        out << "<slot>";
1869        out << escape(getSlot());
1870        out << "</slot>";
1871        out << endl;
1872      }
1873  
1874      if (getSize() > 0)
1875      {
1876        out << spaces(2*level+1);
1877        out << "<size";
1878        switch (getClass())
1879        {
1880          case hw::memory:
1881          case hw::address:
1882          case hw::storage:
1883          case hw::disk:
1884          case hw::volume:
1885          case hw::display:
1886            out << " units=\"bytes\"";
1887            break;
1888  
1889          case hw::processor:
1890          case hw::bus:
1891          case hw::system:
1892            out << " units=\"Hz\"";
1893            break;
1894  
1895          case hw::network:
1896            out << " units=\"bit/s\"";
1897            break;
1898  
1899          case hw::power:
1900            out << " units=\"mWh\"";
1901            break;
1902  
1903          default:
1904            out << "";
1905        }
1906        out << ">";
1907        out << getSize();
1908        out << "</size>";
1909        out << endl;
1910      }
1911  
1912      if (getCapacity() > 0)
1913      {
1914        out << spaces(2*level+1);
1915        out << "<capacity";
1916        switch (getClass())
1917        {
1918          case hw::memory:
1919          case hw::address:
1920          case hw::storage:
1921          case hw::disk:
1922            out << " units=\"bytes\"";
1923            break;
1924  
1925          case hw::processor:
1926          case hw::bus:
1927          case hw::system:
1928            out << " units=\"Hz\"";
1929            break;
1930  
1931          case hw::power:
1932            out << " units=\"mWh\"";
1933            break;
1934  
1935          default:
1936            out << "";
1937        }
1938        out << ">";
1939        out << getCapacity();
1940        out << "</capacity>";
1941        out << endl;
1942      }
1943  
1944      if (getWidth() > 0)
1945      {
1946        out << spaces(2*level+1);
1947        out << "<width units=\"bits\">";
1948        out << getWidth();
1949        out << "</width>";
1950        out << endl;
1951      }
1952  
1953      if (getClock() > 0)
1954      {
1955        out << spaces(2*level+1);
1956        out << "<clock units=\"Hz\">";
1957        out << getClock();
1958        out << "</clock>";
1959        out << endl;
1960      }
1961  
1962      if (config.size() > 0)
1963      {
1964        out << spaces(2*level+1);
1965        out << "<configuration>" << endl;
1966        for (unsigned int j = 0; j < config.size(); j++)
1967        {
1968          out << spaces(2*level+2);
1969          out << "<setting id=\"" << escape(config[j]) << "\" value=\"" << escape(getConfig(config[j])) << "\" />";
1970          out << endl;
1971        }
1972        out << spaces(2*level+1);
1973        out << "</configuration>" << endl;
1974      }
1975      config.clear();
1976  
1977      splitlines(getCapabilities(), config, ' ');
1978      if (config.size() > 0)
1979      {
1980        out << spaces(2*level+1);
1981        out << "<capabilities>" << endl;
1982        for (unsigned int j = 0; j < config.size(); j++)
1983        {
1984          out << spaces(2*level+2);
1985          out << "<capability id=\"" << escape(config[j]);
1986          if (getCapabilityDescription(config[j]) == "")
1987          {
1988            out << "\" />";
1989          }
1990          else
1991          {
1992            out << "\" >";
1993            out << escape(getCapabilityDescription(config[j]));
1994            out << "</capability>";
1995          }
1996          out << endl;
1997        }
1998        out << spaces(2*level+1);
1999        out << "</capabilities>" << endl;
2000      }
2001      config.clear();
2002  
2003      if (resources.size() > 0)
2004      {
2005        out << spaces(2*level+1);
2006        out << "<resources>" << endl;
2007        for (unsigned int j = 0; j < resources.size(); j++)
2008        {
2009          out << spaces(2*level+2);
2010          out << "<resource type=\"" << resources[j] << "\" />";
2011          out << endl;
2012        }
2013        out << spaces(2*level+1);
2014        out << "</resources>" << endl;
2015      }
2016      resources.clear();
2017  
2018      vector < string > hints = getHints();
2019      if (hints.size() > 0) {
2020        out << spaces(2*level+1);
2021        out << "<hints>" << endl;
2022        for(unsigned int i=0; i<hints.size(); i++) {
2023          out << spaces(2*level+2);
2024          out << "<hint name=\"" << hints[i] << "\" " << "value=\"" << getHint(hints[i]).asString() << "\" />";
2025          out << endl;
2026        }
2027        out << spaces(2*level+1);
2028        out << "</hints>" << endl;
2029      }
2030    }
2031  
2032    for (unsigned int i = 0; i < countChildren(); i++)
2033    {
2034      out << getChild(i)->asXML(visible(getClassName()) ? level + 1 : 1);
2035    }
2036  
2037    if(visible(getClassName()))
2038    {
2039      out << spaces(2*level);
2040      out << "</node>" << endl;
2041    }
2042  
2043    if((level==0) && ::enabled("output:list"))
2044      out << "</list>" << endl;
2045  
2046  
2047    return out.str();
2048  }
2049  
2050  string hwNode::asString()
2051  {
2052    string summary = "";
2053    if(!This)
2054      return "";
2055  
2056    if(getClass() != hw::memory)
2057      summary = getProduct();        // memory devices tend to have obscure product names
2058    if (summary == "")
2059      summary = getDescription();
2060  
2061    if((getClass() == hw::memory) || (getClass() == hw::disk) || (getClass() == hw::storage) || (getClass() == hw::volume))
2062    {
2063      unsigned long long size = 0;
2064      if(getClass() != hw::memory)
2065      {
2066        if(getCapacity())
2067          size = getCapacity();
2068        else
2069        {
2070          if(getSize())
2071            size = getSize();
2072        }
2073      }
2074      else
2075      {
2076        if(getSize())
2077          size = getSize();
2078      }
2079      if(size)
2080        summary = (getClass()==hw::disk?(decimalkilos(size)+"B"):kilobytes(size)) +" "+ summary;
2081    }
2082  
2083    return summary;
2084  }
2085  
2086  struct hw::resource_i
2087  {
2088    hw::hwResourceType type;
2089  
2090    unsigned int ui1;
2091    unsigned long ul1, ul2;
2092    unsigned long long ull1, ull2;
2093    bool b;
2094  
2095    int refcount;
2096  };
2097  
2098  resource::resource()
2099  {
2100    This = new struct resource_i;
2101  
2102    if (This)
2103    {
2104      memset(This, 0, sizeof(*This));
2105      This->type = none;
2106      This->refcount = 1;
2107    }
2108  }
2109  
2110  
2111  resource::~resource()
2112  {
2113    if (This)
2114    {
2115      This->refcount--;
2116  
2117      if (This->refcount <= 0)
2118      {
2119        delete This;
2120        This = NULL;
2121      }
2122    }
2123  }
2124  
2125  
2126  resource::resource(const resource & r)
2127  {
2128    This = r.This;
2129  
2130    if (This)
2131      This->refcount++;
2132  }
2133  
2134  
2135  resource & resource::operator = (const resource & r)
2136  {
2137    if (this == &r)
2138      return *this;                                 // ignore self-affectation
2139  
2140    if (This == r.This)
2141      return *this;                                 // both objects reference the same data
2142  
2143    if (This)
2144    {
2145      This->refcount--;
2146  
2147      if (This->refcount <= 0)
2148      {
2149        delete This;
2150        This = NULL;
2151      }
2152    }
2153  
2154    This = r.This;
2155    if (This)
2156      This->refcount++;
2157  
2158    return *this;
2159  }
2160  
2161  
2162  resource resource::iomem(unsigned long long start,
2163  unsigned long long end)
2164  {
2165    resource r;
2166  
2167    if (!r.This)
2168      return r;
2169  
2170    r.This->type = hw::iomem;
2171    r.This->ull1 = start;
2172    r.This->ull2 = end;
2173  
2174    return r;
2175  }
2176  
2177  
2178  resource resource::ioport(unsigned long start,
2179  unsigned long end)
2180  {
2181    resource r;
2182  
2183    if (!r.This)
2184      return r;
2185  
2186    r.This->type = hw::ioport;
2187    r.This->ul1 = start;
2188    r.This->ul2 = end;
2189  
2190    return r;
2191  }
2192  
2193  
2194  resource resource::mem(unsigned long long start,
2195  unsigned long long end, bool prefetchable)
2196  {
2197    resource r;
2198  
2199    if (!r.This)
2200      return r;
2201  
2202    r.This->type = hw::mem;
2203    r.This->ull1 = start;
2204    r.This->ull2 = end;
2205    r.This->b = prefetchable;
2206  
2207    return r;
2208  }
2209  
2210  
2211  resource resource::irq(unsigned int value)
2212  {
2213    resource r;
2214  
2215    if (!r.This)
2216      return r;
2217  
2218    r.This->type = hw::irq;
2219    r.This->ui1 = value;
2220  
2221    return r;
2222  }
2223  
2224  
2225  resource resource::dma(unsigned int value)
2226  {
2227    resource r;
2228  
2229    if (!r.This)
2230      return r;
2231  
2232    r.This->type = hw::dma;
2233    r.This->ui1 = value;
2234  
2235    return r;
2236  }
2237  
2238  
2239  string resource::asString(const string & separator) const
2240  {
2241    char buffer[80];
2242    string result = "";
2243  
2244    if (!This)
2245      return result;
2246  
2247    strncpy(buffer, "", sizeof(buffer));
2248  
2249    switch (This->type)
2250    {
2251      case hw::none:
2252        result = _("(none)");
2253        break;
2254      case hw::dma:
2255        result = _("dma") + separator;
2256        snprintf(buffer, sizeof(buffer), "%d", This->ui1);
2257        break;
2258      case hw::irq:
2259        result = _("irq") + separator;
2260        snprintf(buffer, sizeof(buffer), "%d", This->ui1);
2261        break;
2262      case hw::iomem:
2263        result = _("iomemory") + separator;
2264        snprintf(buffer, sizeof(buffer), "%llx-%llx", This->ull1, This->ull2);
2265        break;
2266      case hw::mem:
2267        result = _("memory") + separator;
2268        snprintf(buffer, sizeof(buffer), "%llx-%llx", This->ull1, This->ull2);
2269        if(This->b) strcat(buffer, _("(prefetchable)"));
2270        break;
2271      case hw::ioport:
2272        result = _("ioport") + separator;
2273        if(This->ul1 == This->ul2)
2274          snprintf(buffer, sizeof(buffer), "%lx", This->ul1);
2275        else
2276          snprintf(buffer, sizeof(buffer), _("%lx(size=%ld)"), This->ul1, This->ul2 - This->ul1 + 1);
2277        break;
2278      default:
2279        result = _("(unknown)");
2280    }
2281  
2282    return result + string(buffer);
2283  }
2284  
2285  
2286  bool resource::operator == (const resource & r)
2287  const
2288  {
2289    if (This == r.This)
2290      return true;
2291  
2292    if (!This || !r.This)
2293      return false;
2294  
2295    if (This->type != r.This->type)
2296      return false;
2297  
2298    switch (This->type)
2299    {
2300      case hw::dma:
2301      case hw::irq:
2302        return This->ui1 == r.This->ui1;
2303        break;
2304  
2305      case hw::iomem:
2306      case hw::mem:
2307        return ((This->ull1 >= r.This->ull1)
2308        && (This->ull2 <= r.This->ull2)) || ((r.This->ull1 >= This->ull1)
2309        && (r.This->ull2 <= This->ull2));
2310      break;
2311  
2312      case hw::ioport:
2313        return ((This->ul1 >= r.This->ul1)
2314        && (This->ul1 <= r.This->ul2)) || ((r.This->ul1 >= This->ul1)
2315        && (r.This->ul1 <= This->ul2));
2316      break;
2317  
2318      default:return false;
2319    }
2320  }
2321  
2322  
2323  struct hw::value_i
2324  {
2325    hw::hwValueType type;
2326  
2327    long long ll;
2328    string s;
2329    bool b;
2330  
2331    int refcount;
2332  };
2333  
2334  value::value()
2335  {
2336    This = new hw::value_i;
2337  
2338    if(This)
2339    {
2340      This->type = nil;
2341      This->refcount = 1;
2342    }
2343  }
2344  
2345  
2346  value::~value()
2347  {
2348    if(This)
2349    {
2350      This->refcount--;
2351      if(This->refcount<=0)
2352        delete This;
2353      This = NULL;
2354    }
2355  }
2356  
2357  
2358  value::value(long long ll)
2359  {
2360    This = new hw::value_i;
2361  
2362    if(This)
2363    {
2364      This->type = integer;
2365      This->ll = ll;
2366      This->refcount = 1;
2367    }
2368  }
2369  
2370  
2371  value::value(const string & s)
2372  {
2373    This = new hw::value_i;
2374  
2375    if(This)
2376    {
2377      This->type = text;
2378      This->s = s;
2379      This->refcount = 1;
2380    }
2381  }
2382  
2383  
2384  value::value(const value & v)
2385  {
2386    This = v.This;
2387  
2388    if(This)
2389    {
2390      This->refcount++;
2391    }
2392  }
2393  
2394  
2395  value & value::operator=(const value & v)
2396  {
2397    if(v.This == This) return *this;
2398  
2399    if(This)
2400    {
2401      This->refcount--;
2402      if(This->refcount<=0)
2403        delete This;
2404    }
2405  
2406    This = v.This;
2407    if(This)
2408      This->refcount++;
2409  
2410    return *this;
2411  }
2412  
2413  
2414  bool value::operator==(const value & v) const
2415  {
2416    if(v.This == This) return true;
2417  
2418    if(!v.This || !This) return false;
2419  
2420    if(v.This->type != This->type) return false;
2421  
2422    switch(This->type)
2423    {
2424      case hw::integer:
2425        return This->ll == v.This->ll;
2426      case hw::text:
2427        return This->s == v.This->s;
2428      case hw::boolean:
2429        return This->b == v.This->b;
2430      case hw::nil:
2431        return true;
2432    };
2433  
2434    return false;
2435  }
2436  
2437  
2438  string value::asString() const
2439  {
2440    if(!This) return "";
2441  
2442    switch(This->type)
2443    {
2444      case hw::integer:
2445        return "0x"+tohex(This->ll);
2446      case hw::text:
2447        return This->s;
2448      case hw::boolean:
2449        return This->b?_("true"):_("false");
2450      case hw::nil:
2451        return _("(nil)");
2452    };
2453  
2454    return "";
2455  }
2456  
2457  
2458  long long value::asInteger() const
2459  {
2460    if(!This) return 0;
2461  
2462    switch(This->type)
2463    {
2464      case hw::text:
2465        return stoll(This->s, NULL, 0);
2466      case hw::integer:
2467        return This->ll;
2468      case hw::boolean:
2469        return This->b?1:0;
2470      case hw::nil:
2471        return 0;
2472    };
2473  
2474    return 0;
2475  }
2476  
2477  
2478  bool value::defined() const
2479  {
2480    if(!This) return false;
2481    if(This->type==nil) return false;
2482  
2483    return true;
2484  }
2485  
2486  bool hwNode::dump(const string & filename, bool recurse)
2487  {
2488  #ifdef SQLITE
2489    try {
2490      sqlite::database db(filename);
2491  
2492      db.execute("BEGIN TRANSACTION");
2493      ::dump(*this, db, "", recurse);
2494      db.execute("COMMIT");
2495    }
2496    catch(exception & e)
2497    {
2498      return false;
2499    }
2500  #else
2501    return false;
2502  #endif
2503  
2504    return true;
2505  }