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 }