Back to index

lshw  02.16
hw.cc
Go to the documentation of this file.
00001 #define _XOPEN_SOURCE
00002 #include "hw.h"
00003 #include "osutils.h"
00004 #include "version.h"
00005 #include "config.h"
00006 #include "options.h"
00007 #include "heuristics.h"
00008 #include "dump.h"
00009 #include "db.h"
00010 #include <cstring>
00011 #include <vector>
00012 #include <map>
00013 #include <sstream>
00014 #include <stdlib.h>
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include <ctype.h>
00018 #include <limits.h>
00019 #include <unistd.h>
00020 #include <limits.h>
00021 #include <sys/utsname.h>
00022 
00023 using namespace hw;
00024 
00025 __ID("@(#) $Id: hw.cc 2433 2012-01-10 22:01:30Z lyonel $");
00026 
00027 struct hwNode_i
00028 {
00029   hwClass deviceclass;
00030   string id, vendor, product, version, date, serial, slot, handle, description,
00031     businfo, physid, dev;
00032   bool enabled;
00033   bool claimed;
00034   unsigned long long start;
00035   unsigned long long size;
00036   unsigned long long capacity;
00037   unsigned long long clock;
00038   unsigned int width;
00039   vector < hwNode > children;
00040   vector < string > attracted;
00041   vector < string > features;
00042   vector < string > logicalnames;
00043   map < string, string > features_descriptions;
00044   vector < resource > resources;
00045   map < string, string > config;
00046   map < string, value > hints;
00047 };
00048 
00049 string hw::strip(const string & s)
00050 {
00051   string result = s;
00052   size_t i = result.find('\0');
00053 
00054   if(i != string::npos)
00055     result = result.substr(0, i);
00056 
00057   while ((result.length() > 0) && ((uint8_t)result[0] <= ' '))
00058     result.erase(0, 1);
00059   while ((result.length() > 0) && ((uint8_t)result[result.length() - 1] <= ' '))
00060     result.erase(result.length() - 1);
00061 
00062   for (i = 0; i < result.length(); i++)
00063     if ((uint8_t)result[i] < ' ')
00064     {
00065       result.erase(i, 1);
00066       i--;
00067     }
00068 
00069   result = utf8_sanitize(result);
00070 
00071   return result;
00072 }
00073 
00074 string hw::asString(long n)
00075 {
00076   char buffer[256];
00077 
00078   snprintf(buffer, sizeof(buffer), "%ld", n);
00079   return string(buffer);
00080 }
00081 
00082 static string cleanupId(const string & id)
00083 {
00084   string result = strip(id);
00085 
00086   for (unsigned int i = 0; i < result.length(); i++)
00087   {
00088     result[i] = tolower(result[i]);
00089     if (!strchr("0123456789abcdefghijklmnopqrstuvwxyz_.:-", result[i]))
00090       result[i] = '_';
00091   }
00092 
00093   return result;
00094 }
00095 
00096 
00097 hwNode::hwNode(const string & id,
00098 hwClass c,
00099 const string & vendor,
00100 const string & product, const string & version)
00101 {
00102   This = NULL;
00103   This = new hwNode_i;
00104 
00105   if (!This)
00106     return;
00107 
00108   This->deviceclass = c;
00109   This->id = cleanupId(id);
00110   This->vendor = strip(vendor);
00111   This->product = strip(product);
00112   This->version = strip(version);
00113   This->start = 0;
00114   This->size = 0;
00115   This->capacity = 0;
00116   This->clock = 0;
00117   This->width = 0;
00118   This->enabled = true;
00119   This->claimed = false;
00120   This->handle = string("");
00121   This->description = string("");
00122   This->businfo = string("");
00123   This->physid = string("");
00124   This->dev = string("");
00125 }
00126 
00127 
00128 hwNode::hwNode(const hwNode & o)
00129 {
00130   This = NULL;
00131   This = new hwNode_i;
00132 
00133   if (!This)
00134     return;
00135 
00136   if (o.This)
00137     (*This) = (*o.This);
00138 }
00139 
00140 
00141 hwNode::~hwNode()
00142 {
00143   if (This)
00144     delete This;
00145 }
00146 
00147 
00148 hwNode & hwNode::operator = (const hwNode & o)
00149 {
00150   if (this == &o)
00151     return *this;                                 // self-affectation
00152 
00153   if (This)
00154     delete This;
00155   This = NULL;
00156   This = new hwNode_i;
00157 
00158   if (!This)
00159     return *this;
00160 
00161   if (o.This)
00162     (*This) = (*o.This);
00163 
00164   return *this;
00165 }
00166 
00167 
00168 hwClass hwNode::getClass() const
00169 {
00170   if (This)
00171     return This->deviceclass;
00172   else
00173     return hw::generic;
00174 }
00175 
00176 
00177 const char *hwNode::getClassName() const
00178 {
00179   if (This)
00180   {
00181     switch (This->deviceclass)
00182     {
00183       case processor:
00184         return "processor";
00185 
00186       case memory:
00187         return "memory";
00188 
00189       case address:
00190         return "address";
00191 
00192       case storage:
00193         return "storage";
00194 
00195       case disk:
00196         return "disk";
00197 
00198       case tape:
00199         return "tape";
00200 
00201       case hw::system:
00202         return "system";
00203 
00204       case bridge:
00205         return "bridge";
00206 
00207       case bus:
00208         return "bus";
00209 
00210       case network:
00211         return "network";
00212 
00213       case display:
00214         return "display";
00215 
00216       case input:
00217         return "input";
00218 
00219       case printer:
00220         return "printer";
00221 
00222       case multimedia:
00223         return "multimedia";
00224 
00225       case communication:
00226         return "communication";
00227 
00228       case power:
00229         return "power";
00230 
00231       case volume:
00232         return "volume";
00233 
00234       default:
00235         return "generic";
00236     }
00237   }
00238   else
00239     return "generic";
00240 }
00241 
00242 
00243 void hwNode::setClass(hwClass c)
00244 {
00245   if (!This)
00246     return;
00247 
00248   This->deviceclass = c;
00249 }
00250 
00251 
00252 bool hwNode::enabled() const
00253 {
00254   if (!This)
00255     return false;
00256 
00257   return (This->enabled);
00258 }
00259 
00260 
00261 bool hwNode::disabled() const
00262 {
00263   if (!This)
00264     return true;
00265 
00266   return !(This->enabled);
00267 }
00268 
00269 
00270 void hwNode::enable()
00271 {
00272   if (!This)
00273     return;
00274 
00275   This->enabled = true;
00276 }
00277 
00278 
00279 void hwNode::disable()
00280 {
00281   if (!This)
00282     return;
00283 
00284   This->enabled = false;
00285 }
00286 
00287 
00288 bool hwNode::claimed() const
00289 {
00290   if (!This)
00291     return false;
00292 
00293   if (This->claimed)
00294     return true;
00295 
00296   for (unsigned int i = 0; i < This->children.size(); i++)
00297     if (This->children[i].claimed())
00298   {
00299     This->claimed = true;
00300     return true;
00301   }
00302 
00303   return false;
00304 }
00305 
00306 
00307 void hwNode::claim(bool claimchildren)
00308 {
00309   if (!This)
00310     return;
00311 
00312   This->claimed = true;
00313 
00314   if (!claimchildren)
00315     return;
00316 
00317   for (unsigned int i = 0; i < This->children.size(); i++)
00318     This->children[i].claim(claimchildren);
00319 }
00320 
00321 
00322 void hwNode::unclaim()
00323 {
00324   if (!This)
00325     return;
00326 
00327   This->claimed = false;
00328 }
00329 
00330 
00331 string hwNode::getId() const
00332 {
00333   if (This)
00334     return This->id;
00335   else
00336     return "";
00337 }
00338 
00339 
00340 void hwNode::setId(const string & id)
00341 {
00342   if (!This)
00343     return;
00344 
00345   This->id = cleanupId(id);
00346 }
00347 
00348 
00349 void hwNode::setHandle(const string & handle)
00350 {
00351   if (!This)
00352     return;
00353 
00354   This->handle = handle;
00355 }
00356 
00357 
00358 string hwNode::getHandle() const
00359 {
00360   if (This)
00361     return This->handle;
00362   else
00363     return "";
00364 }
00365 
00366 
00367 string hwNode::getDescription() const
00368 {
00369   if (This)
00370     return This->description;
00371   else
00372     return "";
00373 }
00374 
00375 
00376 void hwNode::setDescription(const string & description)
00377 {
00378   if (This)
00379     This->description = strip(description);
00380 }
00381 
00382 
00383 string hwNode::getVendor() const
00384 {
00385   if (This)
00386     return This->vendor;
00387   else
00388     return "";
00389 }
00390 
00391 
00392 void hwNode::setVendor(const string & vendor)
00393 {
00394   if (This)
00395     This->vendor = strip(vendor);
00396 }
00397 
00398 
00399 string hwNode::getProduct() const
00400 {
00401   if (This)
00402     return This->product;
00403   else
00404     return "";
00405 }
00406 
00407 
00408 void hwNode::setProduct(const string & product)
00409 {
00410   if (This)
00411     This->product = strip(product);
00412 }
00413 
00414 
00415 string hwNode::getVersion() const
00416 {
00417   if (This)
00418     return This->version;
00419   else
00420     return "";
00421 }
00422 
00423 
00424 void hwNode::setVersion(const string & version)
00425 {
00426   if (This)
00427     This->version = strip(version);
00428 }
00429 
00430 string hwNode::getDate() const
00431 {
00432   if (This)
00433     return This->date;
00434   else
00435     return "";
00436 }
00437 
00438 
00439 void hwNode::setDate(const string & s)
00440 {
00441   if (This)
00442     This->date = strip(s);
00443 }
00444 
00445 
00446 string hwNode::getSerial() const
00447 {
00448   if (This)
00449     return This->serial;
00450   else
00451     return "";
00452 }
00453 
00454 
00455 void hwNode::setSerial(const string & serial)
00456 {
00457   if(serial == "00000000-0000-0000-0000-000000000000")
00458     return;
00459 
00460   if (This)
00461     This->serial = strip(serial);
00462 }
00463 
00464 
00465 string hwNode::getSlot() const
00466 {
00467   if (This)
00468     return This->slot;
00469   else
00470     return "";
00471 }
00472 
00473 
00474 void hwNode::setSlot(const string & slot)
00475 {
00476   if (This)
00477     This->slot = strip(slot);
00478 }
00479 
00480 
00481 unsigned long long hwNode::getStart() const
00482 {
00483   if (This)
00484     return This->start;
00485   else
00486     return 0;
00487 }
00488 
00489 
00490 void hwNode::setStart(unsigned long long start)
00491 {
00492   if (This)
00493     This->start = start;
00494 }
00495 
00496 
00497 unsigned long long hwNode::getSize() const
00498 {
00499   if (This)
00500     return This->size;
00501   else
00502     return 0;
00503 }
00504 
00505 
00506 void hwNode::setSize(unsigned long long size)
00507 {
00508   if (This)
00509     This->size = size;
00510 }
00511 
00512 
00513 unsigned long long hwNode::getCapacity() const
00514 {
00515   if (This)
00516     return This->capacity;
00517   else
00518     return 0;
00519 }
00520 
00521 
00522 void hwNode::setCapacity(unsigned long long capacity)
00523 {
00524   if (This)
00525     This->capacity = capacity;
00526 }
00527 
00528 
00529 unsigned long long hwNode::getClock() const
00530 {
00531   if (This)
00532     return This->clock;
00533   else
00534     return 0;
00535 }
00536 
00537 
00538 void hwNode::setClock(unsigned long long clock)
00539 {
00540   if (This)
00541     This->clock = clock;
00542 }
00543 
00544 
00545 unsigned int hwNode::countChildren(hw::hwClass c) const
00546 {
00547   unsigned int count = 0;
00548 
00549   if (!This)
00550     return 0;
00551 
00552   if (c == hw::generic)
00553     return This->children.size();
00554 
00555   for (unsigned int i = 0; i < This->children.size(); i++)
00556     if (This->children[i].getClass() == c)
00557       count++;
00558 
00559   return count;
00560 }
00561 
00562 
00563 hwNode *hwNode::getChild(unsigned int i)
00564 {
00565   if (!This)
00566     return NULL;
00567 
00568   if (i >= This->children.size())
00569     return NULL;
00570   else
00571     return &(This->children[i]);
00572 }
00573 
00574 
00575 hwNode *hwNode::getChildByPhysId(const string & physid)
00576 {
00577   if (physid == "" || !This)
00578     return NULL;
00579 
00580   for (unsigned int i = 0; i < This->children.size(); i++)
00581   {
00582     if (This->children[i].getPhysId() == physid)
00583       return &(This->children[i]);
00584   }
00585 
00586   return NULL;
00587 }
00588 
00589 
00590 hwNode *hwNode::getChildByPhysId(long physid)
00591 {
00592   char buffer[20];
00593   if (!This)
00594     return NULL;
00595 
00596   snprintf(buffer, sizeof(buffer), "%lx", physid);
00597 
00598   for (unsigned int i = 0; i < This->children.size(); i++)
00599   {
00600     if (This->children[i].getPhysId() == string(buffer))
00601       return &(This->children[i]);
00602   }
00603 
00604   return NULL;
00605 }
00606 
00607 
00608 hwNode *hwNode::getChild(const string & id)
00609 {
00610   string baseid = id, path = "";
00611   size_t pos = 0;
00612 
00613   if (!This)
00614     return NULL;
00615 
00616   pos = id.find('/');
00617   if (pos != string::npos)
00618   {
00619     baseid = id.substr(0, pos);
00620     if (pos < id.length() - 1)
00621       path = id.substr(pos + 1);
00622   }
00623 
00624   for (unsigned int i = 0; i < This->children.size(); i++)
00625     if (This->children[i].getId() == baseid)
00626   {
00627     if (path == "")
00628       return &(This->children[i]);
00629     else
00630       return This->children[i].getChild(path);
00631   }
00632   return NULL;
00633 }
00634 
00635 
00636 hwNode *hwNode::findChild(bool(*matchfunction) (const hwNode &))
00637 {
00638   if (!This)
00639     return NULL;
00640 
00641   if (matchfunction(*this))
00642     return this;
00643 
00644   for (unsigned int i = 0; i < This->children.size(); i++)
00645   {
00646     hwNode *result = This->children[i].findChild(matchfunction);
00647 
00648     if (result)
00649       return result;
00650   }
00651 
00652   return NULL;
00653 }
00654 
00655 
00656 hwNode *hwNode::findChildByHandle(const string & handle)
00657 {
00658   if (!This)
00659     return NULL;
00660 
00661   if (This->handle == handle)
00662     return this;
00663 
00664   for (unsigned int i = 0; i < This->children.size(); i++)
00665   {
00666     hwNode *result = This->children[i].findChildByHandle(handle);
00667 
00668     if (result)
00669       return result;
00670   }
00671 
00672   return NULL;
00673 }
00674 
00675 
00676 hwNode *hwNode::findChildByLogicalName(const string & name)
00677 {
00678   unsigned int i = 0;
00679 
00680   if (!This)
00681     return NULL;
00682 
00683   for (i = 0; i < This->logicalnames.size(); i++)
00684     if (This->logicalnames[i] == name)
00685       return this;
00686 
00687   for (i = 0; i < This->children.size(); i++)
00688   {
00689     hwNode *result = This->children[i].findChildByLogicalName(name);
00690 
00691     if (result)
00692       return result;
00693   }
00694 
00695   return NULL;
00696 }
00697 
00698 
00699 hwNode *hwNode::findChildByBusInfo(const string & businfo)
00700 {
00701   if (!This)
00702     return NULL;
00703 
00704   if (strip(businfo) == "")
00705     return NULL;
00706 
00707   if (lowercase(strip(This->businfo)) == lowercase(strip(businfo)))
00708     return this;
00709 
00710   for (unsigned int i = 0; i < This->children.size(); i++)
00711   {
00712     hwNode *result = This->children[i].findChildByBusInfo(businfo);
00713 
00714     if (result)
00715       return result;
00716   }
00717 
00718   return NULL;
00719 }
00720 
00721 
00722 hwNode *hwNode::findChildByResource(const hw::resource & r)
00723 {
00724   if (!This)
00725     return NULL;
00726 
00727   if (this->usesResource(r))
00728     return this;
00729 
00730   for (unsigned int i = 0; i < This->children.size(); i++)
00731   {
00732     hwNode *result = This->children[i].findChildByResource(r);
00733 
00734     if (result)
00735       return result;
00736   }
00737 
00738   return NULL;
00739 }
00740 
00741 
00742 static string generateId(const string & radical,
00743 int count)
00744 {
00745   char buffer[10];
00746 
00747   snprintf(buffer, sizeof(buffer), "%d", count);
00748 
00749   return radical + ":" + string(buffer);
00750 }
00751 
00752 
00753 hwNode *hwNode::addChild(const hwNode & node)
00754 {
00755   hwNode *existing = NULL;
00756   hwNode *samephysid = NULL;
00757   string id = node.getId();
00758   int count = 0;
00759 
00760   if (!This)
00761     return NULL;
00762 
00763 // first see if the new node is attracted by one of our children
00764   for (unsigned int i = 0; i < This->children.size(); i++)
00765     if (This->children[i].attractsNode(node))
00766       return This->children[i].addChild(node);
00767 
00768 // find if another child already has the same physical id
00769 // in that case, we remove BOTH physical ids and let auto-allocation proceed
00770   if (node.getPhysId() != "")
00771     samephysid = getChildByPhysId(node.getPhysId());
00772   if (samephysid)
00773   {
00774     samephysid->setPhysId("");
00775   }
00776 
00777   existing = getChild(id);
00778   if (existing)                                   // first rename existing instance
00779   {
00780     while (getChild(generateId(id, count)))       // find a usable name
00781       count++;
00782 
00783     existing->setId(generateId(id, count));       // rename
00784   }
00785 
00786   while (getChild(generateId(id, count)))
00787     count++;
00788 
00789   This->children.push_back(node);
00790   if (existing || getChild(generateId(id, 0)))
00791     This->children.back().setId(generateId(id, count));
00792 
00793   if (samephysid)
00794     This->children.back().setPhysId("");
00795 
00796   return &(This->children.back());
00797 //return getChild(This->children.back().getId());
00798 }
00799 
00800 
00801 void hwNode::attractHandle(const string & handle)
00802 {
00803   if (!This)
00804     return;
00805 
00806   This->attracted.push_back(handle);
00807 }
00808 
00809 
00810 bool hwNode::attractsHandle(const string & handle) const
00811 {
00812   unsigned int i = 0;
00813   if (handle == "" || !This)
00814     return false;
00815 
00816   for (i = 0; i < This->attracted.size(); i++)
00817     if (This->attracted[i] == handle)
00818       return true;
00819 
00820   for (i = 0; i < This->children.size(); i++)
00821     if (This->children[i].attractsHandle(handle))
00822       return true;
00823 
00824   return false;
00825 }
00826 
00827 
00828 bool hwNode::attractsNode(const hwNode & node) const
00829 {
00830   if (!This || !node.This)
00831     return false;
00832 
00833   return attractsHandle(node.This->handle);
00834 }
00835 
00836 
00837 bool hwNode::isCapable(const string & feature) const
00838 {
00839   string featureid = cleanupId(feature);
00840 
00841   if (!This)
00842     return false;
00843 
00844   for (unsigned int i = 0; i < This->features.size(); i++)
00845     if (This->features[i] == featureid)
00846       return true;
00847 
00848   return false;
00849 }
00850 
00851 
00852 void hwNode::addCapability(const string & feature,
00853 const string & description)
00854 {
00855   string features = feature;
00856 
00857   if (!This)
00858     return;
00859 
00860   if (description != "")
00861     This->features_descriptions[cleanupId(feature)] = strip(description);
00862 
00863   while (features.length() > 0)
00864   {
00865     size_t pos = features.find('\0');
00866 
00867     if (pos == string::npos)
00868     {
00869       if (!isCapable(cleanupId(features)))
00870         This->features.push_back(cleanupId(features));
00871       features = "";
00872     }
00873     else
00874     {
00875       string featureid = cleanupId(features.substr(0, pos));
00876       if (!isCapable(featureid))
00877         This->features.push_back(featureid);
00878       features = features.substr(pos + 1);
00879     }
00880   }
00881 }
00882 
00883 
00884 void hwNode::describeCapability(const string & feature,
00885 const string & description)
00886 {
00887   if (!This)
00888     return;
00889 
00890   if (!isCapable(feature))
00891     return;
00892 
00893   This->features_descriptions[cleanupId(feature)] = strip(description);
00894 }
00895 
00896 
00897 string hwNode::getCapabilities() const
00898 {
00899   string result = "";
00900 
00901   if (!This)
00902     return "";
00903 
00904   for (unsigned int i = 0; i < This->features.size(); i++)
00905     result += This->features[i] + " ";
00906 
00907   return strip(result);
00908 }
00909 
00910 
00911 vector < string > hwNode::getCapabilitiesList() const
00912 {
00913   vector < string > result;
00914 
00915   if (!This)
00916     return result;
00917 
00918   for (unsigned int i = 0; i < This->features.size(); i++)
00919     result.push_back(This->features[i]);
00920 
00921   return result;
00922 }
00923 
00924 
00925 string hwNode::getCapabilityDescription(const string & feature) const
00926 {
00927   string featureid = cleanupId(feature);
00928 
00929   if (!isCapable(feature))
00930     return "";
00931 
00932   if (!This)
00933     return "";
00934 
00935   if (This->features_descriptions.find(featureid) ==
00936     This->features_descriptions.end())
00937     return "";
00938 
00939   return This->features_descriptions[featureid];
00940 }
00941 
00942 
00943 void hwNode::setConfig(const string & key,
00944 const string & value)
00945 {
00946   if (!This)
00947     return;
00948 
00949   This->config[key] = strip(value);
00950   if (strip(value) == "")
00951     This->config.erase(This->config.find(key));
00952 }
00953 
00954 
00955 void hwNode::setConfig(const string & key,
00956 unsigned long long value)
00957 {
00958   if (!This)
00959     return;
00960 
00961   This->config[key] = tostring(value);
00962 }
00963 
00964 
00965 string hwNode::getConfig(const string & key) const
00966 {
00967   if (!This)
00968     return "";
00969 
00970   if (This->config.find(key) == This->config.end())
00971     return "";
00972 
00973   return This->config[key];
00974 }
00975 
00976 
00977 vector < string > hwNode::getConfigKeys() const
00978 {
00979   vector < string > result;
00980 
00981   if (!This)
00982     return result;
00983 
00984   for (map < string, string >::iterator i = This->config.begin();
00985     i != This->config.end(); i++)
00986   result.push_back(i->first);
00987 
00988   return result;
00989 }
00990 
00991 vector < string > hwNode::getConfigValues(const string & separator) const
00992 {
00993   vector < string > result;
00994 
00995   if (!This)
00996     return result;
00997 
00998   for (map < string, string >::iterator i = This->config.begin();
00999     i != This->config.end(); i++)
01000   result.push_back(i->first + separator + i->second);
01001 
01002   return result;
01003 }
01004 
01005 
01006 string hwNode::getLogicalName() const
01007 {
01008   if (This && (This->logicalnames.size()>0))
01009     return This->logicalnames[0];
01010   else
01011     return "";
01012 }
01013 
01014 
01015 vector<string> hwNode::getLogicalNames() const
01016 {
01017   if (This)
01018     return This->logicalnames;
01019   else
01020     return vector<string>();
01021 }
01022 
01023 
01024 void hwNode::setLogicalName(const string & name)
01025 {
01026   string n = strip(name);
01027 
01028   if (This)
01029   {
01030     for (unsigned i = 0; i < This->logicalnames.size(); i++)
01031       if (This->logicalnames[i] == n || This->logicalnames[i] == "/dev/" + n)
01032         return;                                   // nothing to add, this logical name already exists
01033     if ((name[0] != '/') && exists("/dev/" + n))
01034     {
01035       This->logicalnames.push_back("/dev/" + n);
01036     }
01037     else
01038       This->logicalnames.push_back(n);
01039 
01040     if(This->dev == "")
01041       This->dev = get_devid(n);
01042   }
01043 }
01044 
01045 
01046 string hwNode::getDev() const
01047 {
01048   if (This)
01049     return This->dev;
01050   else
01051     return "";
01052 }
01053 
01054 
01055 void hwNode::setDev(const string & s)
01056 {
01057   if (This)
01058   {
01059     string devid = strip(s);
01060     unsigned int i = 0;
01061 
01062     while((i<devid.length()) && isdigit(devid[i])) i++;
01063     if(i>=devid.length()) return;
01064     if(devid[i] != ':') return;
01065     i++;
01066     while((i<devid.length()) && isdigit(devid[i])) i++;
01067     if(i!=devid.length()) return;
01068 
01069     This->dev = devid;
01070   }
01071 }
01072 
01073 
01074 string hwNode::getBusInfo() const
01075 {
01076   if (This)
01077     return This->businfo;
01078   else
01079     return "";
01080 }
01081 
01082 
01083 void hwNode::setBusInfo(const string & businfo)
01084 {
01085   if (This)
01086   {
01087     if (businfo.find('@') != string::npos)
01088       This->businfo = strip(businfo);
01089     else
01090       This->businfo = guessBusInfo(strip(businfo));
01091   }
01092 }
01093 
01094 
01095 string hwNode::getPhysId() const
01096 {
01097   if (This)
01098     return This->physid;
01099   else
01100     return "";
01101 }
01102 
01103 
01104 void hwNode::setPhysId(long physid)
01105 {
01106   if (This)
01107   {
01108     char buffer[20];
01109 
01110     snprintf(buffer, sizeof(buffer), "%lx", physid);
01111     This->physid = string(buffer);
01112   }
01113 }
01114 
01115 
01116 void hwNode::setPhysId(unsigned physid1,
01117 unsigned physid2)
01118 {
01119   if (This)
01120   {
01121     char buffer[40];
01122 
01123     if (physid2 != 0)
01124       snprintf(buffer, sizeof(buffer), "%x.%x", physid1, physid2);
01125     else
01126       snprintf(buffer, sizeof(buffer), "%x", physid1);
01127     This->physid = string(buffer);
01128   }
01129 }
01130 
01131 
01132 void hwNode::setPhysId(unsigned physid1,
01133 unsigned physid2,
01134 unsigned physid3)
01135 {
01136   if (This)
01137   {
01138     char buffer[40];
01139 
01140     snprintf(buffer, sizeof(buffer), "%x.%x.%x", physid1, physid2, physid3);
01141     This->physid = string(buffer);
01142   }
01143 }
01144 
01145 
01146 void hwNode::setPhysId(const string & physid)
01147 {
01148   if (This)
01149   {
01150     This->physid = strip(physid);
01151 
01152     while ((This->physid.length() > 1) && (This->physid[0] == '0'))
01153       This->physid.erase(0, 1);
01154   }
01155 }
01156 
01157 
01158 void hwNode::assignPhysIds()
01159 {
01160   if (!This)
01161     return;
01162 
01163   for (unsigned int i = 0; i < This->children.size(); i++)
01164   {
01165     long curid = 0;
01166 
01167     if (This->children[i].getClass() == hw::bridge)
01168       curid = 0x100;
01169 
01170     if (This->children[i].getPhysId() == "")
01171     {
01172       while (getChildByPhysId(curid))
01173         curid++;
01174 
01175       This->children[i].setPhysId(curid);
01176     }
01177 
01178     This->children[i].assignPhysIds();
01179   }
01180 }
01181 
01182 
01183 void hwNode::fixInconsistencies()
01184 {
01185   if (!This)
01186     return;
01187 
01188   if (getCapacity() < getSize())
01189     setCapacity(0);
01190 
01191   guessProduct(*this);
01192   guessVendor(*this);
01193 
01194   if(getLogicalName() != "")
01195     claim();
01196 
01197   for (unsigned int i = 0; i < This->children.size(); i++)
01198     This->children[i].fixInconsistencies();
01199 }
01200 
01201 
01202 void hwNode::merge(const hwNode & node)
01203 {
01204   if (!This)
01205     return;
01206   if (!node.This)
01207     return;
01208 
01209   if (This->deviceclass == hw::generic)
01210     This->deviceclass = node.getClass();
01211   if (This->vendor == "")
01212     This->vendor = node.getVendor();
01213   if (This->product == "")
01214     This->product = node.getProduct();
01215   if (This->version == "")
01216     This->version = node.getVersion();
01217   if (This->serial == "")
01218     This->serial = node.getSerial();
01219   if (This->start == 0)
01220     This->start = node.getStart();
01221   if (This->size == 0)
01222     This->size = node.getSize();
01223   if (This->capacity == 0)
01224     This->capacity = node.getCapacity();
01225   if (This->clock == 0)
01226     This->clock = node.getClock();
01227   if (This->width == 0)
01228     This->width = node.getWidth();
01229   if (node.enabled())
01230     enable();
01231   else
01232     disable();
01233   if (node.claimed())
01234     claim();
01235   if (This->handle == "")
01236     This->handle = node.getHandle();
01237   if (This->description == "")
01238     This->description = node.getDescription();
01239   if (This->logicalnames.size() == 0)
01240     This->logicalnames = node.getLogicalNames();
01241   if (This->businfo == "")
01242     This->businfo = node.getBusInfo();
01243   if (This->physid == "")
01244     This->physid = node.getPhysId();
01245 
01246   for (unsigned int i = 0; i < node.This->features.size(); i++)
01247     addCapability(node.This->features[i]);
01248   for (map < string, string >::iterator i = node.This->features_descriptions.begin();
01249     i != node.This->features_descriptions.end(); i++)
01250   describeCapability(i->first, i->second);
01251 
01252   for (map < string, string >::iterator i = node.This->config.begin();
01253     i != node.This->config.end(); i++)
01254   setConfig(i->first, i->second);
01255 
01256   for (map < string, value >::iterator i = node.This->hints.begin();
01257     i != node.This->hints.end(); i++)
01258   addHint(i->first, i->second);
01259 }
01260 
01261 
01262 void hwNode::addResource(const resource & r)
01263 {
01264   if (!This)
01265     return;
01266 
01267   This->resources.push_back(r);
01268 }
01269 
01270 
01271 bool hwNode::usesResource(const resource & r) const
01272 {
01273   if (!This)
01274     return false;
01275 
01276   for (size_t i = 0; i < This->resources.size(); i++)
01277     if (r == This->resources[i])
01278       return true;
01279 
01280   return false;
01281 }
01282 
01283 
01284 vector < string > hwNode::getResources(const string & separator) const
01285 {
01286   vector < string > result;
01287 
01288   if (!This)
01289     return result;
01290 
01291   for (vector < resource >::iterator i = This->resources.begin();
01292     i != This->resources.end(); i++)
01293   result.push_back(i->asString(separator));
01294 
01295   return result;
01296 }
01297 
01298 
01299 void hwNode::setWidth(unsigned int width)
01300 {
01301   if(This)
01302     This->width = width;
01303 }
01304 
01305 
01306 unsigned int hwNode::getWidth() const
01307 {
01308   if(This)
01309     return This->width;
01310   else
01311     return 0;
01312 }
01313 
01314 
01315 void hwNode::addHint(const string & id, const value & v)
01316 {
01317   if(This)
01318     This->hints[id] = v;
01319 }
01320 
01321 
01322 value hwNode::getHint(const string & id) const
01323 {
01324   if(!This)
01325     return value();
01326 
01327   return This->hints[id];
01328 }
01329 
01330 vector < string > hwNode::getHints() const
01331 {
01332   vector < string > result;
01333 
01334   if (!This)
01335     return result;
01336 
01337   for (map < string, value >::iterator i = This->hints.begin();
01338     i != This->hints.end(); i++)
01339   result.push_back(i->first);
01340 
01341   return result;
01342 }
01343 
01344 string hwNode::asJSON(unsigned level)
01345 {
01346   vector < string > config;
01347   vector < string > resources;
01348   ostringstream out;
01349 
01350   if(!This) return "";
01351 
01352   config = getConfigKeys();
01353   resources = getResources("\" value=\"");
01354 
01355   if(visible(getClassName()))
01356   {
01357     out << "{" << endl;
01358     out << spaces(2*level+2) << "\"id\" : \"" << getId() << "\"," << endl;
01359     out << spaces(2*level+2) << "\"class\" : \"" << getClassName() << "\"";
01360 
01361     if (disabled())
01362       out << "," << endl << spaces(2*level+2) << "\"disabled\" : true";
01363     if (claimed())
01364       out << "," << endl << spaces(2*level+2) << "\"claimed\" : true";
01365 
01366     if(getHandle() != "")
01367       out << "," << endl << spaces(2*level+2) << "\"handle\" : \"" << getHandle() << "\"";
01368 
01369     if (getDescription() != "")
01370     {
01371       out << "," << endl;
01372       out << spaces(2*level+2);
01373       out << "\"description\" : \"";
01374       out << escapeJSON(getDescription());
01375       out << "\"";
01376     }
01377 
01378     if (getProduct() != "")
01379     {
01380       out << "," << endl;
01381       out << spaces(2*level+2);
01382       out << "\"product\" : \"";
01383       out << escapeJSON(getProduct());
01384       out << "\"";
01385     }
01386 
01387     if (getVendor() != "")
01388     {
01389       out << "," << endl;
01390       out << spaces(2*level+2);
01391       out << "\"vendor\" : \"";
01392       out << escapeJSON(getVendor());
01393       out << "\"";
01394     }
01395 
01396     if (getPhysId() != "")
01397     {
01398       out << "," << endl;
01399       out << spaces(2*level+2);
01400       out << "\"physid\" : \"";
01401       out << getPhysId();
01402       out << "\"";
01403     }
01404 
01405     if (getBusInfo() != "")
01406     {
01407       out << "," << endl;
01408       out << spaces(2*level+2);
01409       out << "\"businfo\" : \"";
01410       out << escapeJSON(getBusInfo());
01411       out << "\"";
01412     }
01413 
01414     if (getLogicalName() != "")
01415     {
01416       vector<string> logicalnames = getLogicalNames();
01417 
01418       out << "," << endl;
01419       out << spaces(2*level+2);
01420       out << "\"logicalname\" : ";
01421       if(logicalnames.size() > 1)
01422       {
01423         out << "[";
01424         for(unsigned int i = 0; i<logicalnames.size(); i++)
01425         {
01426           if(i) out << ", ";
01427           out << "\"" << logicalnames[i] << "\"";
01428         }
01429         out << "]";
01430       }
01431       else
01432         out << "\"" << escapeJSON(getLogicalName()) << "\"";
01433     }
01434 
01435     if (getDev() != "")
01436     {
01437       out << "," << endl;
01438       out << spaces(2*level+2);
01439       out << "\"dev\" : \"";
01440       out << escapeJSON(getDev());
01441       out << "\"";
01442     }
01443 
01444     if (getVersion() != "")
01445     {
01446       out << "," << endl;
01447       out << spaces(2*level+2);
01448       out << "\"version\" : \"";
01449       out << escapeJSON(getVersion());
01450       out << "\"";
01451     }
01452 
01453     if (getDate() != "")
01454     {
01455       out << "," << endl;
01456       out << spaces(2*level+2);
01457       out << "\"date\" : \"";
01458       out << escapeJSON(getDate());
01459       out << "\"";
01460     }
01461 
01462     if (getSerial() != "")
01463     {
01464       out << "," << endl;
01465       out << spaces(2*level+2);
01466       out << "\"serial\" : \"";
01467       out << (::enabled("output:sanitize")?REMOVED:escapeJSON(getSerial()));
01468       out << "\"";
01469     }
01470 
01471     if (getSlot() != "")
01472     {
01473       out << "," << endl;
01474       out << spaces(2*level+2);
01475       out << "\"slot\" : \"";
01476       out << escapeJSON(getSlot());
01477       out << "\"";
01478     }
01479 
01480     if ((getSize() > 0) || (getCapacity() > 0))
01481       switch (getClass())
01482       {
01483         case hw::memory:
01484         case hw::address:
01485         case hw::storage:
01486         case hw::disk:
01487         case hw::display:
01488           out << "," << endl << spaces(2*level+2) << "\"units\" : \"bytes\"";
01489           break;
01490 
01491         case hw::processor:
01492         case hw::bus:
01493         case hw::system:
01494           out << "," << endl << spaces(2*level+2) << "\"units\" : \"Hz\"";
01495           break;
01496 
01497         case hw::power:
01498           out << "," << endl << spaces(2*level+2) << "\"units\" : \"mWh\"";
01499           break;
01500 
01501         case hw::network:
01502           out << "," << endl << spaces(2*level+2) << "\"units\" : \"bit/s\"";
01503           break;
01504 
01505         default:
01506           break;
01507       }
01508 
01509     if (getSize() > 0)
01510     {
01511       out << "," << endl;
01512       out << spaces(2*level+2);
01513       out << "\"size\" : ";
01514       out << getSize();
01515     }
01516 
01517     if (getCapacity() > 0)
01518     {
01519       out << "," << endl;
01520       out << spaces(2*level+2);
01521       out << "\"capacity\" : ";
01522       out << getCapacity();
01523     }
01524 
01525     if (getWidth() > 0)
01526     {
01527       out << "," << endl;
01528       out << spaces(2*level+2);
01529       out << "\"width\" : ";
01530       out << getWidth();
01531     }
01532 
01533     if (getClock() > 0)
01534     {
01535       out << "," << endl;
01536       out << spaces(2*level+2);
01537       out << "\"clock\" : ";
01538       out << getClock();
01539     }
01540 
01541     if (config.size() > 0)
01542     {
01543       out << "," << endl;
01544       out << spaces(2*level+2);
01545       out << "\"configuration\" : {" << endl;
01546       for (unsigned int j = 0; j < config.size(); j++)
01547       {
01548         if(j) out << "," << endl;
01549         out << spaces(2*level+4);
01550         out << "\"" << escapeJSON(config[j]) << "\" : \"" << escapeJSON(getConfig(config[j])) << "\"";
01551       }
01552       out << endl << spaces(2*level+2);
01553       out << "}";
01554     }
01555     config.clear();
01556 
01557     splitlines(getCapabilities(), config, ' ');
01558     if (config.size() > 0)
01559     {
01560       out << "," << endl;
01561       out << spaces(2*level+2);
01562       out << "\"capabilities\" : {" << endl;
01563       for (unsigned int j = 0; j < config.size(); j++)
01564       {
01565         if(j) out << "," << endl;
01566         out << spaces(2*level+4);
01567         out << "\"" << escapeJSON(config[j]) << "\" : ";
01568         if (getCapabilityDescription(config[j]) == "")
01569         {
01570           out << "true";
01571         }
01572         else
01573         {
01574           out << "\"";
01575           out << escapeJSON(getCapabilityDescription(config[j]));
01576           out << "\"";
01577         }
01578       }
01579       out << endl << spaces(2*level+2);
01580       out << "}";
01581     }
01582     config.clear();
01583 
01584     if (0 && resources.size() > 0)
01585     {
01586       out << spaces(2*level+1);
01587       out << "<resources>" << endl;
01588       for (unsigned int j = 0; j < resources.size(); j++)
01589       {
01590         out << spaces(2*level+2);
01591         out << "<resource type=\"" << escapeJSON(resources[j]) << "\" />";
01592         out << endl;
01593       }
01594       out << spaces(2*level+1);
01595       out << "</resources>" << endl;
01596     }
01597     resources.clear();
01598   }
01599 
01600   
01601   if(countChildren()>0)
01602   {
01603     if(visible(getClassName()))
01604       out << "," << endl << spaces(2*level+2) << "\"children\" : [" << endl;
01605 
01606     for (unsigned int i = 0; i < countChildren(); i++)
01607     {
01608       out << spaces(2*level+4) << getChild(i)->asJSON(visible(getClassName()) ? level + 2 : 1);
01609       if(visible(getChild(i)->getClassName()) && (i < countChildren()-1)) out << "," << endl;
01610     }
01611 
01612     if(visible(getClassName()))
01613       out << endl << spaces(2*level+2) << "]";
01614   }
01615 
01616   if(visible(getClassName()))
01617   {
01618     out << endl << spaces(2*level);
01619     out << "}";
01620   }
01621 
01622   return out.str();
01623 }
01624 
01625 string hwNode::asXML(unsigned level)
01626 {
01627   vector < string > config;
01628   vector < string > resources;
01629   ostringstream out;
01630 
01631   if(!This) return "";
01632 
01633   config = getConfigKeys();
01634   resources = getResources("\" value=\"");
01635 
01636   if (level == 0)
01637   {
01638     struct utsname un;
01639 
01640     out << "<?xml version=\"1.0\" standalone=\"yes\" ?>" << endl;
01641     out << _("<!-- generated by lshw-") << getpackageversion() << " -->" <<
01642   #if defined(__GNUC__) && defined(__VERSION__)
01643       endl << "<!-- GCC " << escapecomment(__VERSION__) << " -->" <<
01644   #endif
01645       endl;
01646 
01647     if(uname(&un) == 0)
01648       out << "<!-- " << escapecomment(un.sysname) << " " << escapecomment(un.release) << " " << escapecomment(un.version) << " " << escapecomment(un.machine) << " -->" << endl;
01649   #if defined(__GLIBC__) && defined(_CS_GNU_LIBC_VERSION)
01650     char version[PATH_MAX];
01651 
01652       if(confstr(_CS_GNU_LIBC_VERSION, version, sizeof(version))>0)
01653         out << "<!-- GNU libc " << __GLIBC__ << " (" << escapecomment(version) << ") -->" << endl;
01654   #endif
01655     if (geteuid() != 0)
01656       out << _("<!-- WARNING: not running as root -->") << endl;
01657 
01658     if(::enabled("output:list"))
01659       out << "<list>" << endl;
01660 
01661   }
01662 
01663   if(visible(getClassName()))
01664   {
01665     out << spaces(2*level);
01666     out << "<node id=\"" << getId() << "\"";
01667     if (disabled())
01668       out << " disabled=\"true\"";
01669     if (claimed())
01670       out << " claimed=\"true\"";
01671 
01672     out << " class=\"" << getClassName() << "\"";
01673     out << " handle=\"" << getHandle() << "\"";
01674     out << ">" << endl;
01675 
01676     if (getDescription() != "")
01677     {
01678       out << spaces(2*level+1);
01679       out << "<description>";
01680       out << escape(getDescription());
01681       out << "</description>";
01682       out << endl;
01683     }
01684 
01685     if (getProduct() != "")
01686     {
01687       out << spaces(2*level+1);
01688       out << "<product>";
01689       out << escape(getProduct());
01690       out << "</product>";
01691       out << endl;
01692     }
01693 
01694     if (getVendor() != "")
01695     {
01696       out << spaces(2*level+1);
01697       out << "<vendor>";
01698       out << escape(getVendor());
01699       out << "</vendor>";
01700       out << endl;
01701     }
01702 
01703     if (getPhysId() != "")
01704     {
01705       out << spaces(2*level+1);
01706       out << "<physid>";
01707       out << getPhysId();
01708       out << "</physid>";
01709       out << endl;
01710     }
01711 
01712     if (getBusInfo() != "")
01713     {
01714       out << spaces(2*level+1);
01715       out << "<businfo>";
01716       out << escape(getBusInfo());
01717       out << "</businfo>";
01718       out << endl;
01719     }
01720 
01721     if (getLogicalName() != "")
01722     {
01723       vector<string> logicalnames = getLogicalNames();
01724 
01725       for(unsigned int i = 0; i<logicalnames.size(); i++)
01726       {
01727         out << spaces(2*level+1);
01728         out << "<logicalname>";
01729         out << logicalnames[i];
01730         out << "</logicalname>";
01731         out << endl;
01732       }
01733     }
01734 
01735     if (getDev() != "")
01736     {
01737       out << spaces(2*level+1);
01738       out << "<dev>";
01739       out << escape(getDev());
01740       out << "</dev>";
01741       out << endl;
01742     }
01743 
01744     if (getVersion() != "")
01745     {
01746       out << spaces(2*level+1);
01747       out << "<version>";
01748       out << escape(getVersion());
01749       out << "</version>";
01750       out << endl;
01751     }
01752 
01753     if (getDate() != "")
01754     {
01755       out << spaces(2*level+1);
01756       out << "<date>";
01757       out << escape(getDate());
01758       out << "</date>";
01759       out << endl;
01760     }
01761 
01762     if (getSerial() != "")
01763     {
01764       out << spaces(2*level+1);
01765       out << "<serial>";
01766       out << (::enabled("output:sanitize")?REMOVED:escape(getSerial()));
01767       out << "</serial>";
01768       out << endl;
01769     }
01770 
01771     if (getSlot() != "")
01772     {
01773       out << spaces(2*level+1);
01774       out << "<slot>";
01775       out << escape(getSlot());
01776       out << "</slot>";
01777       out << endl;
01778     }
01779 
01780     if (getSize() > 0)
01781     {
01782       out << spaces(2*level+1);
01783       out << "<size";
01784       switch (getClass())
01785       {
01786         case hw::memory:
01787         case hw::address:
01788         case hw::storage:
01789         case hw::disk:
01790         case hw::volume:
01791         case hw::display:
01792           out << " units=\"bytes\"";
01793           break;
01794 
01795         case hw::processor:
01796         case hw::bus:
01797         case hw::system:
01798           out << " units=\"Hz\"";
01799           break;
01800 
01801         case hw::network:
01802           out << " units=\"bit/s\"";
01803           break;
01804 
01805         case hw::power:
01806           out << " units=\"mWh\"";
01807           break;
01808 
01809         default:
01810           out << "";
01811       }
01812       out << ">";
01813       out << getSize();
01814       out << "</size>";
01815       out << endl;
01816     }
01817 
01818     if (getCapacity() > 0)
01819     {
01820       out << spaces(2*level+1);
01821       out << "<capacity";
01822       switch (getClass())
01823       {
01824         case hw::memory:
01825         case hw::address:
01826         case hw::storage:
01827         case hw::disk:
01828           out << " units=\"bytes\"";
01829           break;
01830 
01831         case hw::processor:
01832         case hw::bus:
01833         case hw::system:
01834           out << " units=\"Hz\"";
01835           break;
01836 
01837         case hw::power:
01838           out << " units=\"mWh\"";
01839           break;
01840 
01841         default:
01842           out << "";
01843       }
01844       out << ">";
01845       out << getCapacity();
01846       out << "</capacity>";
01847       out << endl;
01848     }
01849 
01850     if (getWidth() > 0)
01851     {
01852       out << spaces(2*level+1);
01853       out << "<width units=\"bits\">";
01854       out << getWidth();
01855       out << "</width>";
01856       out << endl;
01857     }
01858 
01859     if (getClock() > 0)
01860     {
01861       out << spaces(2*level+1);
01862       out << "<clock units=\"Hz\">";
01863       out << getClock();
01864       out << "</clock>";
01865       out << endl;
01866     }
01867 
01868     if (config.size() > 0)
01869     {
01870       out << spaces(2*level+1);
01871       out << "<configuration>" << endl;
01872       for (unsigned int j = 0; j < config.size(); j++)
01873       {
01874         out << spaces(2*level+2);
01875         out << "<setting id=\"" << escape(config[j]) << "\" value=\"" << escape(getConfig(config[j])) << "\" />";
01876         out << endl;
01877       }
01878       out << spaces(2*level+1);
01879       out << "</configuration>" << endl;
01880     }
01881     config.clear();
01882 
01883     splitlines(getCapabilities(), config, ' ');
01884     if (config.size() > 0)
01885     {
01886       out << spaces(2*level+1);
01887       out << "<capabilities>" << endl;
01888       for (unsigned int j = 0; j < config.size(); j++)
01889       {
01890         out << spaces(2*level+2);
01891         out << "<capability id=\"" << escape(config[j]);
01892         if (getCapabilityDescription(config[j]) == "")
01893         {
01894           out << "\" />";
01895         }
01896         else
01897         {
01898           out << "\" >";
01899           out << escape(getCapabilityDescription(config[j]));
01900           out << "</capability>";
01901         }
01902         out << endl;
01903       }
01904       out << spaces(2*level+1);
01905       out << "</capabilities>" << endl;
01906     }
01907     config.clear();
01908 
01909     if (resources.size() > 0)
01910     {
01911       out << spaces(2*level+1);
01912       out << "<resources>" << endl;
01913       for (unsigned int j = 0; j < resources.size(); j++)
01914       {
01915         out << spaces(2*level+2);
01916         out << "<resource type=\"" << resources[j] << "\" />";
01917         out << endl;
01918       }
01919       out << spaces(2*level+1);
01920       out << "</resources>" << endl;
01921     }
01922     resources.clear();
01923   }
01924 
01925   for (unsigned int i = 0; i < countChildren(); i++)
01926   {
01927     out << getChild(i)->asXML(visible(getClassName()) ? level + 1 : 1);
01928   }
01929 
01930   if(visible(getClassName()))
01931   {
01932     out << spaces(2*level);
01933     out << "</node>" << endl;
01934   }
01935 
01936   if((level==0) && ::enabled("output:list"))
01937     out << "</list>" << endl;
01938 
01939 
01940   return out.str();
01941 }
01942 
01943 string hwNode::asString()
01944 {
01945   string summary = "";
01946   if(!This)
01947     return "";
01948 
01949   if(getClass() != hw::memory)
01950     summary = getProduct();        // memory devices tend to have obscure product names
01951   if (summary == "")
01952     summary = getDescription();
01953 
01954   if((getClass() == hw::memory) || (getClass() == hw::disk) || (getClass() == hw::storage) || (getClass() == hw::volume))
01955   {
01956     unsigned long long size = 0;
01957     if(getClass() != hw::memory)
01958     {
01959       if(getCapacity())
01960         size = getCapacity();
01961       else
01962       {
01963         if(getSize())
01964           size = getSize();
01965       }
01966     }
01967     else
01968     {
01969       if(getSize())
01970         size = getSize();
01971     }
01972     if(size)
01973       summary = (getClass()==hw::disk?(decimalkilos(size)+"B"):kilobytes(size)) +" "+ summary;
01974   }
01975 
01976   return summary;
01977 }
01978 
01979 struct hw::resource_i
01980 {
01981   hw::hwResourceType type;
01982 
01983   unsigned int ui1;
01984   unsigned long ul1, ul2;
01985   unsigned long long ull1, ull2;
01986   bool b;
01987 
01988   int refcount;
01989 };
01990 
01991 resource::resource()
01992 {
01993   This = new struct resource_i;
01994 
01995   if (This)
01996   {
01997     memset(This, 0, sizeof(*This));
01998     This->type = none;
01999     This->refcount = 1;
02000   }
02001 }
02002 
02003 
02004 resource::~resource()
02005 {
02006   if (This)
02007   {
02008     This->refcount--;
02009 
02010     if (This->refcount <= 0)
02011     {
02012       delete This;
02013       This = NULL;
02014     }
02015   }
02016 }
02017 
02018 
02019 resource::resource(const resource & r)
02020 {
02021   This = r.This;
02022 
02023   if (This)
02024     This->refcount++;
02025 }
02026 
02027 
02028 resource & resource::operator = (const resource & r)
02029 {
02030   if (this == &r)
02031     return *this;                                 // ignore self-affectation
02032 
02033   if (This == r.This)
02034     return *this;                                 // both objects reference the same data
02035 
02036   if (This)
02037   {
02038     This->refcount--;
02039 
02040     if (This->refcount <= 0)
02041     {
02042       delete This;
02043       This = NULL;
02044     }
02045   }
02046 
02047   This = r.This;
02048   if (This)
02049     This->refcount++;
02050 
02051   return *this;
02052 }
02053 
02054 
02055 resource resource::iomem(unsigned long long start,
02056 unsigned long long end)
02057 {
02058   resource r;
02059 
02060   if (!r.This)
02061     return r;
02062 
02063   r.This->type = hw::iomem;
02064   r.This->ull1 = start;
02065   r.This->ull2 = end;
02066 
02067   return r;
02068 }
02069 
02070 
02071 resource resource::ioport(unsigned long start,
02072 unsigned long end)
02073 {
02074   resource r;
02075 
02076   if (!r.This)
02077     return r;
02078 
02079   r.This->type = hw::ioport;
02080   r.This->ul1 = start;
02081   r.This->ul2 = end;
02082 
02083   return r;
02084 }
02085 
02086 
02087 resource resource::mem(unsigned long long start,
02088 unsigned long long end, bool prefetchable)
02089 {
02090   resource r;
02091 
02092   if (!r.This)
02093     return r;
02094 
02095   r.This->type = hw::mem;
02096   r.This->ull1 = start;
02097   r.This->ull2 = end;
02098   r.This->b = prefetchable;
02099 
02100   return r;
02101 }
02102 
02103 
02104 resource resource::irq(unsigned int value)
02105 {
02106   resource r;
02107 
02108   if (!r.This)
02109     return r;
02110 
02111   r.This->type = hw::irq;
02112   r.This->ui1 = value;
02113 
02114   return r;
02115 }
02116 
02117 
02118 resource resource::dma(unsigned int value)
02119 {
02120   resource r;
02121 
02122   if (!r.This)
02123     return r;
02124 
02125   r.This->type = hw::dma;
02126   r.This->ui1 = value;
02127 
02128   return r;
02129 }
02130 
02131 
02132 string resource::asString(const string & separator) const
02133 {
02134   char buffer[80];
02135   string result = "";
02136 
02137   if (!This)
02138     return result;
02139 
02140   strncpy(buffer, "", sizeof(buffer));
02141 
02142   switch (This->type)
02143   {
02144     case hw::none:
02145       result = _("(none)");
02146       break;
02147     case hw::dma:
02148       result = _("dma") + separator;
02149       snprintf(buffer, sizeof(buffer), "%d", This->ui1);
02150       break;
02151     case hw::irq:
02152       result = _("irq") + separator;
02153       snprintf(buffer, sizeof(buffer), "%d", This->ui1);
02154       break;
02155     case hw::iomem:
02156       result = _("iomemory") + separator;
02157       snprintf(buffer, sizeof(buffer), "%llx-%llx", This->ull1, This->ull2);
02158       break;
02159     case hw::mem:
02160       result = _("memory") + separator;
02161       snprintf(buffer, sizeof(buffer), "%llx-%llx", This->ull1, This->ull2);
02162       if(This->b) strcat(buffer, _("(prefetchable)"));
02163       break;
02164     case hw::ioport:
02165       result = _("ioport") + separator;
02166       if(This->ul1 == This->ul2)
02167         snprintf(buffer, sizeof(buffer), "%lx", This->ul1);
02168       else
02169         snprintf(buffer, sizeof(buffer), _("%lx(size=%ld)"), This->ul1, This->ul2 - This->ul1 + 1);
02170       break;
02171     default:
02172       result = _("(unknown)");
02173   }
02174 
02175   return result + string(buffer);
02176 }
02177 
02178 
02179 bool resource::operator == (const resource & r)
02180 const
02181 {
02182   if (This == r.This)
02183     return true;
02184 
02185   if (!This || !r.This)
02186     return false;
02187 
02188   if (This->type != r.This->type)
02189     return false;
02190 
02191   switch (This->type)
02192   {
02193     case hw::dma:
02194     case hw::irq:
02195       return This->ui1 == r.This->ui1;
02196       break;
02197 
02198     case hw::iomem:
02199     case hw::mem:
02200       return ((This->ull1 >= r.This->ull1)
02201       && (This->ull2 <= r.This->ull2)) || ((r.This->ull1 >= This->ull1)
02202       && (r.This->ull2 <= This->ull2));
02203     break;
02204 
02205     case hw::ioport:
02206       return ((This->ul1 >= r.This->ul1)
02207       && (This->ul1 <= r.This->ul2)) || ((r.This->ul1 >= This->ul1)
02208       && (r.This->ul1 <= This->ul2));
02209     break;
02210 
02211     default:return false;
02212   }
02213 }
02214 
02215 
02216 struct hw::value_i
02217 {
02218   hw::hwValueType type;
02219 
02220   long long ll;
02221   string s;
02222   bool b;
02223 
02224   int refcount;
02225 };
02226 
02227 value::value()
02228 {
02229   This = new hw::value_i;
02230 
02231   if(This)
02232   {
02233     This->type = nil;
02234     This->refcount = 1;
02235   }
02236 }
02237 
02238 
02239 value::~value()
02240 {
02241   if(This)
02242   {
02243     This->refcount--;
02244     if(This->refcount<=0)
02245       delete This;
02246     This = NULL;
02247   }
02248 }
02249 
02250 
02251 value::value(long long ll)
02252 {
02253   This = new hw::value_i;
02254 
02255   if(This)
02256   {
02257     This->type = integer;
02258     This->ll = ll;
02259     This->refcount = 1;
02260   }
02261 }
02262 
02263 
02264 value::value(const string & s)
02265 {
02266   This = new hw::value_i;
02267 
02268   if(This)
02269   {
02270     This->type = text;
02271     This->s = s;
02272     This->refcount = 1;
02273   }
02274 }
02275 
02276 
02277 value::value(const value & v)
02278 {
02279   This = v.This;
02280 
02281   if(This)
02282   {
02283     This->refcount++;
02284   }
02285 }
02286 
02287 
02288 value & value::operator=(const value & v)
02289 {
02290   if(v.This == This) return *this;
02291 
02292   if(This)
02293   {
02294     This->refcount--;
02295     if(This->refcount<=0)
02296       delete This;
02297   }
02298 
02299   This = v.This;
02300   if(This)
02301     This->refcount++;
02302 
02303   return *this;
02304 }
02305 
02306 
02307 bool value::operator==(const value & v) const
02308 {
02309   if(v.This == This) return true;
02310 
02311   if(!v.This || !This) return false;
02312 
02313   if(v.This->type != This->type) return false;
02314 
02315   switch(This->type)
02316   {
02317     case hw::integer:
02318       return This->ll == v.This->ll;
02319     case hw::text:
02320       return This->s == v.This->s;
02321     case hw::boolean:
02322       return This->b == v.This->b;
02323     case hw::nil:
02324       return true;
02325   };
02326 
02327   return false;
02328 }
02329 
02330 
02331 string value::asString() const
02332 {
02333   if(!This) return "";
02334 
02335   switch(This->type)
02336   {
02337     case hw::integer:
02338       return "0x"+tohex(This->ll);
02339     case hw::text:
02340       return This->s;
02341     case hw::boolean:
02342       return This->b?_("true"):_("false");
02343     case hw::nil:
02344       return _("(nil)");
02345   };
02346 
02347   return "";
02348 }
02349 
02350 
02351 bool value::defined() const
02352 {
02353   if(!This) return false;
02354   if(This->type==nil) return false;
02355 
02356   return true;
02357 }
02358 
02359 bool hwNode::dump(const string & filename, bool recurse)
02360 {
02361 #ifdef SQLITE
02362   try {
02363     sqlite::database db(filename);
02364 
02365     db.execute("BEGIN TRANSACTION");
02366     ::dump(*this, db, "", recurse);
02367     db.execute("COMMIT");
02368   }
02369   catch(exception & e)
02370   {
02371     return false;
02372   }
02373 #else
02374   return false;
02375 #endif
02376 
02377   return true;
02378 }