Author: stippi Date: 2009-10-18 19:59:07 +0200 (Sun, 18 Oct 2009) New Revision: 33640 Changeset: http://dev.haiku-os.org/changeset/33640/haiku Added: haiku/trunk/src/apps/devices/Device.cpp haiku/trunk/src/apps/devices/Device.h haiku/trunk/src/apps/devices/DevicePCI.cpp haiku/trunk/src/apps/devices/DevicePCI.h haiku/trunk/src/apps/devices/DevicesApplication.cpp haiku/trunk/src/apps/devices/DevicesView.cpp haiku/trunk/src/apps/devices/DevicesView.h haiku/trunk/src/apps/devices/Documentation/ haiku/trunk/src/apps/devices/Documentation/Design.txt haiku/trunk/src/apps/devices/Documentation/Specification.txt haiku/trunk/src/apps/devices/Documentation/Todo.txt haiku/trunk/src/apps/devices/PropertyList.cpp haiku/trunk/src/apps/devices/PropertyList.h haiku/trunk/src/apps/devices/PropertyListPlain.cpp haiku/trunk/src/apps/devices/PropertyListPlain.h haiku/trunk/src/apps/devices/dm_wrapper.c haiku/trunk/src/apps/devices/dm_wrapper.h Removed: haiku/trunk/src/apps/devices/ConfigurationWindow.cpp haiku/trunk/src/apps/devices/Devices.cpp haiku/trunk/src/apps/devices/DevicesInfo.cpp haiku/trunk/src/apps/devices/DevicesInfo.h haiku/trunk/src/apps/devices/DevicesWindow.cpp haiku/trunk/src/apps/devices/DevicesWindows.h haiku/trunk/src/apps/devices/ModemWindow.cpp haiku/trunk/src/apps/devices/cm_wrapper.c haiku/trunk/src/apps/devices/cm_wrapper.h Modified: haiku/trunk/build/jam/HaikuImage haiku/trunk/src/apps/devices/Devices.rdef haiku/trunk/src/apps/devices/Jamfile Log: Patch by Pieter Panman: * Rewrote Devices application. -> Thanks a bunch!! Nice work! * Put Devices onto the image. Changes by myself: * Merge some code from the old "preflet" which the new app still relied on. * Fixed some coding style issues. I didn't review all of the code yet, though. Modified: haiku/trunk/build/jam/HaikuImage =================================================================== --- haiku/trunk/build/jam/HaikuImage 2009-10-18 15:40:39 UTC (rev 33639) +++ haiku/trunk/build/jam/HaikuImage 2009-10-18 17:59:07 UTC (rev 33640) @@ -62,9 +62,9 @@ zdiff zforce zgrep zip zipcloak <bin>zipgrep zipnote zipsplit zmore znew ; -SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc DiskProbe - DiskUsage DriveSetup CDPlayer Expander Icon-O-Matic Installer LaunchBox - Magnify Mail MediaConverter MediaPlayer MidiPlayer NetworkStatus +SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc Devices + DiskProbe DiskUsage DriveSetup CDPlayer Expander Icon-O-Matic Installer + LaunchBox Magnify Mail MediaConverter MediaPlayer MidiPlayer NetworkStatus PackageInstaller People PoorMan PowerStatus ProcessController Screenshot ShowImage SoundRecorder StyledEdit Terminal TextSearch TV Workspaces ; @@ -304,8 +304,8 @@ # Deskbar Application links AddDirectoryToHaikuImage home config be Applications ; DESKBAR_APPLICATIONS = ActivityMonitor CharacterMap CodyCam CDPlayer DeskCalc - DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer Magnify - Mail MediaConverter MediaPlayer MidiPlayer People PoorMan Screenshot + Devices DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer + Magnify Mail MediaConverter MediaPlayer MidiPlayer People PoorMan Screenshot SoundRecorder StyledEdit Terminal TV ; local linkTarget ; Added: haiku/trunk/src/apps/devices/Device.cpp =================================================================== --- haiku/trunk/src/apps/devices/Device.cpp (rev 0) +++ haiku/trunk/src/apps/devices/Device.cpp 2009-10-18 17:59:07 UTC (rev 33640) @@ -0,0 +1,128 @@ +/* + * Copyright 2008-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Pieter Panman + */ + + +#include "Device.h" + +#include <iostream> + + +// This list comes from the pciid list, except for the last one +const char* kCategoryString[] = { + "Unclassified device", // 0x00 + "Mass storage controller", // 0x01 + "Network controller", // 0x02 + "Display controller", // 0x03 + "Multimedia controller", // 0x04 + "Memory controller", // 0x05 + "Bridge", // 0x06 + "Communication controller", // 0x07 + "Generic system peripheral", // 0x08 + "Input device controller", // 0x09 + "Docking station", // 0x0a + "Processor", // 0x0b + "Serial bus controller", // 0x0c + "Wireless controller", // 0x0d + "Intelligent controller", // 0x0e + "Satellite communications controller", // 0x0f + "Encryption controller", // 0x10 + "Signal processing controller", // 0x11 + "Computer" // 0x12 (added later) +}; + + +Device::Device(Device* physicalParent, BusType busType, Category category, + const BString& name, const BString& manufacturer, + const BString& driverUsed, const BString& devPathsPublished) + : + BStringItem(name.String()), + fBusType(busType), + fCategory(category), + fPhysicalParent(physicalParent) +{ + SetAttribute("Device name", name); + SetAttribute("Manufacturer", manufacturer); + SetAttribute("Driver used", driverUsed); + SetAttribute("Device paths", devPathsPublished); +} + + +Device::~Device() +{ +} + + +void +Device::SetAttribute(const BString& name, const BString& value) +{ + if (name == "Device name") { + SetText(value.String()); + } + fAttributeMap[name] = value; +} + + +Attributes +Device::GetBasicAttributes() +{ + Attributes attributes; + attributes.push_back(Attribute("Device name:", GetName())); + attributes.push_back(Attribute("Manufacturer:", GetManufacturer())); + return attributes; +} + + +Attributes +Device::GetBusAttributes() +{ + Attributes attributes; + attributes.push_back(Attribute("None", "")); + return attributes; +} + + +Attributes +Device::GetAllAttributes() +{ + Attributes attributes; + AttributeMapIterator iter; + for (iter = fAttributeMap.begin(); iter != fAttributeMap.end(); iter++) { + attributes.push_back(Attribute(iter->first, iter->second)); + } + return attributes; +} + + +BString +Device::GetBasicStrings() +{ + BString str; + str << "Device Name\t\t\t\t: " << GetName() << "\n"; + str << "Manufacturer\t\t\t: " << GetManufacturer() << "\n"; + str << "Driver used\t\t\t\t: " << GetDriverUsed() << "\n"; + str << "Device paths\t: " << GetDevPathsPublished(); + return str; +} + +BString +Device::GetBusStrings() +{ + return "None"; +} + + +BString +Device::GetAllStrings() +{ + BString str; + AttributeMapIterator iter; + for (iter = fAttributeMap.begin(); iter != fAttributeMap.end(); iter++) { + str << iter->first << " : " << iter->second << "\n"; + } + return str; +} Added: haiku/trunk/src/apps/devices/Device.h =================================================================== --- haiku/trunk/src/apps/devices/Device.h (rev 0) +++ haiku/trunk/src/apps/devices/Device.h 2009-10-18 17:59:07 UTC (rev 33640) @@ -0,0 +1,109 @@ +/* + * Copyright 2008-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Pieter Panman + */ +#ifndef DEVICE_H +#define DEVICE_H + + +#include <map> +#include <vector> + +#include <String.h> +#include <StringItem.h> + +extern "C" { +#include "dm_wrapper.h" +} + + +typedef enum { + BUS_ISA = 1, + BUS_PCI, + BUS_SCSI, + BUS_NONE +} BusType; + + +struct Attribute { + Attribute(BString name, BString value) + { fName = name; fValue = value; } + BString fName; + BString fValue; +}; + + +typedef std::map<BString, BString>::const_iterator AttributeMapIterator; +typedef std::map<BString, BString> AttributeMap; +typedef std::pair<BString, BString> AttributePair; +typedef std::vector<Attribute> Attributes; + + +typedef enum { + CAT_NONE = 0, + CAT_BUS = 6, + CAT_COMPUTER = 0x12 +} Category; + + +extern const char* kCategoryString[]; + + +class Device : public BStringItem { +public: + Device(Device* physicalParent, + BusType busType=BUS_NONE, + Category category=CAT_NONE, + const BString& name = "unknown", + const BString& manufacturer = "unknown", + const BString& driverUsed = "unknown", + const BString& devPathsPublished = "unknown"); + virtual ~Device(); + + virtual BString GetName() + { return fAttributeMap["Device name"]; } + virtual BString GetManufacturer() + { return fAttributeMap["Manufacturer"]; } + virtual BString GetDriverUsed() + { return fAttributeMap["Driver used"]; } + virtual BString GetDevPathsPublished() + { return fAttributeMap["Device paths"]; } + virtual Category GetCategory() const + { return fCategory; } + virtual Device* GetPhysicalParent() const + { return fPhysicalParent; } + virtual BusType GetBusType() const + { return fBusType; } + + virtual Attributes GetBasicAttributes(); + virtual Attributes GetBusAttributes(); + virtual Attributes GetAllAttributes(); + + virtual BString GetBasicStrings(); + virtual BString GetBusStrings(); + virtual BString GetAllStrings(); + + virtual BString GetBusTabName() + { return "Bus Information"; } + + virtual Attribute GetAttribute(const BString& name) + { return Attribute(name.String(), + fAttributeMap[name]); } + + virtual void SetAttribute(const BString& name, + const BString& value); + + virtual void InitFromAttributes() { return; } + +protected: + AttributeMap fAttributeMap; + BusType fBusType; + Category fCategory; + Device* fPhysicalParent; +}; + +#endif /* DEVICE_H */ + Added: haiku/trunk/src/apps/devices/DevicePCI.cpp =================================================================== --- haiku/trunk/src/apps/devices/DevicePCI.cpp (rev 0) +++ haiku/trunk/src/apps/devices/DevicePCI.cpp 2009-10-18 17:59:07 UTC (rev 33640) @@ -0,0 +1,127 @@ +/* + * Copyright 2008-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Pieter Panman + */ + + +#include <sstream> + +#include "DevicePCI.h" + +extern "C" { +#include "dm_wrapper.h" +#include "pcihdr.h" +#include "pci-utils.h" +} + + +DevicePCI::DevicePCI(Device* parent) + : + Device(parent), + fClassBaseId(0), + fClassSubId(0), + fClassApiId(0), + fVendorId(0), + fDeviceId(0), + fSubsystemVendorId(0), + fSubSystemId(0) +{ +} + + +DevicePCI::~DevicePCI() +{ +} + + +BString ToHex(uint16 num) +{ + std::stringstream ss; + ss.flags(std::ios::hex | std::ios::showbase); + ss << num; + return BString(ss.str().c_str()); +} + + +void +DevicePCI::InitFromAttributes() +{ + // Process the attributes + fClassBaseId = atoi(fAttributeMap[B_DEVICE_TYPE].String()); + fClassSubId = atoi(fAttributeMap[B_DEVICE_SUB_TYPE].String()); + fClassApiId = atoi(fAttributeMap[B_DEVICE_INTERFACE].String()); + fVendorId = atoi(fAttributeMap[B_DEVICE_VENDOR_ID].String()); + fDeviceId = atoi(fAttributeMap[B_DEVICE_ID].String()); + + // Looks better in Hex, so rewrite + fAttributeMap[B_DEVICE_TYPE] = ToHex(fClassBaseId); + fAttributeMap[B_DEVICE_SUB_TYPE] = ToHex(fClassSubId); + fAttributeMap[B_DEVICE_INTERFACE] = ToHex(fClassApiId); + fAttributeMap[B_DEVICE_VENDOR_ID] = ToHex(fVendorId); + fAttributeMap[B_DEVICE_ID] = ToHex(fDeviceId); + + // Fetch ClassInfo + char classInfo[64]; + get_class_info(fClassBaseId, fClassSubId, fClassApiId, classInfo, sizeof(classInfo)); + + // Fetch ManufacturerName + BString ManufacturerName; + const char *venShort; + const char *venFull; + get_vendor_info(fVendorId, &venShort, &venFull); + if (!venShort && !venFull) { + ManufacturerName << "Unkown"; + } else if (venShort && venFull) { + ManufacturerName << venFull << "(" << venShort << ")"; + } else { + ManufacturerName << (venShort ? venShort : venFull); + } + + // Fetch DeviceName + BString DeviceName; + const char *devShort; + const char *devFull; + get_device_info(fVendorId, fDeviceId, fSubsystemVendorId, fSubSystemId, &devShort, &devFull); + if (!devShort && !devFull) { + DeviceName << "Unknown"; + } else if (devShort && devFull) { + DeviceName << devFull << "(" << devShort << ")"; + } else { + DeviceName << (devShort ? devShort : devFull); + } + + SetAttribute("Device name", DeviceName); + SetAttribute("Manufacturer", ManufacturerName); + SetAttribute("Driver used", "Not implemented"); + SetAttribute("Device paths", "Not implemented"); + SetAttribute("Class Info", classInfo); + fCategory = (Category)fClassBaseId; + BString outlineName; + outlineName << ManufacturerName << " " << DeviceName; + SetText(outlineName.String()); +} + + +Attributes +DevicePCI::GetBusAttributes() +{ + Attributes attributes; + attributes.push_back(GetAttribute(B_DEVICE_TYPE)); + attributes.push_back(GetAttribute(B_DEVICE_SUB_TYPE)); + attributes.push_back(GetAttribute(B_DEVICE_INTERFACE)); + attributes.push_back(GetAttribute(B_DEVICE_VENDOR_ID)); + attributes.push_back(GetAttribute(B_DEVICE_ID)); + return attributes; +} + + +BString +DevicePCI::GetBusStrings() +{ + BString str; + str << "Class Info:\t\t\t\t: " << fAttributeMap["Class Info"]; + return str; +} Added: haiku/trunk/src/apps/devices/DevicePCI.h =================================================================== --- haiku/trunk/src/apps/devices/DevicePCI.h (rev 0) +++ haiku/trunk/src/apps/devices/DevicePCI.h 2009-10-18 17:59:07 UTC (rev 33640) @@ -0,0 +1,36 @@ +/* + * Copyright 2008-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Pieter Panman + */ +#ifndef DEVICEPCI_H +#define DEVICEPCI_H + + +#include "Device.h" + + +class DevicePCI : public Device { +public: + DevicePCI(Device* parent); + virtual ~DevicePCI(); + virtual Attributes GetBusAttributes(); + virtual BString GetBusStrings(); + virtual void InitFromAttributes(); + + virtual BString GetBusTabName() + { return "PCI Information"; } + +private: + uint16 fClassBaseId; + uint16 fClassSubId; + uint16 fClassApiId; + uint16 fVendorId; + uint16 fDeviceId; + uint16 fSubsystemVendorId; + uint16 fSubSystemId; +}; + +#endif /* DEVICEPCI_H */ Modified: haiku/trunk/src/apps/devices/Devices.rdef =================================================================== --- haiku/trunk/src/apps/devices/Devices.rdef 2009-10-18 15:40:39 UTC (rev 33639) +++ haiku/trunk/src/apps/devices/Devices.rdef 2009-10-18 17:59:07 UTC (rev 33640) @@ -1,5 +1,5 @@ -resource app_signature "application/x-vnd.Haiku.Devices"; +resource app_signature "application/x-vnd.Haiku-Devices"; resource app_version { @@ -9,12 +9,12 @@ /* 0 = development 1 = alpha 2 = beta 3 = gamma 4 = golden master 5 = final */ - variety = 2, + variety = 1, internal = 0, short_info = "Devices", - long_info = "Devices ©2002-2009 Haiku" + long_info = "Devices ©2009 Haiku" }; resource app_flags B_SINGLE_LAUNCH; Added: haiku/trunk/src/apps/devices/DevicesApplication.cpp =================================================================== --- haiku/trunk/src/apps/devices/DevicesApplication.cpp (rev 0) +++ haiku/trunk/src/apps/devices/DevicesApplication.cpp 2009-10-18 17:59:07 UTC (rev 33640) @@ -0,0 +1,119 @@ +/* + * Copyright 2008-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * Pieter Panman + */ + +#include <Alert.h> +#include <Application.h> +#include <TextView.h> + +#include "DevicesView.h" + + +class DevicesApplication : public BApplication { +public: + DevicesApplication(); + virtual void AboutRequested(); + static void ShowAbout(); +}; + + +class DevicesWindow : public BWindow { +public: + DevicesWindow(); + virtual void MessageReceived(BMessage* message); +private: + DevicesView* fDevicesView; +}; + + +DevicesApplication::DevicesApplication() + : + BApplication("application/x-vnd.Haiku-Devices") +{ + DevicesWindow* window = new DevicesWindow(); + window->CenterOnScreen(); + window->Show(); +} + + +void +DevicesApplication::AboutRequested() +{ + ShowAbout(); +} + + +void +DevicesApplication::ShowAbout() +{ + BAlert* alert = new BAlert("about", "Devices\n" + "\twritten by Pieter Panman\n" + "\n" + "\tBased on listdev by Jérôme Duval\n" + "\tand the previous Devices preference\n" + "\tby Jérôme Duval and Sikosis\n" + "\tCopyright 2009, Haiku Inc.\n", "Ok"); + BTextView* view = alert->TextView(); + BFont font; + + view->SetStylable(true); + + view->GetFont(&font); + font.SetSize(18); + font.SetFace(B_BOLD_FACE); + view->SetFontAndColor(0, 7, &font); + + alert->Go(); +} + + +DevicesWindow::DevicesWindow() + : + BWindow(BRect(50, 50, 750, 550), "Devices", B_TITLED_WINDOW, + B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS + | B_QUIT_ON_WINDOW_CLOSE) +{ + float minWidth; + float maxWidth; + float minHeight; + float maxHeight; + GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); + minWidth = 600; + minHeight = 300; + SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight); + fDevicesView = new DevicesView(Bounds()); + AddChild(fDevicesView); +} + + +void +DevicesWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgRefresh: + case kMsgReportCompatibility: + case kMsgGenerateSysInfo: + case kMsgSelectionChanged: + case kMsgOrderCategory: + case kMsgOrderConnection: + fDevicesView->MessageReceived(message); + break; + + default: + BWindow::MessageReceived(message); + break; + } +} + + +int +main() +{ + DevicesApplication app; + app.Run(); + return 0; +} Added: haiku/trunk/src/apps/devices/DevicesView.cpp =================================================================== --- haiku/trunk/src/apps/devices/DevicesView.cpp (rev 0) +++ haiku/trunk/src/apps/devices/DevicesView.cpp 2009-10-18 17:59:07 UTC (rev 33640) @@ -0,0 +1,392 @@ +/* + * Copyright 2008-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * Pieter Panman + */ + + +#include <Application.h> +#include <MenuBar.h> + +#include "DevicesView.h" + + +DevicesView::DevicesView(const BRect& rect) + : BView(rect, "DevicesView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS) +{ + CreateLayout(); + RescanDevices(); + RebuildDevicesOutline(); +} + + +void +DevicesView::CreateLayout() +{ + SetLayout(new BGroupLayout(B_VERTICAL)); + + BMenuBar* menuBar = new BMenuBar("menu"); + BMenu* menu = new BMenu("Devices"); + BMenuItem* item; + menu->AddItem(new BMenuItem("Refresh Devices", new BMessage(kMsgRefresh), 'R')); + menu->AddItem(item = new BMenuItem("Report Compatibility", + new BMessage(kMsgReportCompatibility))); + item->SetEnabled(false); + menu->AddItem(item = new BMenuItem("Generate System Information", + new BMessage(kMsgGenerateSysInfo))); + item->SetEnabled(false); + menu->AddSeparatorItem(); + menu->AddItem(item = new BMenuItem("About Devices" B_UTF8_ELLIPSIS, + new BMessage(B_ABOUT_REQUESTED))); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q')); + menu->SetTargetForItems(this); + item->SetTarget(be_app); + menuBar->AddItem(menu); + + fDevicesOutline = new BOutlineListView("devices_list"); + fDevicesOutline->SetTarget(this); + fDevicesOutline->SetSelectionMessage(new BMessage(kMsgSelectionChanged)); + + BScrollView *scrollView = new BScrollView("devicesScrollView", + fDevicesOutline, B_WILL_DRAW | B_FRAME_EVENTS, true, true); + // Horizontal scrollbar doesn't behave properly like the vertical + // scrollbar... If you make the view bigger (exposing a larger percentage + // of the view), it does not adjust the width of the scroll 'dragger' + // why? Bug? In scrollview or in outlinelistview? + + BPopUpMenu* orderByPopupMenu = new BPopUpMenu("orderByMenu"); + BMenuItem* byCategory = new BMenuItem("category", + new BMessage(kMsgOrderCategory)); + BMenuItem* byConnection = new BMenuItem("connection", + new BMessage(kMsgOrderConnection)); + byCategory->SetMarked(true); + fOrderBy = byCategory->IsMarked() ? ORDER_BY_CATEGORY : + ORDER_BY_CONNECTION; + orderByPopupMenu->AddItem(byCategory); + orderByPopupMenu->AddItem(byConnection); + fOrderByMenu = new BMenuField("Order by:", orderByPopupMenu); + + fTabView = new BTabView("fTabView", B_WIDTH_FROM_LABEL); + + fBasicTab = new BTab(); + fBasicView = new PropertyListPlain("basicView"); + fTabView->AddTab(fBasicView, fBasicTab); + fBasicTab->SetLabel("Basic Information"); + + fDeviceTypeTab = new BTab(); + fBusView = new PropertyListPlain("busView"); + fTabView->AddTab(fBusView, fDeviceTypeTab); + fDeviceTypeTab->SetLabel("Bus"); + + fDetailedTab = new BTab(); + fAttributesView = new PropertyList("attributesView"); + fTabView->AddTab(fAttributesView, fDetailedTab); + fDetailedTab->SetLabel("Detailed"); + + AddChild(BGroupLayoutBuilder(B_VERTICAL,0) + .Add(menuBar) + .Add(BSplitLayoutBuilder(B_HORIZONTAL, 5) + .Add(BGroupLayoutBuilder(B_VERTICAL, 5) + .Add(fOrderByMenu, 1) + .Add(scrollView, 2) + ) + .Add(fTabView, 2) + .SetInsets(5, 5, 5, 5) + ) + ); +} + + +void +DevicesView::RescanDevices() +{ + // Empty the outline and delete the devices in the list, incl. categories + fDevicesOutline->MakeEmpty(); + DeleteDevices(); + DeleteCategoryMap(); + + // Fill the devices list + status_t error; + device_node_cookie rootCookie; + if ((error = init_dm_wrapper()) < 0) { + std::cerr << "Error initializing device manager: " << strerror(error) + << std::endl; + return; + } + + get_root(&rootCookie); + AddDeviceAndChildren(&rootCookie, NULL); + + uninit_dm_wrapper(); + + CreateCategoryMap(); +} + + +void +DevicesView::DeleteDevices() +{ + while(fDevices.size() > 0) { + delete fDevices.back(); + fDevices.pop_back(); + } +} + + +void +DevicesView::CreateCategoryMap() +{ + CategoryMapIterator iter; + for (unsigned int i = 0; i < fDevices.size(); i++) { + Category category = fDevices[i]->GetCategory(); + const char* categoryName = kCategoryString[category]; + + iter = fCategoryMap.find(category); + if( iter == fCategoryMap.end() ) { + // This category has not yet been added, add it. + fCategoryMap[category] = new Device(NULL, BUS_NONE, CAT_NONE, + categoryName); + } + } +} + + +void +DevicesView::DeleteCategoryMap() +{ + CategoryMapIterator iter; + for(iter = fCategoryMap.begin(); iter != fCategoryMap.end(); iter++) { + delete iter->second; + } + fCategoryMap.clear(); +} + + +int +DevicesView::SortItemsCompare(const BListItem *item1, + const BListItem *item2) +{ + const BStringItem* stringItem1 = dynamic_cast<const BStringItem*>(item1); + const BStringItem* stringItem2 = dynamic_cast<const BStringItem*>(item2); + if (!(stringItem1 && stringItem2)) { + // is this check necessary? + std::cerr << "Could not cast BListItem to BStringItem, file a bug\n"; + return 0; + } + return Compare(stringItem1->Text(),stringItem2->Text()); +} + + +void +DevicesView::RebuildDevicesOutline() +{ + // Rearranges existing Devices into the proper hierarchy + fDevicesOutline->MakeEmpty(); + + if (fOrderBy == ORDER_BY_CONNECTION) { + for (unsigned int i = 0; i < fDevices.size(); i++) { + if (fDevices[i]->GetPhysicalParent() == NULL) { + // process each parent device and its children + fDevicesOutline->AddItem(fDevices[i]); + AddChildrenToOutlineByConnection(fDevices[i]); + } + } + } + else if (fOrderBy == ORDER_BY_CATEGORY) { + // Add all categories to the outline + CategoryMapIterator iter; + for (iter = fCategoryMap.begin(); iter != fCategoryMap.end(); iter++) { + fDevicesOutline->AddItem(iter->second); + } + + // Add all devices under the categories + for (unsigned int i = 0; i < fDevices.size(); i++) { + Category category = fDevices[i]->GetCategory(); + + iter = fCategoryMap.find(category); + if(iter == fCategoryMap.end()) { + std::cerr << "Tried to add device without category, file a bug\n"; + continue; + } + else { + fDevicesOutline->AddUnder(fDevices[i], iter->second); + } + } + fDevicesOutline->SortItemsUnder(NULL, true, SortItemsCompare); + } + // TODO: Implement BY_BUS +} + + +void +DevicesView::AddChildrenToOutlineByConnection(Device* parent) +{ + for (unsigned int i = 0; i < fDevices.size(); i++) { + if (fDevices[i]->GetPhysicalParent() == parent) { + fDevicesOutline->AddUnder(fDevices[i], parent); + AddChildrenToOutlineByConnection(fDevices[i]); + } + } +} + + +void +DevicesView::AddDeviceAndChildren(device_node_cookie *node, Device* parent) +{ + Attributes attributes; + Device* newDevice = NULL; + + // Copy all its attributes, + // necessary because we can only request them once from the device manager + char data[256]; + struct device_attr_info attr; + attr.cookie = 0; + attr.node_cookie = *node; + attr.value.raw.data = data; + attr.value.raw.length = sizeof(data); + + while (dm_get_next_attr(&attr) == B_OK) { + BString attrString; + switch (attr.type) { + case B_STRING_TYPE: + attrString << attr.value.string; + break; + case B_UINT8_TYPE: + attrString << attr.value.ui8; + break; + case B_UINT16_TYPE: + attrString << attr.value.ui16; + break; + case B_UINT32_TYPE: + attrString << attr.value.ui32; + break; + case B_UINT64_TYPE: + attrString << attr.value.ui64; + break; + default: + attrString << "Raw data"; + } + attributes.push_back(Attribute(attr.name, attrString)); + } + + // Determine what type of device it is and create it + for (unsigned int i = 0; i < attributes.size(); i++) { + // Devices Root + if (attributes[i].fName == "device/pretty name" + && attributes[i].fValue == "Devices Root") { + newDevice = new Device(parent, BUS_NONE, CAT_COMPUTER, "Computer"); + break; + } + + // PCI bus + if (attributes[i].fName == "device/pretty name" + && attributes[i].fValue == "PCI") { + newDevice = new Device(parent, BUS_PCI, CAT_BUS, "PCI Bus"); + break; + } + + // ISA bus + if (attributes[i].fName == "device/bus" + && attributes[i].fValue == "isa") { + newDevice = new Device(parent, BUS_ISA, CAT_BUS, "ISA Bus"); + break; + } + + // PCI device + if (attributes[i].fName == B_DEVICE_BUS + && attributes[i].fValue == "pci") { + newDevice = new DevicePCI(parent); + break; + } + } + + if (newDevice == NULL) { + newDevice = new Device(parent, BUS_NONE, CAT_NONE, "Unknown Device"); + } + + // Add its attributes to the device, initialize it and add to the list. + for (unsigned int i = 0; i < attributes.size(); i++) { + newDevice->SetAttribute(attributes[i].fName, attributes[i].fValue); + } + newDevice->InitFromAttributes(); + fDevices.push_back(newDevice); + + // Process children + status_t err; + device_node_cookie child = *node; + + if (get_child(&child) != B_OK) + return; + + do { + AddDeviceAndChildren(&child, newDevice); + } while ((err = get_next_child(&child)) == B_OK); +} + + +DevicesView::~DevicesView() +{ + DeleteDevices(); +} + + +void +DevicesView::MessageReceived(BMessage *msg) +{ + switch (msg->what) { + case kMsgSelectionChanged: + { + int32 selected = fDevicesOutline->CurrentSelection(0); + if (selected >= 0) { + Device* device = (Device*)fDevicesOutline->ItemAt(selected); + fBasicView->AddAttributes(device->GetBasicAttributes()); + fBusView->AddAttributes(device->GetBusAttributes()); + fAttributesView->AddAttributes(device->GetAllAttributes()); + fDeviceTypeTab->SetLabel(device->GetBusTabName()); + // hmm the label doesn't automatically refresh + fTabView->Invalidate(); + } + break; + } + + case kMsgOrderCategory: + { + fOrderBy = ORDER_BY_CATEGORY; + RescanDevices(); + RebuildDevicesOutline(); + break; + } + + case kMsgOrderConnection: + { + fOrderBy = ORDER_BY_CONNECTION; + RescanDevices(); + RebuildDevicesOutline(); + break; + } + + case kMsgRefresh: + { + RescanDevices(); + RebuildDevicesOutline(); + break; + } + + case kMsgReportCompatibility: + { + break; + } + + case kMsgGenerateSysInfo: + { + break; + } + + default: + BView::MessageReceived(msg); + break; [... truncated: 774 lines follow ...]