summaryrefslogtreecommitdiff
path: root/usb/usbview/xmlhelper.cpp
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /usb/usbview/xmlhelper.cpp
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'usb/usbview/xmlhelper.cpp')
-rw-r--r--usb/usbview/xmlhelper.cpp3058
1 files changed, 3058 insertions, 0 deletions
diff --git a/usb/usbview/xmlhelper.cpp b/usb/usbview/xmlhelper.cpp
new file mode 100644
index 00000000..4221aeb0
--- /dev/null
+++ b/usb/usbview/xmlhelper.cpp
@@ -0,0 +1,3058 @@
+/*++
+
+ Copyright (c) 1997-2011 Microsoft Corporation
+
+ Module Name:
+
+ XMLHELPER.CPP
+
+Abstract:
+
+This source file contains helper APIs for reading writing XML
+
+Environment:
+
+user mode
+
+Revision History:
+
+05-05-11 : created
+
+--*/
+
+/*****************************************************************************
+ I N C L U D E S
+ *****************************************************************************/
+#include "uvcview.h"
+#include "h264.h"
+#include "xmlhelper.h"
+
+// usbschema.hpp is autogenerated from schema during build PASS0
+#include "usbschema.hpp"
+
+// Include code analysis suppressions
+#include "codeanalysis.h"
+
+/*****************************************************************************
+ D E F I N E S
+ *****************************************************************************/
+#define COBJMACROS
+
+#define PACHAR_TO_STRING(X) ((X != NULL)? gcnew String(Marshal::PtrToStringAnsi((IntPtr) X )):nullptr)
+#define PWCHAR_TO_STRING(X) ((X != NULL)? gcnew String(Marshal::PtrToStringUni((IntPtr) X )):nullptr)
+
+#define MAX_STRING_DESCRIPTOR_LENGTH 512
+#define STRING_DESCRIPTOR_EN_LANGUAGE_ID 0x0409
+#define DEVICE_DESCRIPTOR_LENGTH 18
+
+#define SERVICE_EHCI "usbehci"
+#define SERVICE_XHCI "usbxhci"
+#define SERVICE_OHCI "usbohci"
+#define SERVICE_UHCI "usbuhci"
+
+#define USB_1_1 "USB 1.1"
+#define USB_2_0 "USB 2.0"
+#define USB_3_0 "USB 3.0"
+#define USB_GENERIC "USB GENERIC (UNKNOWN)"
+
+/*****************************************************************************
+ N A M E S P A C E S
+ *****************************************************************************/
+
+using namespace System;
+using namespace System::IO;
+using namespace System::Runtime::InteropServices;
+using namespace System::Collections;
+using namespace Microsoft::Kits::Samples::Usb;
+
+
+/*****************************************************************************
+ G L O B A L S
+ *****************************************************************************/
+
+namespace Microsoft
+{
+ namespace Kits
+ {
+ namespace Samples
+ {
+ namespace Usb
+ {
+ public ref class XmlGlobal sealed
+ {
+ private:
+ static XmlGlobal ^ pInstance = gcnew XmlGlobal();
+
+ // Empty private constructor
+ XmlGlobal()
+ {
+ }
+
+ public:
+ //
+ // Globals for XML view
+ //
+ property UvcViewAll ^ ViewAll;
+ property bool XmlViewInitialized;
+
+ //
+ // Stack of parents of a given node. This is used for finding
+ // where a given object should be added
+ //
+
+#if CODE_ANALYSIS
+ // ParentStack need not be constant since we will only have one instance of this object
+ [SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible")]
+#endif
+ static Stack ^ ParentStack = gcnew Stack();
+
+ static XmlGlobal ^ Instance()
+ {
+ return pInstance;
+ }
+ };
+ };
+ };
+ };
+};
+
+#define gXmlView ((XmlGlobal::Instance())->ViewAll->UvcView)
+#define gXmlViewInitialized ((XmlGlobal::Instance())->XmlViewInitialized)
+#define gXmlStack ((XmlGlobal::Instance())->ParentStack)
+
+/*****************************************************************************
+ D E C L A R A T I O N S
+ *****************************************************************************/
+
+String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly);
+void XmlAddHostControllerPowerMapping( UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo);
+String ^ XmlGetDeviceClassString(UCHAR deviceClass);
+void XmlAddHostControllerPowerMapping(UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo);
+void XmlAddHub30Descriptor(Hub30DescriptorType ^hub30Desc, PUSB_30_HUB_DESCRIPTOR hub30Descriptor);
+void XmlAddHubDescriptor(HubDescriptorType ^hubDesc, PUSB_HUB_DESCRIPTOR hubDescriptor);
+void XmlAddPortConnectorProps(PortConnectorType ^portXmlProps, PUSB_PORT_CONNECTOR_PROPERTIES portProps);
+void XmlAddHubCharacteristics(HubInformationType ^hubI, WORD hubChar);
+HRESULT XmlAddHubNodeInformation(HubNodeInformationType ^ni, PUSB_NODE_INFORMATION nodeInfo);
+HRESULT XmlAddHubInformationEx(HubInformationExType ^ex, PUSB_HUB_INFORMATION_EX hubInfoEx);
+HRESULT XmlAddHubCapabilitiesEx(HubCapabilitiesExType ^ex, USB_HUB_CAPABILITIES_EX hubCapEx);
+ExternalHubType ^ AddExternalHub(Object ^parent);
+NoDeviceType ^ AddDisconnectedPort(Object ^parent);
+UsbDeviceType ^ AddUsbDevice(Object ^parent);
+void XmlAddEndpointDescriptor(
+ EndpointDescriptorType ^usbXmlEndpointDescriptor,
+ PUSB_ENDPOINT_DESCRIPTOR endPointDescriptor,
+ UCHAR connectionSpeed);
+void XmlAddPipeInformation(
+ array< UsbPipeInfoType ^> ^ usbXmlPipeInfoList,
+ PUSB_PIPE_INFO pipeInfo,
+ ULONG numPipes,
+ UCHAR connectionSpeed);
+void XmlAddUsbDeviceDescriptor(
+ UsbDeviceDescriptorType ^usbXmlDeviceDescriptor,
+ PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor);
+void XmlAddConfigurationDescriptor(
+ UsbConfigurationDescriptorType ^ confXmlDesc,
+ PUSBDEVICEINFO deviceInfo,
+ PUSB_CONFIGURATION_DESCRIPTOR configDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc);
+void XmlAddDeviceQualDescriptor(
+ UsbDeviceQualifierDescriptorType ^ qualXmlDesc,
+ PUSB_DEVICE_QUALIFIER_DESCRIPTOR qualDesc);
+void XmlAddDeviceConfiguration(
+ UsbDeviceConfigurationType ^ confXmlDesc,
+ PUSBDEVICEINFO deviceInfo,
+ PUSB_CONFIGURATION_DESCRIPTOR configDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc,
+ int numInterfaces);
+void XmlAddConnectionInfoSt(
+ NodeConnectionInfoExStructType ^xmlConnectionInfoSt,
+ PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo,
+ PDEVICE_INFO_NODE pNode);
+String ^ XmlGetLangIdString(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc);
+String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly);
+String ^ XmlGetDeviceClassString(UCHAR deviceClass);
+bool XmlAddDeviceClassDetails(
+ UsbDeviceClassDetailsType ^ deviceDetails,
+ PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo,
+ PUSBDEVICEINFO deviceInfo);
+void XmlAddConnectionInfo(
+ NodeConnectionInfoExType ^xmlConnectionInfo,
+ PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo,
+ PUSBDEVICEINFO deviceInfo,
+ PSTRING_DESCRIPTOR_NODE stringDesc,
+ PDEVICE_INFO_NODE pNode);
+void XmlAddHidDescriptor(
+ UsbDeviceHidDescriptorType ^ hidXmlDesc,
+ PUSB_HID_DESCRIPTOR hidDesc);
+void XmlAddDeviceInterfaceDescriptor(
+ UsbDeviceInterfaceDescriptorType ^ ifXmlDesc,
+ PUSB_INTERFACE_DESCRIPTOR ifDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc);
+void XmlAddOTGDescriptor(
+ UsbDeviceOTGDescriptorType ^ otgXmlDesc,
+ PUSB_OTG_DESCRIPTOR otgDesc);
+void XmlAddIADDescriptor(
+ UsbDeviceIADDescriptorType ^ iadXmlDesc,
+ PUSB_IAD_DESCRIPTOR iadDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc,
+ int nInterfaces);
+array < UsbDeviceConfigurationType ^> ^ XmlGetConfigDescriptors(
+ PUSBDEVICEINFO deviceInfo,
+ PUSB_CONFIGURATION_DESCRIPTOR configDescs,
+ PSTRING_DESCRIPTOR_NODE stringDesc);
+UsbBosDescriptorType ^ XmlGetBosDescriptor(PUSB_BOS_DESCRIPTOR bosDesc);
+UsbDeviceClassType ^ XmlGetDeviceClass(UCHAR deviceClass, UCHAR deviceSubClass, UCHAR deviceProtocol);
+UsbDeviceUnknownDescriptorType ^ XmlGetUnknownDescriptor(
+ PUSB_COMMON_DESCRIPTOR unknownDesc
+ );
+UsbUsb20ExtensionDescriptorType ^ XmlGetUsb20CapabilityExtensionDescriptor(
+ PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR capDesc
+ );
+UsbSuperSpeedExtensionDescriptorType ^ XmlGetSuperSpeedCapabilityExtensionDescriptor(
+ PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR capDesc
+ );
+UsbDispContIdCapExtDescriptorType ^ XmlGetContainerIdCapabilityExtensionDescriptor(
+ PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR capDesc
+ );
+
+/*****************************************************************************
+ D E F I N I T I O N S
+ *****************************************************************************/
+
+/*****************************************************************************
+ XmlNotifyEndOfNodeList
+
+ This function is called back by WalkTreeTopDown() function to notify us
+ that there are no more children to add for the current parent
+
+ *****************************************************************************/
+VOID XmlNotifyEndOfNodeList(PVOID pContext)
+{
+ UNREFERENCED_PARAMETER(pContext);
+
+ if (gXmlStack != nullptr && gXmlStack->Count > 0)
+ {
+ // Remove the last parent on the stack
+ gXmlStack->Pop();
+ }
+}
+
+/*****************************************************************************
+
+ XmlAddHostControllerPowerMapping()
+
+ add power info to xml structure
+ *****************************************************************************/
+void XmlAddHostControllerPowerMapping(UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo)
+{
+ int i, powerState;
+ PUSB_POWER_INFO pUPI = usbHCPowerInfo;
+ UsbHCPowerStateType ^ pwrState = nullptr;
+
+ xmlPwrInfo->PowerMap = gcnew array<UsbHCPowerStateType ^> (WdmUsbPowerSystemShutdown);
+
+ for(i = 0, powerState = WdmUsbPowerSystemWorking; powerState < WdmUsbPowerSystemShutdown; i++, powerState++, pUPI++)
+ {
+ xmlPwrInfo->PowerMap[i] = gcnew UsbHCPowerStateType();
+ pwrState = xmlPwrInfo->PowerMap[i];
+ pwrState->SystemState = PACHAR_TO_STRING(GetPowerStateString(pUPI->SystemState));
+ pwrState->HostControllerState = PACHAR_TO_STRING(GetPowerStateString(pUPI->HcDevicePowerState));
+ pwrState->HubState = PACHAR_TO_STRING(GetPowerStateString(pUPI->RhDevicePowerState));
+ pwrState->CanWakeUp = pUPI->CanWakeup? true:false;
+ pwrState->IsPowered = pUPI->IsPowered? true:false;
+ }
+
+ xmlPwrInfo->LastSleepState = PACHAR_TO_STRING(GetPowerStateString(pUPI->LastSystemSleepState));
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddHostController()
+
+ Add an host controller to XML view
+ *****************************************************************************/
+
+HRESULT XmlAddHostController(PSTR hcName, PUSBHOSTCONTROLLERINFO hcInfo)
+{
+ HRESULT hr = S_OK;
+
+ UNREFERENCED_PARAMETER(hcName);
+
+ HostControllerType ^ hc = nullptr;
+ //
+ // Check if the USB Tree array has been initialized
+ // It would have been great if XSD had a way of generating a list instead of array, but it does not
+ // So we have to do array.Resize everytime
+ //
+ if (gXmlView->UsbTree == nullptr)
+ {
+ // This is the first time we are being called, initialize the array with 1 element
+ gXmlView->UsbTree = gcnew array<HostControllerType ^>(1);
+ gXmlView->UsbTree[0] = gcnew HostControllerType();
+ hc = gXmlView->UsbTree[0];
+ }
+ else
+ {
+ // Create a new array every time as Array.Resize does not seem to work in our case (CLI)
+ // We do this using ArrayList.
+ ArrayList ^hcList = gcnew ArrayList;
+ hcList->AddRange(gXmlView->UsbTree);
+ hc = gcnew HostControllerType();
+ hcList->Add(hc);
+ gXmlView->UsbTree = reinterpret_cast<array<HostControllerType ^>^> (hcList->ToArray(HostControllerType::typeid));
+ }
+
+ if (hc != nullptr)
+ {
+ ULONG debugPort = 0;
+
+ UsbHCDeviceInfoType ^ ci = nullptr;
+ UsbHCPowerStateMappingType ^ pm = nullptr;
+
+ if (NULL != hcInfo->UsbDeviceProperties)
+ {
+ hc->HwId = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->HwId);
+ hc->DeviceId = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceId);
+ hc->ServiceName = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->Service);
+ hc->DeviceName = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceDesc);
+ hc->DeviceClass = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceClass);
+
+ if (_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_OHCI) == 0)
+ {
+ hc->UsbProtocol = gcnew String(USB_1_1);
+ }
+ else if(_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_EHCI) == 0 ||
+ _stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_UHCI) == 0)
+ {
+ hc->UsbProtocol = gcnew String(USB_2_0);
+ }
+ else if (_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_XHCI) == 0)
+ {
+ hc->UsbProtocol = gcnew String(USB_3_0);
+ }
+ else
+ {
+ USB_CONTROLLER_FLAVOR flavor = hcInfo->ControllerInfo->ControllerFlavor;
+
+ // If protocol lookup failed based on service name, try Controller flavor
+ if(NULL != hcInfo->ControllerInfo)
+ {
+ if(flavor == USB_HcGeneric)
+ {
+ hc->UsbProtocol = gcnew String(USB_GENERIC);
+ }
+ else if(flavor >= OHCI_Generic && flavor < UHCI_Generic)
+ {
+ hc->UsbProtocol = gcnew String(USB_1_1);
+ }
+ else if(flavor >= UHCI_Generic && flavor < EHCI_Generic)
+ {
+ hc->UsbProtocol = gcnew String(USB_2_0);
+ }
+ else if(flavor >= EHCI_Generic)
+ {
+ hc->UsbProtocol = gcnew String(USB_3_0);
+ }
+ }
+ }
+ }
+
+ hc->ControllerInfo = gcnew UsbHCDeviceInfoType();
+ hc->PowerMapping = gcnew UsbHCPowerStateMappingType();
+ ci = hc->ControllerInfo;
+ pm = hc->PowerMapping;
+
+ ci->VendorId = hcInfo->VendorID;
+ ci->DeviceId = hcInfo->DeviceID;
+ ci->DriverKey = PACHAR_TO_STRING(hcInfo->DriverKey);
+ ci->SubSysId = hcInfo->SubSysID;
+ ci->Revision = hcInfo->Revision;
+
+ if(NULL != hcInfo->ControllerInfo)
+ {
+ ci->NumberOfRootPorts = hcInfo->ControllerInfo->NumberOfRootPorts;
+ ci->ControllerFlavor = hcInfo->ControllerInfo->ControllerFlavor;
+ ci->PortSwitchingEnabled = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_FLAG_PORT_POWER_SWITCHING)? true: false;
+ ci->SelectiveSuspendEnabled = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_FLAG_SEL_SUSPEND)? true: false;
+ ci->LegacyBios = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_LEGACY_BIOS)? true: false;
+ ci->ControllerFlavorString = PACHAR_TO_STRING(GetControllerFlavorString(hcInfo->ControllerInfo->ControllerFlavor));
+ }
+
+ // Add power mappings
+ XmlAddHostControllerPowerMapping(pm, (PUSB_POWER_INFO) (&(hcInfo->USBPowerInfo[0])));
+
+ // Add debug port
+ debugPort = GetEhciDebugPort(hcInfo->VendorID, hcInfo->DeviceID);
+ if (debugPort > 0)
+ {
+ ci->DebugPort = debugPort;
+ }
+
+ gXmlStack->Push(hc);
+
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+
+ return hr;
+}
+
+/*****************************************************************************
+
+ XmlAddHub30Descriptor()
+
+ Adds the hub 3.0 descriptor to the given hub object
+ *****************************************************************************/
+void XmlAddHub30Descriptor(Hub30DescriptorType ^hub30Desc, PUSB_30_HUB_DESCRIPTOR hub30Descriptor)
+{
+
+ if (nullptr != hub30Desc && NULL != hub30Descriptor)
+ {
+ hub30Desc->Length = hub30Descriptor->bLength;
+ hub30Desc->DescriptorType = hub30Descriptor->bDescriptorType;
+ hub30Desc->NumberOfPorts = hub30Descriptor->bNumberOfPorts;
+ hub30Desc->HubCharacteristics = hub30Descriptor->wHubCharacteristics;
+ hub30Desc->PowerOntoPowerGood = hub30Descriptor->bPowerOnToPowerGood;
+ hub30Desc->HubControlCurrent = hub30Descriptor->bHubControlCurrent;
+ hub30Desc->HubHdrDecLat = hub30Descriptor->bHubHdrDecLat;
+ hub30Desc->DeviceRemovable = hub30Descriptor->DeviceRemovable;
+ }
+}
+
+/*****************************************************************************
+
+ XmlAddHubDescriptor()
+
+ Adds the hub descriptor to the given hub object
+ *****************************************************************************/
+void XmlAddHubDescriptor(HubDescriptorType ^hubDesc, PUSB_HUB_DESCRIPTOR hubDescriptor)
+{
+ if (nullptr != hubDesc && NULL != hubDescriptor)
+ {
+ hubDesc->DescriptorLength = hubDescriptor->bDescriptorLength;
+ hubDesc->DescriptorType = hubDescriptor->bDescriptorType;
+ hubDesc->NumberOfPorts = hubDescriptor->bNumberOfPorts;
+ hubDesc->PowerOntoPowerGood = hubDescriptor->bPowerOnToPowerGood;
+ hubDesc->HubControlCurrent = hubDescriptor->bHubControlCurrent;
+ }
+}
+
+/*****************************************************************************
+
+ XmlAddPortConnectorProps()
+
+ Adds the port connector properties to XML file
+ *****************************************************************************/
+void XmlAddPortConnectorProps(PortConnectorType ^portXmlProps, PUSB_PORT_CONNECTOR_PROPERTIES portProps)
+{
+ if (NULL != portProps)
+ {
+ portXmlProps->UsbPortProperties = gcnew UsbPortPropertiesType();
+
+ portXmlProps->ConnectionIndex = portProps->ConnectionIndex;
+ portXmlProps->ActualLength = portProps->ActualLength;
+ portXmlProps->CompanionIndex = portProps->CompanionIndex;
+ portXmlProps->CompanionPortNumber = portProps->CompanionPortNumber;
+ portXmlProps->CompanionHubSymbolicLinkName = PWCHAR_TO_STRING(portProps->CompanionHubSymbolicLinkName);
+
+ portXmlProps->UsbPortProperties->PortIsUserConnectable = portProps->UsbPortProperties.PortIsUserConnectable? true:false;
+ portXmlProps->UsbPortProperties->PortIsDebugCapable = portProps->UsbPortProperties.PortIsDebugCapable? true:false;
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddConnectionInfoV2()
+
+ Adds the V2 connection info structure
+ *****************************************************************************/
+void XmlAddConnectionInfoV2(NodeConnectionInfoExV2Type ^ connectionXmlInfo, PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfo)
+{
+ if (NULL != connectionInfo)
+ {
+ connectionXmlInfo->ConnectionIndex = connectionInfo->ConnectionIndex;
+ connectionXmlInfo->Length = connectionInfo->Length;
+
+ connectionXmlInfo->Usb110Supported = connectionInfo->SupportedUsbProtocols.Usb110? true:false;
+ connectionXmlInfo->Usb200Supported = connectionInfo->SupportedUsbProtocols.Usb200? true:false;
+ connectionXmlInfo->Usb300Supported = connectionInfo->SupportedUsbProtocols.Usb300? true:false;
+
+ connectionXmlInfo->DeviceIsOperatingAtSuperSpeedOrHigher =
+ connectionInfo->Flags.DeviceIsOperatingAtSuperSpeedOrHigher;
+
+ connectionXmlInfo->DeviceIsSuperSpeedCapableOrHigher =
+ connectionInfo->Flags.DeviceIsSuperSpeedCapableOrHigher;
+
+ connectionXmlInfo->DeviceIsOperatingAtSuperSpeedPlusOrHigher =
+ connectionInfo->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher;
+
+ connectionXmlInfo->DeviceIsSuperSpeedPlusCapableOrHigher =
+ connectionInfo->Flags.DeviceIsSuperSpeedPlusCapableOrHigher;
+
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddHubCharacteristics()
+
+ Adds the hub characteristics to the given hub object
+ *****************************************************************************/
+void XmlAddHubCharacteristics(HubInformationType ^hubI, WORD hubChar)
+{
+ HubCharacteristicsType ^hubC = nullptr;
+
+ hubI->HubCharacteristics = gcnew HubCharacteristicsType();
+ hubC = hubI->HubCharacteristics;
+ hubC->HubCharacteristicsValue = hubChar;
+ switch(hubChar & 0x3)
+ {
+ case 0x0:
+ hubC->PowerSwitching = gcnew String("Ganged");
+ break;
+ case 0x1:
+ hubC->PowerSwitching = gcnew String("Individual");
+ break;
+ case 0x2:
+ case 0x3:
+ hubC->PowerSwitching = gcnew String("None");
+ break;
+ default:
+ hubC->PowerSwitching = gcnew String("Unknown");
+ }
+
+ hubC->CompoundDevice = (hubChar & 0x4)? true:false;
+
+ switch(hubChar & 0x18)
+ {
+ case 0x0:
+ hubC->OverCurrentProtection = gcnew String("Global");
+ break;
+ case 0x8:
+ hubC->OverCurrentProtection = gcnew String("Individual");
+ break;
+ case 0x10:
+ case 0x18:
+ hubC->OverCurrentProtection = gcnew String("No protection, bus power only");
+ break;
+ default:
+ hubC->OverCurrentProtection = gcnew String("Unknown");
+ }
+}
+
+/*****************************************************************************
+
+ XmlAddHubNodeInformation()
+
+ Adds the node information to the hub object
+ *****************************************************************************/
+HRESULT XmlAddHubNodeInformation(HubNodeInformationType ^ni, PUSB_NODE_INFORMATION nodeInfo)
+{
+ PUSB_HUB_INFORMATION hubInfo = NULL;
+
+ if (NULL == nodeInfo)
+ {
+ return E_FAIL;
+ }
+
+ hubInfo = &(nodeInfo->u.HubInformation);
+ ni->HubNode = static_cast<HubNodeType> (nodeInfo->NodeType);
+
+ ni->HubInformation = gcnew HubInformationType();
+ ni->HubInformation->IsRootHub = true;
+ ni->HubInformation->IsBusPowered = hubInfo->HubIsBusPowered? true:false;
+
+ // Add hub characteristics
+ XmlAddHubCharacteristics(ni->HubInformation, hubInfo->HubDescriptor.wHubCharacteristics);
+ // Add descriptor
+ ni->HubInformation->HubDescriptor = gcnew HubDescriptorType();
+ XmlAddHubDescriptor(ni->HubInformation->HubDescriptor, &(hubInfo->HubDescriptor));
+
+ return S_OK;
+}
+
+/*****************************************************************************
+
+ XmlAddHubInformation()
+
+ Adds the node information to the hub object
+ *****************************************************************************/
+HRESULT XmlAddHubInformationEx(HubInformationExType ^ex, PUSB_HUB_INFORMATION_EX hubInfoEx)
+{
+ HubDescriptorType ^hubDesc = nullptr;
+ Hub30DescriptorType ^hub30Desc = nullptr;
+
+ if (NULL == hubInfoEx)
+ {
+ return E_FAIL;
+ }
+
+ ex->HubType = static_cast<HubTypeType> (hubInfoEx->HubType);
+ ex->HighestPortNumber = hubInfoEx->HighestPortNumber;
+ switch(hubInfoEx->HubType)
+ {
+ case UsbRootHub:
+ case Usb20Hub:
+ ex->HubDescriptor = hubDesc = gcnew HubDescriptorType();
+ XmlAddHubDescriptor(hubDesc, &(hubInfoEx->u.UsbHubDescriptor));
+ break;
+ case Usb30Hub:
+ ex->Hub30Descriptor = hub30Desc = gcnew Hub30DescriptorType();
+ XmlAddHub30Descriptor(hub30Desc, &(hubInfoEx->u.Usb30HubDescriptor));
+ break;
+ }
+ return S_OK;
+}
+
+/*****************************************************************************
+
+ XmlAddHubCapabilitiesEx()
+
+ Adds the hub capabilities information to the hub object
+ *****************************************************************************/
+HRESULT XmlAddHubCapabilitiesEx(HubCapabilitiesExType ^ex, PUSB_HUB_CAPABILITIES_EX hubCapEx)
+{
+ if(NULL != hubCapEx)
+ {
+ ex->HubIsHighSpeedCapable = hubCapEx->CapabilityFlags.HubIsHighSpeedCapable?true:false;
+ ex->HubIsHighSpeed = hubCapEx->CapabilityFlags.HubIsHighSpeed?true:false;
+ ex->HubIsMultiTtCapable = hubCapEx->CapabilityFlags.HubIsMultiTtCapable?true:false;
+ ex->HubIsMultiTt = hubCapEx->CapabilityFlags.HubIsMultiTt?true:false;
+ ex->HubIsRoot = hubCapEx->CapabilityFlags.HubIsRoot?true:false;
+ ex->HubIsArmedWakeOnConnect = hubCapEx->CapabilityFlags.HubIsArmedWakeOnConnect?true:false;
+ ex->HubIsBusPowered = hubCapEx->CapabilityFlags.HubIsBusPowered?true:false;
+ }
+ return S_OK;
+}
+
+/*****************************************************************************
+
+ ExternalHubType ^ AddExternalHub(Object ^parent)
+
+ This routine finds the type of the parent and adds an external hub object to the
+ parent's list of external hubs. The newly created object is returned
+ We are using arrays insted of better types of collections becaused the code generated
+ by xsd.exe does not support other types.
+ *****************************************************************************/
+ExternalHubType ^ AddExternalHub(Object ^parent)
+{
+ RootHubType ^ rhParent = nullptr;
+ ExternalHubType ^ ehParent = nullptr;
+ array<ExternalHubType ^> ^ exHubArray = nullptr;
+ ExternalHubType ^ exHub = nullptr;
+ boolean arrayCreated = false;
+
+ // An external hub can be connected to a Root Hub or another External Hub
+ // We need to determine the type of the object.
+
+ // Try root hub first
+
+ rhParent = dynamic_cast<RootHubType ^> (parent);
+ if (rhParent == nullptr)
+ {
+ // RootHub cast was not successfult, try external hub
+ ehParent = dynamic_cast<ExternalHubType ^> (parent);
+ if (ehParent != nullptr)
+ {
+ // External hub parent
+ if (ehParent->ExternalHub == nullptr)
+ {
+ // First hub in the list of external hubs
+ ehParent->ExternalHub = gcnew array<ExternalHubType ^> (1);
+ arrayCreated = true;
+ }
+ exHubArray = ehParent->ExternalHub;
+ }
+
+ }
+ else
+ {
+ // Parent is a root hub
+ if (rhParent->ExternalHub == nullptr)
+ {
+ // First hub in root hub list
+ rhParent->ExternalHub = gcnew array<ExternalHubType ^>(1);
+ arrayCreated = true;
+ }
+ exHubArray = rhParent->ExternalHub;
+ }
+
+ if (exHubArray != nullptr)
+ {
+ if (arrayCreated)
+ {
+ // We created the array in this function, so we use offset 0
+ exHubArray[0] = gcnew ExternalHubType();
+ exHub = exHubArray[0];
+ }
+ else
+ {
+ // The array was already present, we need to do elaborate things
+ // as array.resize does not work.
+ ArrayList ^exList = gcnew ArrayList();
+ exList->AddRange(exHubArray);
+ exHub = gcnew ExternalHubType();
+ exList->Add(exHub);
+
+ if (rhParent != nullptr)
+ {
+ rhParent->ExternalHub = reinterpret_cast<array<ExternalHubType ^>^> (exList->ToArray(ExternalHubType::typeid));
+ }
+ else
+ {
+ ehParent->ExternalHub = reinterpret_cast<array<ExternalHubType ^>^> (exList->ToArray(ExternalHubType::typeid));
+ }
+ }
+ }
+ return exHub;
+}
+/*****************************************************************************
+
+ NoDeviceType ^ AddDisconnectedPort(Object ^parent)
+
+ This routine finds the type of the parent and adds a empty port connection object to the
+ parent's list of devices. The newly created object is returned
+ We are using arrays insted of better types of collections becaused the code generated
+ by xsd.exe does not support other types.
+ *****************************************************************************/
+NoDeviceType ^ AddDisconnectedPort(Object ^parent)
+{
+ RootHubType ^ rhParent = nullptr;
+ ExternalHubType ^ ehParent = nullptr;
+ array<NoDeviceType ^> ^ devicesArray = nullptr;
+ NoDeviceType ^ noD = nullptr;
+ boolean arrayCreated = false;
+
+ // An external hub can be connected to a Root Hub or another External Hub
+ // We need to determine the type of the object.
+
+ // Try RH first
+
+ rhParent = dynamic_cast<RootHubType ^> (parent);
+ if (rhParent == nullptr)
+ {
+ // RootHub cast was not successfult, try external hub
+ ehParent = dynamic_cast<ExternalHubType ^> (parent);
+ if (ehParent != nullptr)
+ {
+ // External hub parent
+ if (ehParent->NoDevice == nullptr)
+ {
+ // First hub in the list of external hubs
+ ehParent->NoDevice = gcnew array<NoDeviceType ^> (1);
+ arrayCreated = true;
+ }
+ devicesArray = ehParent->NoDevice;
+ }
+
+ }
+ else
+ {
+ // Parent is a root hub
+ if (rhParent->NoDevice == nullptr)
+ {
+ // First hub in root hub list
+ rhParent->NoDevice = gcnew array<NoDeviceType ^>(1);
+ arrayCreated = true;
+ }
+ devicesArray = rhParent->NoDevice;
+ }
+
+ if (devicesArray != nullptr)
+ {
+ if (arrayCreated)
+ {
+ // We created the array in this function, so we use offset 0
+ devicesArray[0] = gcnew NoDeviceType();
+ noD = devicesArray[0];
+ }
+ else
+ {
+ // The array was already present, we need to do elaborate things
+ // as array.resize does not work.
+ ArrayList ^exList = gcnew ArrayList();
+ exList->AddRange(devicesArray);
+ noD = gcnew NoDeviceType();
+ exList->Add(noD);
+
+ if (rhParent != nullptr)
+ {
+ rhParent->NoDevice = reinterpret_cast<array<NoDeviceType ^>^> (exList->ToArray(NoDeviceType::typeid));
+ }
+ else
+ {
+ ehParent->NoDevice = reinterpret_cast<array<NoDeviceType ^>^> (exList->ToArray(NoDeviceType::typeid));
+ }
+ }
+ }
+ return noD;
+}
+
+/*****************************************************************************
+
+ UsbDeviceType ^ AddUsbDevice(Object ^parent)
+
+ This routine finds the type of the parent and adds a port connection object to the
+ parent's list of port connectors. The newly created object is returned
+ We are using arrays insted of better types of collections becaused the code generated
+ by xsd.exe does not support other types.
+ *****************************************************************************/
+UsbDeviceType ^ AddUsbDevice(Object ^parent)
+{
+ RootHubType ^ rhParent = nullptr;
+ ExternalHubType ^ ehParent = nullptr;
+ array<UsbDeviceType ^> ^ devicesArray = nullptr;
+ UsbDeviceType ^ usbD = nullptr;
+ boolean arrayCreated = false;
+
+ // An external hub can be connected to a Root Hub or another External Hub
+ // We need to determine the type of the object.
+
+ // Try RH first
+
+ rhParent = dynamic_cast<RootHubType ^> (parent);
+ if (rhParent == nullptr)
+ {
+ // RootHub cast was not successfult, try external hub
+ ehParent = dynamic_cast<ExternalHubType ^> (parent);
+ if (ehParent != nullptr)
+ {
+ // External hub parent
+ if (ehParent->UsbDevice == nullptr)
+ {
+ // First hub in the list of external hubs
+ ehParent->UsbDevice = gcnew array<UsbDeviceType ^> (1);
+ arrayCreated = true;
+ }
+ devicesArray = ehParent->UsbDevice;
+ }
+
+ }
+ else
+ {
+ // Parent is a root hub
+ if (rhParent->UsbDevice == nullptr)
+ {
+ // First hub in root hub list
+ rhParent->UsbDevice = gcnew array<UsbDeviceType ^>(1);
+ arrayCreated = true;
+ }
+ devicesArray = rhParent->UsbDevice;
+ }
+
+ if (devicesArray != nullptr)
+ {
+ if (arrayCreated)
+ {
+ // We created the array in this function, so we use offset 0
+ devicesArray[0] = gcnew UsbDeviceType();
+ usbD = devicesArray[0];
+ }
+ else
+ {
+ // The array was already present, we need to do elaborate things
+ // as array.resize does not work.
+ ArrayList ^exList = gcnew ArrayList();
+ exList->AddRange(devicesArray);
+ usbD = gcnew UsbDeviceType();
+ exList->Add(usbD);
+
+ if (rhParent != nullptr)
+ {
+ rhParent->UsbDevice = reinterpret_cast<array<UsbDeviceType ^>^> (exList->ToArray(UsbDeviceType::typeid));
+ }
+ else
+ {
+ ehParent->UsbDevice = reinterpret_cast<array<UsbDeviceType ^>^> (exList->ToArray(UsbDeviceType::typeid));
+ }
+ }
+ }
+ return usbD;
+}
+
+/*****************************************************************************
+
+ XmlAddIADDescriptor()
+
+ This routine adds usb IAD descriptor
+ *****************************************************************************/
+void XmlAddIADDescriptor(
+ UsbDeviceIADDescriptorType ^ iadXmlDesc,
+ PUSB_IAD_DESCRIPTOR iadDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc,
+ int nInterfaces)
+{
+ if (NULL == iadDesc || NULL == stringDesc)
+ {
+ return;
+ }
+
+ // Update structure fields
+ iadXmlDesc->BLength = iadDesc->bLength;
+ iadXmlDesc->BDescriptorType = iadDesc->bDescriptorType;
+ iadXmlDesc->BFirstInterface = iadDesc->bFirstInterface;
+ iadXmlDesc->BInterfaceCount = iadDesc->bInterfaceCount;
+ iadXmlDesc->BFunctionClass = iadDesc->bFunctionClass;
+ iadXmlDesc->BFunctionSubclass = iadDesc->bFunctionSubClass;
+ iadXmlDesc->BFunctionProtocol = iadDesc->bFunctionProtocol;
+ iadXmlDesc->IFunction = iadDesc->iFunction;
+
+ // Validate fields
+ if (iadDesc->bInterfaceCount == 1)
+ {
+ iadXmlDesc->InterfaceError = gcnew String("ERROR: bInterfaceCount must be greater than 1");
+ }
+ if (nInterfaces < iadDesc->bFirstInterface + iadDesc->bInterfaceCount)
+ {
+ iadXmlDesc->InterfaceError = gcnew String("ERROR: The total number of interfaces");
+ iadXmlDesc->InterfaceError += nInterfaces;
+ iadXmlDesc->InterfaceError += " must be greater than or equal to the highest linked interface number (base ";
+ iadXmlDesc->InterfaceError += iadDesc->bFirstInterface;
+ iadXmlDesc->InterfaceError += " + count ";
+ iadXmlDesc->InterfaceError += iadDesc->bInterfaceCount;
+ iadXmlDesc->InterfaceError += " = ";
+ iadXmlDesc->InterfaceError += (iadDesc->bFirstInterface + iadDesc->bInterfaceCount);
+ iadXmlDesc->InterfaceError += " )";
+ }
+ if (iadDesc->bFunctionClass == 0)
+ {
+ iadXmlDesc->FunctionClassError = gcnew String("ERROR: bFunctionClass contains an illegal value 0");
+ }
+
+ iadXmlDesc->FunctionDetails = XmlGetDeviceClass(
+ iadDesc->bFunctionClass,
+ iadDesc->bFunctionSubClass,
+ iadDesc->bFunctionProtocol);
+
+ // Protocol check
+ if (iadDesc->bFunctionClass == USB_DEVICE_CLASS_VIDEO)
+ {
+ if (iadDesc->bFunctionProtocol != PC_PROTOCOL_UNDEFINED)
+ {
+ iadXmlDesc->Protocol= gcnew String("WARNING: Protocol must be set to PC_PROTOCOL_UNDEFINED");
+ iadXmlDesc->Protocol+= " for this class but is set to: ";
+ iadXmlDesc->Protocol+= iadDesc->bFunctionProtocol;
+ }
+ else
+ {
+ iadXmlDesc->Protocol = gcnew String("PC_PROTOCOL_UNDEFINED protocol");
+ }
+ }
+
+ if (iadDesc->iFunction)
+ {
+ // Add String descriptor
+ iadXmlDesc->StringDesc = XmlGetStringDescriptor(
+ iadDesc->iFunction,
+ stringDesc,
+ false);
+ }
+
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddOTGDescriptor()
+
+ This routine adds usb OTG descriptor
+ *****************************************************************************/
+void XmlAddOTGDescriptor(
+ UsbDeviceOTGDescriptorType ^ otgXmlDesc,
+ PUSB_OTG_DESCRIPTOR otgDesc)
+{
+ if (NULL == otgDesc)
+ {
+ return;
+ }
+
+ otgXmlDesc->BLength = otgDesc->bLength;
+ otgXmlDesc->BDescriptorType = otgDesc->bDescriptorType;
+ otgXmlDesc->BmAttributes = otgDesc->bmAttributes;
+
+ // Add descriptive fields
+ switch (otgDesc->bmAttributes)
+ {
+ case 0:
+ break;
+ case 1:
+ otgXmlDesc->AttributesString = gcnew String("SRP support");
+ break;
+ case 2:
+ otgXmlDesc->AttributesString = gcnew String("HNP support");
+ break;
+ case 3:
+ otgXmlDesc->AttributesString = gcnew String("SRP and HNP support");
+ break;
+ default:
+ otgXmlDesc->AttributesString = gcnew String("ERROR: bmAttributes bits 2-7 are reserved should be 0)");
+ break;
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddHidDescriptor()
+
+ This routine adds usb HID descriptor
+ *****************************************************************************/
+void XmlAddHidDescriptor(
+ UsbDeviceHidDescriptorType ^ hidXmlDesc,
+ PUSB_HID_DESCRIPTOR hidDesc
+ )
+{
+ int i = 0;
+
+ if (NULL == hidDesc)
+ {
+ return;
+ }
+
+ hidXmlDesc->BLength = hidDesc->bLength;
+ hidXmlDesc->BDescriptorType = hidDesc->bDescriptorType;
+ hidXmlDesc->BcdHID = hidDesc->bcdHID;
+ hidXmlDesc->BCountryCode = hidDesc->bCountryCode;
+ hidXmlDesc->BNumDescriptors = hidDesc->bNumDescriptors;
+
+ // Add optional descriptors
+ if (hidDesc->bNumDescriptors > 0)
+ {
+ hidXmlDesc->OptionalDescriptor = gcnew array <UsbDeviceHidOptionalDescriptorsType ^>(hidDesc->bNumDescriptors);
+ for(i=0; i < hidDesc->bNumDescriptors; i++)
+ {
+ hidXmlDesc->OptionalDescriptor[i] = gcnew UsbDeviceHidOptionalDescriptorsType();
+ hidXmlDesc->OptionalDescriptor[i]->BDescriptorType = hidDesc->OptionalDescriptors[i].bDescriptorType;
+ hidXmlDesc->OptionalDescriptor[i]->WDescriptorLength = hidDesc->OptionalDescriptors[i].wDescriptorLength;
+ }
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlGetUnknownDescriptor()
+
+ This routine gets a usb unknown descriptor object form unknown descriptor
+ *****************************************************************************/
+UsbDeviceUnknownDescriptorType ^ XmlGetUnknownDescriptor(
+ PUSB_COMMON_DESCRIPTOR unknownDesc
+ )
+{
+ int i = 0;
+ UsbDeviceUnknownDescriptorType ^ unknownXmlDesc = nullptr;
+
+ if (NULL == unknownDesc)
+ {
+ return nullptr;
+ }
+
+ unknownXmlDesc = gcnew UsbDeviceUnknownDescriptorType();
+ unknownXmlDesc->BLength = unknownDesc->bLength;
+ unknownXmlDesc->BDescriptorType = unknownDesc->bDescriptorType;
+
+ // Add optional descriptors
+ if (unknownDesc->bLength > 0)
+ {
+ unknownXmlDesc->UnknownDescriptor = gcnew String("Unknown descriptor->");
+ for(i=0; i < unknownDesc->bLength; i++)
+ {
+ unknownXmlDesc->UnknownDescriptor += String::Format("0x{0:X} ", ((PUCHAR) unknownDesc)[i]);
+ }
+ }
+ return unknownXmlDesc;
+}
+
+/*****************************************************************************
+
+ XmlAddEndpointDescriptor()
+
+ This routine adds usb endpoint descriptor and verbose fields
+ *****************************************************************************/
+void XmlAddEndpointDescriptor(
+ EndpointDescriptorType ^usbXmlEndpointDescriptor,
+ PUSB_ENDPOINT_DESCRIPTOR endPointDescriptor,
+ UCHAR connectionSpeed
+ )
+{
+ EndpointDescriptorType ^ue = usbXmlEndpointDescriptor;
+ ULONG maxBytes = endPointDescriptor->wMaxPacketSize & 0x7FF;
+
+ // Add structure values
+ ue->Length = endPointDescriptor->bLength;
+ ue->DescriptorType = endPointDescriptor->bDescriptorType;
+ ue->EndpointAddress = endPointDescriptor->bEndpointAddress;
+ ue->Attributes = endPointDescriptor->bmAttributes;
+ ue->MaxPacketSize = endPointDescriptor->wMaxPacketSize;
+
+ // Add verbose fields
+ ue->EndpointId = endPointDescriptor->bEndpointAddress & 0x0F;
+
+ // Add endpoint direction
+ if (USB_ENDPOINT_DIRECTION_OUT(endPointDescriptor->bEndpointAddress))
+ {
+ ue->EndpointDirection = gcnew String("Out");
+ }
+ else if (USB_ENDPOINT_DIRECTION_IN(endPointDescriptor->bEndpointAddress))
+ {
+ ue->EndpointDirection = gcnew String("In");
+ }
+
+ // Add endpoint type
+ switch (endPointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
+ {
+ case USB_ENDPOINT_TYPE_CONTROL:
+ ue->EndpointType = gcnew String("Control Transfer Type");
+ break;
+ case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+ switch (endPointDescriptor->bmAttributes & 0x0C)
+ {
+ case 0x00:
+ ue->EndpointType = gcnew String("Ischronous Transfer Type - No Synchronization");
+ break;
+
+ case 0x04:
+ ue->EndpointType = gcnew String("Ischronous Transfer Type - Asynchronous");
+ break;
+
+ case 0x08:
+ ue->EndpointType = gcnew String("Ischronous Transfer Type - Adaptive");
+ break;
+
+ case 0x0C:
+ ue->EndpointType = gcnew String("Ischronous Transfer Type - Synchronous");
+ break;
+ }
+ break;
+ case USB_ENDPOINT_TYPE_BULK:
+ ue->EndpointType = gcnew String("Bulk Transfer Type");
+ break;
+
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ ue->EndpointType = gcnew String("Interrupt Transfer Type");
+ break;
+ }
+
+ // Add packet info
+ switch (connectionSpeed)
+ {
+ case UsbHighSpeed:
+ if (endPointDescriptor->bmAttributes & 1) {
+ ULONG transactions = ((endPointDescriptor->wMaxPacketSize & 0x1800) >> 11) + 1;
+ // Isoc or Interrupt endpoint
+ ue->EndpointPacketInfo = gcnew String(
+ transactions + " transactions per microframe, " +
+ maxBytes + " max bytes");
+ }
+ else
+ {
+ // Bulk endpoint
+ ue->EndpointPacketInfo = gcnew String(maxBytes + " max bytes");
+ }
+ break;
+ case UsbFullSpeed:
+ ue->EndpointPacketInfo = gcnew String(maxBytes + " max bytes");
+ break;
+ default:
+ // Low or Invalid speed
+ ue->EndpointPacketInfo = gcnew String("Invalid bus speed");
+ break;
+ }
+
+ // Add validation
+ if (endPointDescriptor->wMaxPacketSize & 0xE000)
+ {
+ ue->EndpointPacketSizeValidation = gcnew String("ERROR: wMaxPacketSize bits 15-13 should be 0");
+ } else if (connectionSpeed==UsbHighSpeed)
+ {
+ USHORT hsMux;
+
+ hsMux = (endPointDescriptor->wMaxPacketSize >> 11) & 0x03;
+
+ switch (endPointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
+ {
+ case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ switch (hsMux) {
+ case 0:
+ if ((maxBytes < 1) || (maxBytes > 1024))
+ {
+ ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 1 and 1024");
+ }
+ break;
+
+ case 1:
+ if ((maxBytes < 513) || (maxBytes > 1024))
+ {
+ ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 513 and 1024");
+ }
+ break;
+
+ case 2:
+ if ((maxBytes < 683) || (maxBytes > 1024))
+ {
+ ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 683 and 1024");
+ }
+ break;
+
+ case 3:
+ ue->EndpointPacketSizeValidation = gcnew String("ERROR: Bits 12-11 set to reserved value\r\n");
+ break;
+ }
+ }
+ }
+
+ // Add interval
+ if (endPointDescriptor->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR))
+ {
+ ue->Interval = endPointDescriptor->bInterval;
+ }
+ else
+ {
+ PUSB_ENDPOINT_DESCRIPTOR2 endpointDesc2 = (PUSB_ENDPOINT_DESCRIPTOR2) endPointDescriptor;
+ ue->WInterval = endpointDesc2->wInterval;
+ ue->SyncAddress = endpointDesc2->bSyncAddress;
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddPipeInformation()
+
+ This routine adds all the pipe information for device
+ *****************************************************************************/
+void XmlAddPipeInformation(
+ array< UsbPipeInfoType ^> ^ usbXmlPipeInfoList,
+ PUSB_PIPE_INFO pipeInfo,
+ ULONG numPipes,
+ UCHAR connectionSpeed
+ )
+{
+ ULONG i = 0;
+
+ for(i = 0; i< numPipes; i++)
+ {
+ // Add all pipe in the list
+ usbXmlPipeInfoList[i] = gcnew UsbPipeInfoType();
+ usbXmlPipeInfoList[i]->EndpointDescriptor = gcnew EndpointDescriptorType();
+ XmlAddEndpointDescriptor(
+ usbXmlPipeInfoList[i]->EndpointDescriptor,
+ &pipeInfo[i].EndpointDescriptor,
+ connectionSpeed);
+ usbXmlPipeInfoList[i]->ScheduleOffset = pipeInfo->ScheduleOffset;
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddUsbDeviceDescriptor()
+
+ This routine adds usb device descriptor
+ *****************************************************************************/
+void XmlAddUsbDeviceDescriptor(
+ UsbDeviceDescriptorType ^usbXmlDeviceDescriptor,
+ PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor)
+{
+ UsbDeviceDescriptorType ^ud = usbXmlDeviceDescriptor;
+
+ // Map all fields explicitly
+
+ ud->Length = usbDeviceDescriptor->bLength;
+ ud->DescriptorType = usbDeviceDescriptor->bDescriptorType;
+ ud->CdUSB= usbDeviceDescriptor->bcdUSB;
+ ud->DeviceClass = usbDeviceDescriptor->bDeviceClass;
+ ud->DeviceSubclass = usbDeviceDescriptor->bDeviceSubClass;
+ ud->DeviceProtocol = usbDeviceDescriptor->bDeviceProtocol;
+ ud->MaxPacketSize0 = usbDeviceDescriptor->bMaxPacketSize0;
+ ud->IdVendor = usbDeviceDescriptor->idVendor;
+ ud->IdProduct = usbDeviceDescriptor->idProduct ;
+ ud->CdDevice = usbDeviceDescriptor->bcdDevice;
+ ud->IManufacturer = usbDeviceDescriptor->iManufacturer;
+ ud->IProduct = usbDeviceDescriptor->iProduct;
+ ud->ISerialNumber = usbDeviceDescriptor->iSerialNumber;
+ ud->NumConfigurations = usbDeviceDescriptor->bNumConfigurations;
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddConfigurationDescriptor()
+
+ This routine adds the configuration descriptor
+ *****************************************************************************/
+void XmlAddConfigurationDescriptor(
+ UsbConfigurationDescriptorType ^ confXmlDesc,
+ PUSBDEVICEINFO deviceInfo,
+ PUSB_CONFIGURATION_DESCRIPTOR configDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc
+ )
+
+{
+ UINT uCount = 0;
+ BOOL isSuperSpeed = FALSE;
+
+ if (NULL == configDesc || NULL == deviceInfo)
+ {
+ return;
+ }
+
+ if(deviceInfo->ConnectionInfoV2 &&
+ (deviceInfo->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher ||
+ deviceInfo->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher))
+ {
+ isSuperSpeed = TRUE;
+ }
+
+ confXmlDesc->BLength = configDesc->bLength;
+ confXmlDesc->BDescriptorType = configDesc->bDescriptorType;
+ confXmlDesc->WTotalLength = configDesc->wTotalLength;
+ confXmlDesc->BNumInterfaces = configDesc->bNumInterfaces;
+ confXmlDesc->BConfigurationValue = configDesc->bConfigurationValue;
+ confXmlDesc->IConfiguration = configDesc->iConfiguration;
+ confXmlDesc->BmAttributes = configDesc->bmAttributes;
+ confXmlDesc->MaxPower = configDesc->MaxPower;
+
+ uCount = GetConfigurationSize(deviceInfo);
+
+ if (uCount != configDesc->wTotalLength)
+ {
+ confXmlDesc->ConfigDescError = gcnew String("ERROR: Invalid total configuration size " +
+ configDesc->wTotalLength + ", should be " + uCount);
+ }
+
+ if (configDesc->bConfigurationValue != 1)
+ {
+ confXmlDesc->ConfValueError = gcnew String("CAUTION: Most host controllers will only work with one configuration per speed");
+ }
+
+ if (configDesc->iConfiguration)
+ {
+ confXmlDesc->ConfStringDesc = XmlGetStringDescriptor(
+ configDesc->iConfiguration,
+ stringDesc,
+ false);
+ }
+
+ if (configDesc->bmAttributes & USB_CONFIG_BUS_POWERED)
+ {
+ confXmlDesc->AttributesStr = gcnew String("Bus Powered");
+ }
+ else if (configDesc->bmAttributes & USB_CONFIG_SELF_POWERED)
+ {
+ confXmlDesc->AttributesStr = gcnew String("Self Powered");
+ }
+ else if (configDesc->bmAttributes & USB_CONFIG_REMOTE_WAKEUP)
+ {
+ confXmlDesc->AttributesStr = gcnew String("Remote Wakeup");
+ }
+ else
+ {
+ confXmlDesc->AttributesStr = gcnew String("WARNING: bmAttributes is using reserved space");
+ }
+
+ confXmlDesc->MaxCurrent = gcnew String("");
+ confXmlDesc->MaxCurrent += (isSuperSpeed?configDesc->MaxPower * 8:configDesc->MaxPower * 2);
+ confXmlDesc->MaxCurrent += " mA";
+
+ return;
+}
+
+/*****************************************************************************
+
+ XmlGetDeviceClass()
+
+ This routine returns the interface class and subclass for given interface descriptor
+ *****************************************************************************/
+UsbDeviceClassType ^ XmlGetDeviceClass(UCHAR bInterfaceClass, UCHAR bInterfaceSubclass, UCHAR bInterfaceProtocol)
+{
+ String ^ deviceClass = nullptr;
+ String ^ deviceSubclass = nullptr;
+ UsbDeviceClassType ^ deviceDetails = gcnew UsbDeviceClassType();
+
+ switch (bInterfaceClass)
+ {
+ case USB_DEVICE_CLASS_AUDIO:
+ deviceClass = gcnew String("Audio Interface");
+
+ switch (bInterfaceSubclass)
+ {
+ case USB_AUDIO_SUBCLASS_AUDIOCONTROL:
+ deviceSubclass = gcnew String("Audio Control Interface");
+ break;
+
+ case USB_AUDIO_SUBCLASS_AUDIOSTREAMING:
+ deviceSubclass = gcnew String("Audio Streaming Interface");
+ break;
+
+ case USB_AUDIO_SUBCLASS_MIDISTREAMING:
+ deviceSubclass = gcnew String("MIDI Streaming Interface");
+ break;
+
+ default:
+ deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : ");
+ deviceSubclass += bInterfaceSubclass;
+ break;
+ }
+ break;
+
+ case USB_DEVICE_CLASS_VIDEO:
+ deviceClass = gcnew String("Video Interface");
+
+ switch(bInterfaceSubclass)
+ {
+ case VIDEO_SUBCLASS_CONTROL:
+ deviceSubclass = gcnew String("Video Control");
+ break;
+
+ case VIDEO_SUBCLASS_STREAMING:
+ deviceSubclass = gcnew String("Video Streaming");
+ break;
+
+ default:
+ deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : ");
+ deviceSubclass += bInterfaceSubclass;
+ break;
+ }
+ break;
+
+ case USB_DEVICE_CLASS_VENDOR_SPECIFIC:
+ deviceClass = gcnew String("Vendor Specific Device");
+ break;
+
+ case USB_DEVICE_CLASS_HUMAN_INTERFACE:
+
+ deviceClass = gcnew String("HID Interface");
+ break;
+
+ case USB_DEVICE_CLASS_HUB:
+ deviceClass = gcnew String("HUB Interface");
+ break;
+
+ case USB_DEVICE_CLASS_RESERVED:
+ deviceClass = gcnew String("CAUTION: Reserved USB Device Interface Class");
+ break;
+
+ case USB_DEVICE_CLASS_COMMUNICATIONS:
+ deviceClass = gcnew String("Communications (CDC Control) USB Device\r\n");
+ break;
+
+ case USB_DEVICE_CLASS_MONITOR:
+ deviceClass = gcnew String("Monitor USB Device Interface Class*** (This may be obsolete)");
+ break;
+
+ case USB_DEVICE_CLASS_PHYSICAL_INTERFACE:
+ deviceClass = gcnew String("Physical Interface USB Device");
+ break;
+
+ case USB_DEVICE_CLASS_POWER:
+ if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1)
+ {
+ deviceClass = gcnew String("Image USB Device");
+ }
+ else
+ {
+ deviceClass = gcnew String("Power USB Device (This may be obsolete)");
+ }
+ break;
+
+ case USB_DEVICE_CLASS_PRINTER:
+ deviceClass = gcnew String("Printer USB Device");
+ break;
+
+ case USB_DEVICE_CLASS_STORAGE:
+ deviceClass = gcnew String("Mass Storage USB Device");
+ break;
+
+ case USB_CDC_DATA_INTERFACE:
+ deviceClass = gcnew String("CDC Data USB Device");
+ break;
+
+ case USB_CHIP_SMART_CARD_INTERFACE:
+ deviceClass = gcnew String("Chip/Smart Card USB Device");
+ break;
+
+ case USB_CONTENT_SECURITY_INTERFACE:
+ deviceClass = gcnew String("Content Security USB Device");
+ break;
+
+ case USB_DIAGNOSTIC_DEVICE_INTERFACE:
+ if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1)
+ {
+ deviceClass = gcnew String("Reprogrammable USB2 Compliance Diagnostic Device USB Device");
+ }
+ else
+ {
+ deviceClass = gcnew String("CAUTION: This appears to be an invalid device class: ");
+ deviceClass += bInterfaceClass;
+ }
+ break;
+
+ case USB_WIRELESS_CONTROLLER_INTERFACE:
+ if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1)
+ {
+ deviceClass = gcnew String("Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface");
+ }
+ else
+ {
+ deviceClass = gcnew String("CAUTION: This appears to be an invalid device class: ");
+ deviceClass += bInterfaceClass;
+ }
+ break;
+
+ case USB_APPLICATION_SPECIFIC_INTERFACE:
+ deviceClass = gcnew String("Application Specific USB Device");
+
+ switch(bInterfaceSubclass)
+ {
+ case 1:
+ deviceSubclass = gcnew String("Device Firmware Application Specific USB Device");
+ break;
+ case 2:
+ deviceSubclass = gcnew String("IrDA Bridge Application Specific USB Device");
+ break;
+ case 3:
+ deviceSubclass = gcnew String("Test & Measurement Class (USBTMC) Application Specific USB Device");
+ break;
+ default:
+ deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : ");
+ deviceSubclass += bInterfaceSubclass;
+ }
+ break;
+
+ default:
+
+ deviceClass = gcnew String("Interface Class unknown : ");
+ deviceClass += bInterfaceClass;
+ break;
+ }
+
+ // Return class and subclass
+
+ deviceDetails->DeviceClass = deviceClass;
+ deviceDetails->DeviceSubclass = deviceSubclass;
+
+ return deviceDetails;
+}
+
+/*****************************************************************************
+
+ XmlAddInterfaceDescriptor()
+
+ This routine adds the device interface descriptor
+ *****************************************************************************/
+void XmlAddDeviceInterfaceDescriptor(
+ UsbDeviceInterfaceDescriptorType ^ ifXmlDesc,
+ PUSB_INTERFACE_DESCRIPTOR ifDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc)
+{
+ if (NULL == ifDesc || NULL == stringDesc)
+ {
+ return;
+ }
+
+ // Update structure fields
+ ifXmlDesc->BLength = ifDesc->bLength;
+ ifXmlDesc->BDescriptorType = ifDesc->bDescriptorType;
+ ifXmlDesc->BInterfaceNumber = ifDesc->bInterfaceNumber;
+ ifXmlDesc->BAlternateSetting = ifDesc->bAlternateSetting;
+ ifXmlDesc->BNumEndpoints = ifDesc->bNumEndpoints;
+ ifXmlDesc->BInterfaceClass = ifDesc->bInterfaceClass;
+ ifXmlDesc->BInterfaceSubclass = ifDesc->bInterfaceSubClass;
+ ifXmlDesc->BInterfaceProtocol = ifDesc->bInterfaceProtocol;
+ ifXmlDesc->IInterface = ifDesc->iInterface;
+
+ // Update class and sub class
+ ifXmlDesc->InterfaceDetails = XmlGetDeviceClass(
+ ifDesc->bInterfaceClass,
+ ifDesc->bInterfaceSubClass,
+ ifDesc->bInterfaceProtocol);
+
+ //This is basically the check for PC_PROTOCOL_UNDEFINED
+ if ((ifDesc->bInterfaceClass == USB_DEVICE_CLASS_VIDEO) ||
+ (ifDesc->bInterfaceClass == USB_DEVICE_CLASS_AUDIO))
+ {
+ if (ifDesc->bInterfaceProtocol != PC_PROTOCOL_UNDEFINED)
+ {
+ ifXmlDesc->ProtocolError = gcnew String("WARNING: Protocol must be set to PC_PROTOCOL_UNDEFINED");
+ ifXmlDesc->ProtocolError += " for this class but is set to: ";
+ ifXmlDesc->ProtocolError += ifDesc->bInterfaceProtocol;
+ }
+ }
+
+ if (ifDesc->iInterface)
+ {
+ // Add String descriptor
+ ifXmlDesc->StringDesc = XmlGetStringDescriptor(
+ ifDesc->iInterface,
+ stringDesc,
+ false);
+ }
+
+ if (ifDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR2))
+ {
+ PUSB_INTERFACE_DESCRIPTOR2 interfaceDesc2;
+
+ interfaceDesc2 = (PUSB_INTERFACE_DESCRIPTOR2)ifDesc;
+
+ ifXmlDesc->WNumClasses = interfaceDesc2->wNumClasses;
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddDeviceQualDescriptor()
+
+ This routine adds the device qualifier descriptor
+ *****************************************************************************/
+
+void XmlAddDeviceQualDescriptor(
+ UsbDeviceQualifierDescriptorType ^ qualXmlDesc,
+ PUSB_DEVICE_QUALIFIER_DESCRIPTOR qualDesc)
+{
+ if (NULL == qualDesc)
+ {
+ return;
+ }
+
+ // Add structure fields
+ qualXmlDesc->BLength = qualDesc->bLength;
+ qualXmlDesc->BDescriptorType = qualDesc->bDescriptorType;
+ qualXmlDesc->BcdUSB = qualDesc->bcdUSB;
+ qualXmlDesc->BDeviceClass = qualDesc->bDeviceClass;
+ qualXmlDesc->BDeviceSubclass = qualDesc->bDeviceSubClass;
+ qualXmlDesc->BDeviceProtocol = qualDesc->bDeviceProtocol;
+ qualXmlDesc->BMaxPacketSize0 = qualDesc->bMaxPacketSize0;
+ qualXmlDesc->NumConfigurations = qualDesc->bNumConfigurations;
+
+ // Get device class string
+ qualXmlDesc->DeviceClass = XmlGetDeviceClassString(qualDesc->bDeviceClass);
+
+ if (qualDesc->bDeviceSubClass > 0x00 && qualDesc->bDeviceSubClass < 0xFF)
+ {
+ qualXmlDesc->DeviceSubclassError = gcnew String("ERROR: bDeviceSubClass is invalid : ");
+ qualXmlDesc->DeviceSubclassError += qualDesc->bDeviceSubClass;
+ }
+
+ if (qualDesc->bDeviceProtocol > 0x00 && qualDesc->bDeviceProtocol < 0xFF)
+ {
+ qualXmlDesc->DeviceProtocolError = gcnew String("ERROR: bDeviceProtocol is invalid : ");
+ qualXmlDesc->DeviceProtocolError += qualDesc->bDeviceProtocol;
+ }
+
+ qualXmlDesc->MaxPacketSizeInBytes = qualDesc->bMaxPacketSize0;
+
+ if (qualDesc->bNumConfigurations != 1)
+ {
+ qualXmlDesc->DeviceNumConfigError = gcnew String(
+ "CAUTION: Most host controllers will only work with one configuration per speed");
+ }
+
+ if (qualDesc->bReserved != 0)
+ {
+ qualXmlDesc->ReservedError = gcnew String("WARNING: bReserved needs to be set to 0 to be valid - " +
+ qualDesc->bReserved);
+ }
+
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddAddConfigDescriptors()
+
+ This routine adds the all the config descriptors
+ *****************************************************************************/
+array < UsbDeviceConfigurationType ^> ^ XmlGetConfigDescriptors(
+ PUSBDEVICEINFO deviceInfo,
+ PUSB_CONFIGURATION_DESCRIPTOR configDescs,
+ PSTRING_DESCRIPTOR_NODE stringDesc
+ )
+{
+ array < UsbDeviceConfigurationType ^> ^ confXmlDescs = nullptr;
+ PUSB_COMMON_DESCRIPTOR commonDesc = NULL;
+ PUCHAR descEnd = NULL;
+ ArrayList ^confList = gcnew ArrayList;
+ UsbDeviceConfigurationType ^ deviceConf = nullptr;
+
+ commonDesc = (PUSB_COMMON_DESCRIPTOR) configDescs;
+ descEnd = (PUCHAR) configDescs + configDescs->wTotalLength;
+
+ while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
+ (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
+ {
+ // Add the config descriptor
+ deviceConf = gcnew UsbDeviceConfigurationType();
+
+ XmlAddDeviceConfiguration(
+ deviceConf,
+ deviceInfo,
+ (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc,
+ stringDesc,
+ configDescs->bNumInterfaces
+ );
+
+ confList->Add(deviceConf);
+ commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
+ }
+
+ confXmlDescs = reinterpret_cast<array<UsbDeviceConfigurationType ^>^> (confList->ToArray(UsbDeviceConfigurationType::typeid));
+ return confXmlDescs;
+}
+
+/*****************************************************************************
+
+ XmlAddDeviceConfiguration()
+
+ This routine adds the device configuration
+ *****************************************************************************/
+void XmlAddDeviceConfiguration(
+ UsbDeviceConfigurationType ^ confXmlDesc,
+ PUSBDEVICEINFO deviceInfo,
+ PUSB_CONFIGURATION_DESCRIPTOR configDesc,
+ PSTRING_DESCRIPTOR_NODE stringDesc,
+ int numInterfaces
+ )
+{
+ PUSB_COMMON_DESCRIPTOR commonDesc = NULL;
+ UCHAR bInterfaceClass = 0;
+ UCHAR bInterfaceSubclass = 0;
+ UCHAR bInterfaceProtocol = 0;
+ BOOL displayUnknown = FALSE;
+
+ if (NULL == deviceInfo || NULL == configDesc || NULL == stringDesc)
+ {
+ return;
+ }
+
+ commonDesc = (PUSB_COMMON_DESCRIPTOR)configDesc;
+ displayUnknown = FALSE;
+
+ switch (commonDesc->bDescriptorType)
+ {
+ case USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE:
+ if (commonDesc->bLength != sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR))
+ {
+ // Validate descriptor
+ confXmlDesc->DeviceQualifierError = String::Format(
+ "ERROR: Device Qualifier bLength value incorrect Obtained: {0} Expected {1}",
+ commonDesc->bLength,
+ sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR));
+ displayUnknown = TRUE;
+ break;
+ }
+ // Add device Qual descriptor
+ confXmlDesc->DeviceQualifierDescriptor = gcnew UsbDeviceQualifierDescriptorType();
+
+ XmlAddDeviceQualDescriptor(
+ confXmlDesc->DeviceQualifierDescriptor,
+ (PUSB_DEVICE_QUALIFIER_DESCRIPTOR) commonDesc);
+ break;
+
+ case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
+ if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
+ {
+ // Validate descriptor
+ confXmlDesc->SpeedConfigurationError = String::Format(
+ "ERROR: Other speed configuration bLength value incorrect Obtained: {0} Expected {1}",
+ commonDesc->bLength,
+ sizeof(USB_CONFIGURATION_DESCRIPTOR));
+ displayUnknown = TRUE;
+ }
+
+ // Add configuration desc
+ confXmlDesc->ConfigurationDescriptor = gcnew UsbConfigurationDescriptorType();
+
+ XmlAddConfigurationDescriptor(
+ confXmlDesc->ConfigurationDescriptor,
+ deviceInfo,
+ (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc,
+ stringDesc);
+ break;
+
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
+ {
+ // Validate descriptor
+ confXmlDesc->SpeedConfigurationError = String::Format(
+ "ERROR: Configuration bLength value incorrect Obtained: {0} Expected {1}",
+ commonDesc->bLength,
+ sizeof(USB_CONFIGURATION_DESCRIPTOR));
+ displayUnknown = TRUE;
+ break;
+ }
+
+ // Add configuration desc
+ confXmlDesc->ConfigurationDescriptor = gcnew UsbConfigurationDescriptorType();
+ XmlAddConfigurationDescriptor(
+ confXmlDesc->ConfigurationDescriptor,
+ deviceInfo,
+ (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc,
+ stringDesc);
+ break;
+
+ case USB_INTERFACE_DESCRIPTOR_TYPE:
+ if ((commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR)) &&
+ (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2)))
+ {
+ // Validate descriptor
+ confXmlDesc->InterfaceError = String::Format(
+ "ERROR: Interface bLength value incorrect Obtained: {0} Expected: {1} or {2}",
+ commonDesc->bLength,
+ sizeof(USB_INTERFACE_DESCRIPTOR),
+ sizeof(USB_INTERFACE_DESCRIPTOR2));
+ displayUnknown = TRUE;
+ break;
+ }
+
+ // Add interface descriptor
+ bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass;
+ bInterfaceSubclass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceSubClass;
+ bInterfaceProtocol = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceProtocol;
+
+ confXmlDesc->InterfaceDescriptor = gcnew UsbDeviceInterfaceDescriptorType();
+ XmlAddDeviceInterfaceDescriptor(
+ confXmlDesc->InterfaceDescriptor,
+ (PUSB_INTERFACE_DESCRIPTOR) commonDesc,
+ stringDesc
+ );
+
+ case USB_ENDPOINT_DESCRIPTOR_TYPE:
+ if ((commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR)) &&
+ (commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR2)))
+ {
+ // Validate endpoint descriptor
+ confXmlDesc->EndpointError = String::Format(
+ "ERROR: Endpoint bLength value incorrect Obtained: {0} Expected: {1} or {2}",
+ commonDesc->bLength,
+ sizeof(USB_ENDPOINT_DESCRIPTOR),
+ sizeof(USB_ENDPOINT_DESCRIPTOR2));
+ displayUnknown = TRUE;
+ break;
+ }
+
+ confXmlDesc->EndpointDescriptor = gcnew EndpointDescriptorType();
+
+ if (NULL != deviceInfo->ConnectionInfo)
+ {
+ // Add endpoint descriptor
+ XmlAddEndpointDescriptor(
+ confXmlDesc->EndpointDescriptor,
+ (PUSB_ENDPOINT_DESCRIPTOR) commonDesc,
+ deviceInfo->ConnectionInfo->Speed);
+ }
+
+ break;
+
+ case USB_HID_DESCRIPTOR_TYPE:
+ if (commonDesc->bLength < sizeof(USB_HID_DESCRIPTOR))
+ {
+ // Validate HID
+ confXmlDesc->HidError = String::Format(
+ "ERROR: HID bLength value incorrect Obtained: {0} Expected: {1}",
+ commonDesc->bLength,
+ sizeof(USB_HID_DESCRIPTOR));
+ displayUnknown = TRUE;
+ break;
+ }
+
+ // Add HID descriptor
+ confXmlDesc->HidDescriptor = gcnew UsbDeviceHidDescriptorType();
+ XmlAddHidDescriptor(
+ confXmlDesc->HidDescriptor,
+ (PUSB_HID_DESCRIPTOR) commonDesc
+ );
+ break;
+
+ case USB_OTG_DESCRIPTOR_TYPE:
+ if (commonDesc->bLength < sizeof(USB_OTG_DESCRIPTOR))
+ {
+ // Validate length
+ confXmlDesc->HidError = String::Format(
+ "ERROR: OTG bLength value incorrect Obtained: {0} Expected: {1}",
+ commonDesc->bLength,
+ sizeof(USB_OTG_DESCRIPTOR));
+ displayUnknown = TRUE;
+ break;
+ }
+
+ // Add OTG descriptor
+ confXmlDesc->OtgDescriptor = gcnew UsbDeviceOTGDescriptorType();
+ XmlAddOTGDescriptor(
+ confXmlDesc->OtgDescriptor,
+ (PUSB_OTG_DESCRIPTOR) commonDesc
+ );
+ break;
+
+ case USB_IAD_DESCRIPTOR_TYPE:
+ if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR))
+ {
+ // Validate length
+ confXmlDesc->IadError = String::Format(
+ "ERROR: IAD bLength value incorrect",
+ commonDesc->bLength,
+ sizeof(USB_OTG_DESCRIPTOR));
+ displayUnknown = TRUE;
+ }
+
+ // Add IAD descriptor
+ confXmlDesc->IadDescriptor = gcnew UsbDeviceIADDescriptorType();
+ XmlAddIADDescriptor(
+ confXmlDesc->IadDescriptor,
+ (PUSB_IAD_DESCRIPTOR) commonDesc,
+ stringDesc,
+ numInterfaces
+ );
+ break;
+
+ default:
+ // Interface class device (?)
+ confXmlDesc->DeviceDetails = XmlGetDeviceClass(
+ ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceClass,
+ ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceSubClass,
+ ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceProtocol
+ );
+ break;
+ }
+
+ if (displayUnknown)
+ {
+ // Add unknown descriptor
+ confXmlDesc->UnknownDescriptor = XmlGetUnknownDescriptor(commonDesc);
+ }
+ return;
+}
+
+/*****************************************************************************
+
+ XmlAddConnectionInfoSt()
+
+ This routine adds connection information structures for the device
+ *****************************************************************************/
+void XmlAddConnectionInfoSt(
+ NodeConnectionInfoExStructType ^xmlConnectionInfoSt,
+ PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo,
+ PDEVICE_INFO_NODE pNode)
+{
+ NodeConnectionInfoExStructType ^nS = xmlConnectionInfoSt;
+
+ nS->ConnectionIndex = connectionInfo->ConnectionIndex;
+
+ nS->DeviceDescriptor = gcnew UsbDeviceDescriptorType();
+
+ XmlAddUsbDeviceDescriptor(nS->DeviceDescriptor, &(connectionInfo->DeviceDescriptor));
+
+ nS->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue;
+ nS->Speed = connectionInfo->Speed;
+ nS->SpeedStr = static_cast<UsbConnectionSpeedType> (connectionInfo->Speed);
+ nS->DeviceIsHub = connectionInfo->DeviceIsHub? true: false;
+ nS->NumOfOpenPipes = connectionInfo->NumberOfOpenPipes;
+ nS->UsbConnectionStatus = static_cast<UsbConnectionStatusType> (connectionInfo->ConnectionStatus);
+
+ if(NULL != pNode)
+ {
+ nS->DevicePowerState = static_cast<DevicePowerStateType>(pNode->LatestDevicePowerState);
+ }
+ else
+ {
+ nS->DevicePowerState = static_cast<DevicePowerStateType>(PowerDeviceUnspecified);
+ }
+
+ // Add the pipe list
+ if (connectionInfo->NumberOfOpenPipes > 0)
+ {
+ nS->Pipe = gcnew array <UsbPipeInfoType ^>(connectionInfo->NumberOfOpenPipes);
+ XmlAddPipeInformation(
+ nS->Pipe,
+ connectionInfo->PipeList,
+ connectionInfo->NumberOfOpenPipes,
+ connectionInfo->Speed
+ );
+ }
+
+ return;
+}
+
+/*****************************************************************************
+
+ XmlGetLangIdString()
+
+ Obtains the language string for given string descriptor index
+ *****************************************************************************/
+String ^ XmlGetLangIdString(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc)
+{
+ String ^langIdStr = nullptr;
+ bool foundDescriptor = false;
+
+ while(stringDesc)
+ {
+ if (stringDesc->DescriptorIndex == index)
+ {
+ langIdStr = PACHAR_TO_STRING(GetLangIDString(stringDesc->LanguageID));
+
+ if (langIdStr == nullptr)
+ {
+ langIdStr = gcnew String("WARNING: Invalid language ID: " + stringDesc->LanguageID);
+ }
+ foundDescriptor = true;
+ break;
+ }
+ stringDesc = stringDesc->Next;
+ }
+
+ if (foundDescriptor == false)
+ {
+ // If no descriptor was found, return error message in field
+ langIdStr = gcnew String("ERROR: No String descriptor for index " + index);
+ }
+
+ return langIdStr;
+}
+
+/*****************************************************************************
+
+ XmlGetStringDescriptor()
+
+ Obtains the string descriptor for given string descriptor index
+ *****************************************************************************/
+
+String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly)
+{
+ ULONG nBytes = 0;
+
+ CHAR pString[MAX_STRING_DESCRIPTOR_LENGTH];
+ String ^desc = nullptr;
+ bool foundDescriptor = false;
+ bool foundNonEnglishDescriptor = false;
+
+ ZeroMemory(pString, MAX_STRING_DESCRIPTOR_LENGTH);
+
+ while(stringDesc)
+ {
+ if (stringDesc->DescriptorIndex == index)
+ {
+ if (enOnly && stringDesc->LanguageID != STRING_DESCRIPTOR_EN_LANGUAGE_ID)
+ {
+ // If we are required to return only english descriptor, continue
+ foundNonEnglishDescriptor = true;
+ continue;
+ }
+
+ nBytes = WideCharToMultiByte(
+ CP_ACP,
+ WC_NO_BEST_FIT_CHARS,
+ stringDesc->StringDescriptor->bString,
+ (stringDesc->StringDescriptor->bLength -2)/2,
+ pString,
+ MAX_STRING_DESCRIPTOR_LENGTH,
+ NULL,
+ NULL
+ );
+
+ if (nBytes)
+ {
+ foundDescriptor = true;
+ desc = PACHAR_TO_STRING(pString);
+ }
+ break;
+ }
+ stringDesc = stringDesc->Next;
+ }
+
+ if ((foundDescriptor == false) && (foundNonEnglishDescriptor == false))
+ {
+ // If no descriptor was found, return error message in field
+ desc = gcnew String("ERROR: No String descriptor for index " +
+ index);
+ }
+ else if ((foundDescriptor == false) && (foundNonEnglishDescriptor == true) && (enOnly))
+ {
+ desc = gcnew String("ERROR: The index " + index + " does not support English(US)");
+ }
+
+ return desc;
+}
+
+/*****************************************************************************
+
+ XmlGetDeviceClassString()
+
+ Returns the device class string for given device class ID
+ *****************************************************************************/
+
+String ^ XmlGetDeviceClassString(UCHAR deviceClass)
+{
+ String ^ deviceClassStr = nullptr;
+
+ // Not an IAD device
+ switch (deviceClass)
+ {
+ case USB_INTERFACE_CLASS_DEVICE:
+ deviceClassStr = gcnew String("Interface Class Defined Device");
+ break;
+
+ case USB_COMMUNICATION_DEVICE:
+ deviceClassStr = gcnew String("Communication Device");
+ break;
+
+ case USB_HUB_DEVICE:
+ deviceClassStr = gcnew String("Hub Device");
+ break;
+
+ case USB_DIAGNOSTIC_DEVICE:
+ deviceClassStr = gcnew String("Diagnostic Device");
+ break;
+
+ case USB_WIRELESS_CONTROLLER_DEVICE:
+ deviceClassStr = gcnew String("Wireless Controller(Bluetooth) Device");
+ break;
+
+ case USB_VENDOR_SPECIFIC_DEVICE:
+ deviceClassStr = gcnew String("Vendor specific device");
+ break;
+
+ default:
+ deviceClassStr= gcnew String("ERROR: unknown bDeviceClass" + deviceClass);
+ break;
+ }
+ return deviceClassStr;
+}
+
+
+/*****************************************************************************
+
+ XmlAddDeviceClassDetails()
+
+ This routine adds device class details
+ *****************************************************************************/
+bool XmlAddDeviceClassDetails(
+ UsbDeviceClassDetailsType ^ deviceDetails,
+ PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo,
+ PUSBDEVICEINFO deviceInfo)
+{
+ UINT uIADcount = 0;
+ bool tog = true;
+
+ uIADcount = IsIADDevice((PUSBDEVICEINFO) deviceInfo);
+
+ if (uIADcount)
+ {
+ // IAD device, check validity of device class
+ if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE)
+ {
+ tog = false;
+ deviceDetails->DeviceType = gcnew String("Multi-interface Function Code Device");
+ }
+ else {
+ deviceDetails->DeviceTypeError = gcnew String("ERROR: device class should be Multi-interface Function " +
+ USB_MISCELLANEOUS_DEVICE +
+ "is used");
+ }
+ deviceDetails->UvcVersion = IsUVCDevice((PUSBDEVICEINFO) deviceInfo);
+
+ // This device configuration has 1 or more IAD descriptors
+ if (connectionInfo->DeviceDescriptor.bDeviceSubClass == USB_COMMON_SUB_CLASS)
+ {
+ deviceDetails->SubclassType = gcnew String("Common Class Sub Class");
+ }
+ else
+ {
+ deviceDetails->SubclassTypeError = gcnew String("ERROR: device SubClass should be USB Common Sub Class" +
+ USB_COMMON_SUB_CLASS +
+ " when IAD descriptor is used");
+ }
+
+ // Check device protocol
+ if (connectionInfo->DeviceDescriptor.bDeviceProtocol == USB_IAD_PROTOCOL)
+ {
+ deviceDetails->DeviceProtocol = gcnew String("Interface Association Descriptor protocol");
+ }
+ else
+ {
+ deviceDetails->DeviceProtocolError = gcnew String("ERROR: device Protocol should be USB IAD Protocol " +
+ USB_IAD_PROTOCOL +
+ " when IAD descriptor is used");
+ }
+
+ }
+ else
+ {
+ deviceDetails->DeviceType = XmlGetDeviceClassString(connectionInfo->DeviceDescriptor.bDeviceClass);
+
+ if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE)
+ {
+ deviceDetails->DeviceTypeError = gcnew String("ERROR: Multi-interface Function code " +
+ connectionInfo->DeviceDescriptor.bDeviceClass +
+ " used for device with no IAD descriptors");
+ }
+
+ if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_COMMUNICATION_DEVICE ||
+ connectionInfo->DeviceDescriptor.bDeviceClass == USB_HUB_DEVICE ||
+ connectionInfo->DeviceDescriptor.bDeviceClass == USB_DIAGNOSTIC_DEVICE ||
+ connectionInfo->DeviceDescriptor.bDeviceClass == USB_WIRELESS_CONTROLLER_DEVICE ||
+ connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE ||
+ connectionInfo->DeviceDescriptor.bDeviceClass == USB_VENDOR_SPECIFIC_DEVICE)
+ {
+ tog = false;
+ }
+
+ // Not an IAD device, so all subclass values are invalid
+ if (connectionInfo->DeviceDescriptor.bDeviceSubClass > 0x00 &&
+ connectionInfo->DeviceDescriptor.bDeviceSubClass < 0xFF)
+ {
+ deviceDetails->SubclassTypeError = gcnew String("ERROR: bDeviceSubClass is invalid - " +
+ connectionInfo->DeviceDescriptor.bDeviceSubClass);
+ }
+
+ // Not an IAD device, so all subclass values are invalid, check protocol
+ if (connectionInfo->DeviceDescriptor.bDeviceProtocol > 0x00 &&
+ connectionInfo->DeviceDescriptor.bDeviceProtocol < 0xFF && tog==1)
+ {
+ deviceDetails->DeviceProtocolError = gcnew String("ERROR: bDeviceProtocol is invalid - " +
+ connectionInfo->DeviceDescriptor.bDeviceProtocol);
+ }
+ }
+
+ return tog;
+}
+
+/*****************************************************************************
+
+ XmlAddConnectionInfo()
+
+ This routine adds connection information for the device
+ *****************************************************************************/
+void XmlAddConnectionInfo(
+ NodeConnectionInfoExType ^xmlConnectionInfo,
+ PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo,
+ PUSBDEVICEINFO deviceInfo,
+ PSTRING_DESCRIPTOR_NODE stringDesc,
+ PDEVICE_INFO_NODE pNode)
+{
+ NodeConnectionInfoExType ^ nc = xmlConnectionInfo;
+ bool tog = true;
+ nc->ConnectionInfoStruct = gcnew NodeConnectionInfoExStructType();
+
+ // Update the structure
+ XmlAddConnectionInfoSt(nc->ConnectionInfoStruct, connectionInfo, pNode);
+
+ // Add verbose fields
+ if (connectionInfo->ConnectionStatus == NoDeviceConnected)
+ {
+ // No device connected, nothing to do
+ return;
+ }
+
+ if (connectionInfo->DeviceDescriptor.iProduct)
+ {
+ // Add EN version of string descriptor
+
+ nc->IProductStringDescEn = XmlGetStringDescriptor(
+ connectionInfo->DeviceDescriptor.iProduct,
+ stringDesc,
+ true);
+ }
+
+ // Check open pipes count
+ if (connectionInfo->NumberOfOpenPipes == 0)
+ {
+ nc->PipeInfoError = gcnew String("ERROR: No open pipes");
+ }
+
+ // Check device descriptor length
+ if (connectionInfo->DeviceDescriptor.bLength != DEVICE_DESCRIPTOR_LENGTH)
+ {
+ nc->LengthError = gcnew String("ERROR: bLength " +
+ connectionInfo->DeviceDescriptor.bLength +
+ " incorrect, should be " +
+ DEVICE_DESCRIPTOR_LENGTH
+ );
+ }
+
+ // Check for device error
+ if ((connectionInfo->ConnectionStatus == DeviceFailedEnumeration) ||
+ (connectionInfo->ConnectionStatus == DeviceGeneralFailure))
+ {
+ nc->DeviceError = gcnew String("ERROR: Device enumeration failure");
+ }
+ else
+ {
+ nc->DeviceClassDetails = gcnew UsbDeviceClassDetailsType();
+
+ // Add device class details
+ tog = XmlAddDeviceClassDetails(
+ nc->DeviceClassDetails,
+ connectionInfo,
+ deviceInfo);
+
+ nc->MaxPacketSizeInBytes = connectionInfo->DeviceDescriptor.bMaxPacketSize0;
+
+ // Validate speed
+ switch (connectionInfo->Speed)
+ {
+ case UsbLowSpeed:
+ if (connectionInfo->DeviceDescriptor.bMaxPacketSize0 != 8)
+ {
+ nc->PacketSizeError = gcnew String("ERROR: Low Speed Devices require bMaxPacketSize0 = 8");
+ }
+ break;
+ case UsbFullSpeed:
+ if (!(connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 8 ||
+ connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 16 ||
+ connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 32 ||
+ connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 64))
+ {
+ nc->PacketSizeError = gcnew String("ERROR: Full Speed Devices require bMaxPacketSize0 = 8, 16, 32, or 64");
+ }
+ break;
+ case UsbHighSpeed:
+ if (connectionInfo->DeviceDescriptor.bMaxPacketSize0 != 64)
+ {
+ nc->PacketSizeError = gcnew String("ERROR: High Speed Devices require bMaxPacketSize0 = 64");
+ }
+ break;
+ }
+
+ // Get string descriptors
+ nc->VendorString = PACHAR_TO_STRING(GetVendorString(connectionInfo->DeviceDescriptor.idVendor));
+
+ nc->ManufacturerString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iManufacturer, stringDesc, false);
+ nc->ProductString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iProduct, stringDesc, false);
+ nc->LangIdString = XmlGetLangIdString(connectionInfo->DeviceDescriptor.iProduct, stringDesc);
+ nc->SerialString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iSerialNumber, stringDesc, false);
+
+ // Validate configuration
+ if (connectionInfo->DeviceDescriptor.bNumConfigurations != 1)
+ {
+ nc->ConfigurationCountError = gcnew String("WARNING: Most host controllers will only work with "\
+ "one configuration per speed");
+ }
+ }
+ return;
+}
+
+
+/*****************************************************************************
+
+ XmlAddExternalHub()
+
+ Add a external to the parent Host Controller or hub. This is determined by the
+ last object pushed on the stack
+ *****************************************************************************/
+HRESULT XmlAddExternalHub(PSTR ehName, PUSBEXTERNALHUBINFO ehInfo)
+{
+ HRESULT hr = S_OK;
+ Object ^ parent = gXmlStack->Peek();
+ ExternalHubType ^exHub = nullptr;
+
+ UNREFERENCED_PARAMETER(ehName);
+
+ if (NULL == ehInfo)
+ {
+ return E_FAIL;
+ }
+
+ exHub = AddExternalHub(parent);
+
+ if (exHub != nullptr)
+ {
+ exHub->HubName = PACHAR_TO_STRING(ehInfo->HubName);
+
+ if (NULL != ehInfo->UsbDeviceProperties)
+ {
+ exHub->HwId = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->HwId);
+ exHub->DeviceId = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceId);
+ exHub->ServiceName = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->Service);
+ exHub->DeviceName = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceDesc);
+ exHub->DeviceClass = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceClass);
+ }
+
+ exHub->HubNodeInformation = gcnew HubNodeInformationType();
+ XmlAddHubNodeInformation(exHub->HubNodeInformation, ehInfo->HubInfo);
+
+ exHub->HubInformationEx = gcnew HubInformationExType();
+ XmlAddHubInformationEx(exHub->HubInformationEx, ehInfo->HubInfoEx);
+
+ exHub->HubCapabilityEx = gcnew HubCapabilitiesExType();
+ XmlAddHubCapabilitiesEx(exHub->HubCapabilityEx, ehInfo->HubCapabilityEx);
+
+ exHub->ConnectionInfo = gcnew NodeConnectionInfoExType();
+
+ // Update protocol
+ if (NULL != ehInfo->ConnectionInfo)
+ {
+ switch(ehInfo->ConnectionInfo->Speed)
+ {
+ case UsbLowSpeed:
+ case UsbFullSpeed:
+ exHub->UsbProtocol = gcnew String(USB_1_1);
+ break;
+ case UsbHighSpeed:
+ exHub->UsbProtocol = gcnew String(USB_2_0);
+ break;
+ case UsbSuperSpeed:
+ exHub->UsbProtocol = gcnew String(USB_3_0);
+ break;
+ }
+ }
+
+ // Add connection info
+ XmlAddConnectionInfo(
+ exHub->ConnectionInfo,
+ ehInfo->ConnectionInfo,
+ (PUSBDEVICEINFO) ehInfo,
+ ehInfo->StringDescs,
+ ehInfo->DeviceInfoNode
+ );
+
+ // Add port connectors
+ if (NULL != ehInfo->PortConnectorProps)
+ {
+ exHub->PortConnector = gcnew PortConnectorType();
+
+ XmlAddPortConnectorProps(
+ exHub->PortConnector,
+ ehInfo->PortConnectorProps
+ );
+ }
+ // Add connection info V2
+ exHub->ConnectionInfoV2 = gcnew NodeConnectionInfoExV2Type();
+
+ XmlAddConnectionInfoV2(
+ exHub->ConnectionInfoV2,
+ ehInfo->ConnectionInfoV2
+ );
+
+ // Add configuration descriptor
+ if (NULL != ehInfo->ConfigDesc)
+ {
+ exHub->DeviceConfiguration = XmlGetConfigDescriptors(
+ (PUSBDEVICEINFO) ehInfo,
+ (PUSB_CONFIGURATION_DESCRIPTOR) (ehInfo->ConfigDesc + 1),
+ ehInfo->StringDescs
+ );
+ }
+
+ // Add BOS descriptor
+ if (NULL != ehInfo->BosDesc)
+ {
+ exHub->BosDescriptor = XmlGetBosDescriptor((PUSB_BOS_DESCRIPTOR) (ehInfo->BosDesc + 1));
+ }
+
+ gXmlStack->Push(exHub);
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+ return hr;
+}
+
+/*****************************************************************************
+
+ XmlGetBosDescriptor()
+
+ Gets the Bos descriptor object for given BOS descriptor
+ *****************************************************************************/
+UsbBosDescriptorType ^ XmlGetBosDescriptor(PUSB_BOS_DESCRIPTOR bosDesc)
+{
+ PUSB_COMMON_DESCRIPTOR commonDesc = NULL;
+ PUSB_DEVICE_CAPABILITY_DESCRIPTOR capDesc = NULL;
+ UsbBosDescriptorType ^ bosXmlDesc = nullptr;
+ ArrayList ^usb20CapExtDescList = gcnew ArrayList();
+ ArrayList ^usbSuperSpeedExtDescList = gcnew ArrayList();
+ ArrayList ^usbContIdCapExtDescList = gcnew ArrayList();
+ ArrayList ^usbUnknownDescList = gcnew ArrayList();
+
+ if(NULL == bosDesc)
+ {
+ return nullptr;
+ }
+
+ // Initialize attributes
+ bosXmlDesc = gcnew UsbBosDescriptorType();
+ bosXmlDesc->BLength = bosDesc->bLength;
+ bosXmlDesc->BDescriptorType = bosDesc->bDescriptorType;
+ bosXmlDesc->WTotalLength = bosDesc->wTotalLength;
+ bosXmlDesc->BNumDeviceCaps = bosDesc->bNumDeviceCaps;
+
+ commonDesc = (PUSB_COMMON_DESCRIPTOR) bosDesc;
+
+ while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR) bosDesc,
+ bosDesc->wTotalLength,
+ commonDesc,
+ -1)) != NULL)
+ {
+ switch (commonDesc->bDescriptorType)
+ {
+ case USB_DEVICE_CAPABILITY_DESCRIPTOR_TYPE:
+ capDesc = (PUSB_DEVICE_CAPABILITY_DESCRIPTOR)commonDesc;
+ switch (capDesc->bDevCapabilityType)
+ {
+ case USB_DEVICE_CAPABILITY_USB20_EXTENSION:
+ usb20CapExtDescList->Add(
+ XmlGetUsb20CapabilityExtensionDescriptor(
+ (PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR)capDesc
+ )
+ );
+ break;
+ case USB_DEVICE_CAPABILITY_SUPERSPEED_USB:
+ usbSuperSpeedExtDescList->Add(
+ XmlGetSuperSpeedCapabilityExtensionDescriptor(
+ (PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR)capDesc
+ )
+ );
+ break;
+ case USB_DEVICE_CAPABILITY_CONTAINER_ID:
+ usbContIdCapExtDescList->Add(
+ XmlGetContainerIdCapabilityExtensionDescriptor(
+ (PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR)capDesc
+ )
+ );
+ break;
+ default:
+ usbUnknownDescList->Add(
+ XmlGetUnknownDescriptor(
+ (PUSB_COMMON_DESCRIPTOR) capDesc
+ )
+ );
+ break;
+ }
+ break;
+ default:
+ usbUnknownDescList->Add(XmlGetUnknownDescriptor(commonDesc));
+ break;
+ }
+ }
+
+ // Convert lists to arrays for and add to Bos Descriptor
+ bosXmlDesc->UnknownDescriptor = reinterpret_cast<array<UsbDeviceUnknownDescriptorType ^>^> (
+ usbUnknownDescList->ToArray(UsbDeviceUnknownDescriptorType::typeid)
+ );
+ bosXmlDesc->UsbSuperSpeedExtensionDescriptor = reinterpret_cast<array<UsbSuperSpeedExtensionDescriptorType ^>^> (
+ usbSuperSpeedExtDescList->ToArray(UsbSuperSpeedExtensionDescriptorType::typeid)
+ );
+ bosXmlDesc->UsbUsb20ExtensionDescriptor = reinterpret_cast<array<UsbUsb20ExtensionDescriptorType ^>^> (
+ usb20CapExtDescList->ToArray(UsbUsb20ExtensionDescriptorType::typeid)
+ );
+ bosXmlDesc->UsbDispContIdCapExtDescriptor = reinterpret_cast<array<UsbDispContIdCapExtDescriptorType ^>^> (
+ usbContIdCapExtDescList->ToArray(UsbDispContIdCapExtDescriptorType::typeid)
+ );
+
+ return bosXmlDesc;
+}
+
+
+/*****************************************************************************
+
+ XmlGetUsb20CapabilityExtensionDescriptor()
+
+ Gets a Usb20Capability extension descriptor object from the given descriptor
+ *****************************************************************************/
+UsbUsb20ExtensionDescriptorType ^ XmlGetUsb20CapabilityExtensionDescriptor(
+ PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR capDesc
+ )
+{
+ UsbUsb20ExtensionDescriptorType ^ capXmlDesc = nullptr;
+
+ if(NULL == capDesc)
+ {
+ return nullptr;
+ }
+
+ capXmlDesc = gcnew UsbUsb20ExtensionDescriptorType();
+
+ capXmlDesc->BLength = capDesc->bLength;
+ capXmlDesc->BDescriptorType = capDesc->bDescriptorType;
+ capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType;
+ capXmlDesc->BmAttributes = capDesc->bmAttributes.AsUlong;
+
+ if (capDesc->bmAttributes.AsUlong & USB_DEVICE_CAPABILITY_USB20_EXTENSION_BMATTRIBUTES_RESERVED_MASK)
+ {
+ capXmlDesc->ReservedBitError = gcnew String("ERROR: bits 31..2 and bit 0 are reserved and must be 0");
+ }
+ if (capDesc->bmAttributes.LPMCapable == 1)
+ {
+ capXmlDesc->SupportsLinkPowerManagement = true;
+ }
+
+ return capXmlDesc;
+}
+
+/*****************************************************************************
+
+ XmlGetSuperSpeedCapabilityExtensionDescriptor()
+
+ Gets a Super speed capability extension descriptor object from the given descriptor
+ *****************************************************************************/
+UsbSuperSpeedExtensionDescriptorType ^ XmlGetSuperSpeedCapabilityExtensionDescriptor(
+ PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR capDesc
+ )
+{
+ UsbSuperSpeedExtensionDescriptorType ^ capXmlDesc = nullptr;
+
+ if(NULL == capDesc)
+ {
+ return nullptr;
+ }
+
+ capXmlDesc = gcnew UsbSuperSpeedExtensionDescriptorType();
+
+ capXmlDesc->BLength = capDesc->bLength;
+ capXmlDesc->BDescriptorType = capDesc->bDescriptorType;
+ capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType;
+ capXmlDesc->BmAttributes = capDesc->bmAttributes;
+ capXmlDesc->BU1DevExitLat = capDesc->bU1DevExitLat;
+ capXmlDesc->WSpeedsSupported = capDesc->wSpeedsSupported;
+ capXmlDesc->WU2DevExitLat = capDesc->wU2DevExitLat;
+ capXmlDesc->BFunctionalitySupport = capDesc->bFunctionalitySupport;
+
+ // Add descriptive fields
+ if (capDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_RESERVED_MASK)
+ {
+ capXmlDesc->ReservedAttributesBitError = gcnew String("ERROR: bits 7:2 and bit 0 are reserved");
+ }
+ if (capDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_LTM_CAPABLE)
+ {
+ capXmlDesc->LatencyToleranceMsgCapable = true;
+ }
+ if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_LOW)
+ {
+ capXmlDesc->SupportsLowSpeed = true;
+ }
+ if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_FULL)
+ {
+ capXmlDesc->SupportsFullSpeed = true;
+ }
+ if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_HIGH)
+ {
+ capXmlDesc->SupportsHighSpeed = true;
+ }
+ if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_SUPER)
+ {
+ capXmlDesc->SupportsSuperSpeed = true;
+ }
+ if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_RESERVED_MASK)
+ {
+ capXmlDesc->ReservedSpeedError = gcnew String("ERROR: bits 15:4 are reserved");
+ }
+
+
+ switch (capDesc->bFunctionalitySupport)
+ {
+ case UsbLowSpeed:
+ capXmlDesc->LowestSpeed = gcnew String("low-speed");
+ break;
+ case UsbFullSpeed:
+ capXmlDesc->LowestSpeed = gcnew String("full-speed");
+ break;
+ case UsbHighSpeed:
+ capXmlDesc->LowestSpeed = gcnew String("high-speed");
+ break;
+ case UsbSuperSpeed:
+ capXmlDesc->LowestSpeed = gcnew String("SuperSpeed");
+ break;
+ default:
+ capXmlDesc->LowestSpeed = gcnew String("ERROR: Invalid value");
+ break;
+ }
+
+ if (capDesc->bU1DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U1_DEVICE_EXIT_MAX_VALUE)
+ {
+ capXmlDesc->U1DevExitLatencyString = String::Format("Less than {0} micro-seconds", capDesc->bU1DevExitLat);
+ }
+ else
+ {
+ capXmlDesc->U1DevExitLatencyString = gcnew String("ERROR: Invalid value");
+ }
+
+ if (capDesc->wU2DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U2_DEVICE_EXIT_MAX_VALUE)
+ {
+ capXmlDesc->U2DevExitLatencyString = String::Format("Less than {0} micro-seconds", capDesc->wU2DevExitLat);
+ }
+ else
+ {
+ capXmlDesc->U2DevExitLatencyString = gcnew String("ERROR: Invalid value");
+ }
+
+ return capXmlDesc;
+}
+
+/*****************************************************************************
+
+ XmlGetContainerIdCapabilityExtensionDescriptor()
+
+ Gets a Usb20Capability extension descriptor object from the given descriptor
+ *****************************************************************************/
+UsbDispContIdCapExtDescriptorType ^ XmlGetContainerIdCapabilityExtensionDescriptor(
+ PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR capDesc
+ )
+{
+ UsbDispContIdCapExtDescriptorType ^ capXmlDesc = nullptr;
+ LPGUID pGuid = NULL;
+
+ if(NULL == capDesc)
+ {
+ return nullptr;
+ }
+
+ capXmlDesc = gcnew UsbDispContIdCapExtDescriptorType();
+
+ capXmlDesc->BLength = capDesc->bLength;
+ capXmlDesc->BDescriptorType = capDesc->bDescriptorType;
+ capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType;
+ capXmlDesc->BReserved = capDesc->bReserved;
+
+ if (capDesc->bReserved != 0)
+ {
+ capXmlDesc->ReservedBitError = gcnew String("ERROR: field is reserved and should be zero");
+ }
+
+ pGuid = (LPGUID) capDesc->ContainerID;
+
+ capXmlDesc->ContainerIdStr = String::Format("{0:X}-{1:X}-{2:X}-{3:X}{4:X}-{5:X}{6:X}{7:X}{8:X}{9:X}{10:X}",
+ pGuid->Data1,
+ pGuid->Data2,
+ pGuid->Data3,
+ pGuid->Data4[0],
+ pGuid->Data4[1],
+ pGuid->Data4[2],
+ pGuid->Data4[3],
+ pGuid->Data4[4],
+ pGuid->Data4[5],
+ pGuid->Data4[6],
+ pGuid->Data4[7]);
+
+ return capXmlDesc;
+}
+
+/*****************************************************************************
+
+ XmlAddUsbDevice()
+
+ Add a external to the parent Host Controller or hub. This is determined by the
+ last object pushed on the stack
+ *****************************************************************************/
+HRESULT XmlAddUsbDevice(PSTR devName, PUSBDEVICEINFO deviceInfo)
+{
+ HRESULT hr = S_OK;
+ Object ^ parent = gXmlStack->Peek();
+ UsbDeviceType ^usbDevice = nullptr;
+ NoDeviceType ^noDevice = nullptr;
+
+ if (NULL == deviceInfo)
+ {
+ return E_FAIL;
+ }
+
+ if (deviceInfo->ConfigDesc == NULL)
+ {
+ // There is no USB device on this port, add a NoDevice type here instead of USB device
+ noDevice = AddDisconnectedPort(parent);
+
+ if (nullptr != noDevice)
+ {
+ noDevice->UsbPortNumber = gcnew String("");
+ noDevice->UsbPortNumber += deviceInfo->ConnectionInfo->ConnectionIndex;
+ noDevice->Name = PACHAR_TO_STRING(devName);
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+ }
+
+ else
+ {
+ usbDevice = AddUsbDevice(parent);
+
+ if (nullptr != usbDevice)
+ {
+ // Update device information
+ if (NULL != deviceInfo->UsbDeviceProperties)
+ {
+ usbDevice->HwId = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->HwId);
+ usbDevice->DeviceId = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceId);
+ usbDevice->ServiceName = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->Service);
+ usbDevice->DeviceName = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceDesc);
+ usbDevice->DeviceClass = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceClass);
+ }
+
+ // Update port number
+ usbDevice->UsbPortNumber = gcnew String("");
+ usbDevice->UsbPortNumber += deviceInfo->ConnectionInfo->ConnectionIndex;
+ usbDevice->ConnectionInfo = gcnew NodeConnectionInfoExType();
+
+ // Update protocol
+ if (NULL != deviceInfo->ConnectionInfo)
+ {
+ switch(deviceInfo->ConnectionInfo->Speed)
+ {
+ case UsbLowSpeed:
+ case UsbFullSpeed:
+ usbDevice->UsbProtocol = gcnew String(USB_1_1);
+ break;
+ case UsbHighSpeed:
+ usbDevice->UsbProtocol = gcnew String(USB_2_0);
+ break;
+ case UsbSuperSpeed:
+ usbDevice->UsbProtocol = gcnew String(USB_3_0);
+ break;
+ }
+ }
+
+ // Add connection info
+ XmlAddConnectionInfo(
+ usbDevice->ConnectionInfo,
+ deviceInfo->ConnectionInfo,
+ (PUSBDEVICEINFO) deviceInfo,
+ deviceInfo->StringDescs,
+ deviceInfo->DeviceInfoNode
+ );
+
+ // Add port connector
+ if (NULL != deviceInfo->PortConnectorProps)
+ {
+ usbDevice->PortConnector = gcnew PortConnectorType();
+
+ XmlAddPortConnectorProps(
+ usbDevice->PortConnector,
+ deviceInfo->PortConnectorProps
+ );
+ }
+
+ // Add connectiontion info V2
+ if (NULL != deviceInfo->ConnectionInfoV2)
+ {
+ usbDevice->ConnectionInfoV2 = gcnew NodeConnectionInfoExV2Type();
+ XmlAddConnectionInfoV2(
+ usbDevice->ConnectionInfoV2,
+ deviceInfo->ConnectionInfoV2
+ );
+ }
+
+ // Add configuration descriptor
+ if (NULL != deviceInfo->ConfigDesc)
+ {
+ // The device configuration is allocated by XmlGetConfigDescriptors()
+ usbDevice->DeviceConfiguration = XmlGetConfigDescriptors(
+ (PUSBDEVICEINFO) deviceInfo,
+ (PUSB_CONFIGURATION_DESCRIPTOR) (deviceInfo->ConfigDesc + 1),
+ deviceInfo->StringDescs
+ );
+ }
+
+ // Add BOS descriptor
+ if (NULL != deviceInfo->BosDesc)
+ {
+ usbDevice->BosDescriptor = XmlGetBosDescriptor((PUSB_BOS_DESCRIPTOR) (deviceInfo->BosDesc + 1));
+ }
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+ }
+ return hr;
+}
+
+/*****************************************************************************
+
+ XmlAddRootHub()
+
+ Add a root hub to the parent Host Controller
+ *****************************************************************************/
+HRESULT XmlAddRootHub(PSTR rhName, PUSBROOTHUBINFO rhInfo)
+{
+ HRESULT hr = S_OK;
+ Object ^ parent = gXmlStack->Peek();
+ HostControllerType ^ hcParent = nullptr;
+ PSTR rootHubName = rhInfo->HubName;
+
+ UNREFERENCED_PARAMETER(rhName);
+
+ hcParent = dynamic_cast<HostControllerType ^> (parent);
+
+ if (hcParent != nullptr)
+ {
+ RootHubType ^ rh = nullptr;
+ hcParent = (HostControllerType ^) parent;
+ hcParent->RootHub = gcnew RootHubType();
+
+ rh = hcParent->RootHub;
+ rh->HubName = PACHAR_TO_STRING(rootHubName);
+
+ if (NULL != rhInfo->UsbDeviceProperties)
+ {
+ rh->HwId = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->HwId);
+ rh->DeviceId = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceId);
+ rh->ServiceName = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->Service);
+ rh->DeviceName = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceDesc);
+ rh->DeviceClass = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceClass);
+
+ // Roothub protocol is same as HC protocol
+ rh->UsbProtocol = hcParent->UsbProtocol;
+ }
+
+ rh->HubNodeInformation = gcnew HubNodeInformationType();
+ XmlAddHubNodeInformation(rh->HubNodeInformation, rhInfo->HubInfo);
+
+ rh->HubInformationEx = gcnew HubInformationExType();
+ XmlAddHubInformationEx(rh->HubInformationEx, rhInfo->HubInfoEx);
+
+ rh->HubCapabilityEx = gcnew HubCapabilitiesExType();
+ XmlAddHubCapabilitiesEx(rh->HubCapabilityEx, rhInfo->HubCapabilityEx);
+
+ // Push root hub on to stack
+ gXmlStack->Push(rh);
+ }
+ else
+ {
+ // Root hub should be connected to a host controller
+ hr = E_FAIL;
+ }
+ return S_OK;
+}
+
+/*****************************************************************************
+
+ XmlSetVersion()
+
+ Set version information in XML tree
+ *****************************************************************************/
+VOID XmlSetVersion(
+ UCHAR uvcMajorVersion,
+ UCHAR uvcMinorVersion,
+ UCHAR uvcMajorSpecVersion,
+ UCHAR uvcMinorSpecVersion
+ )
+{
+ MachineInfoType ^ mInfo;
+ gXmlView->MachineInfo = gcnew MachineInfoType();
+
+ mInfo = gXmlView->MachineInfo;
+
+ mInfo->UvcMajorVersion = uvcMajorVersion;
+ mInfo->UvcMinorVersion = uvcMinorVersion;
+ mInfo->UvcMajorSpecVersion = uvcMajorSpecVersion;
+ mInfo->UvcMinorSpecVersion = uvcMinorSpecVersion;
+
+}
+
+/*****************************************************************************
+
+ InitXmlHelper()
+
+ Initialize XML helper
+ *****************************************************************************/
+HRESULT InitXmlHelper()
+{
+ HRESULT hr = S_OK;
+
+ (XmlGlobal::Instance())->ViewAll = gcnew UvcViewAll();
+ (XmlGlobal::Instance())->ViewAll->UvcView = gcnew UvcViewType();
+
+ //
+ // Initialize fields to null so we can check against them for allocation
+ //
+ (XmlGlobal::Instance())->ViewAll->UvcView->MachineInfo = nullptr;
+ (XmlGlobal::Instance())->ViewAll->UvcView->UsbTree = nullptr;
+
+ XmlSetVersion(
+ UVC_SPEC_MAJOR_VERSION,
+ UVC_SPEC_MINOR_VERSION,
+ USBVIEW_MAJOR_VERSION,
+ USBVIEW_MINOR_VERSION
+ );
+
+ gXmlStack->Push(gXmlView);
+
+ gXmlViewInitialized = TRUE;
+
+ return hr;
+}
+
+/*****************************************************************************
+
+ SaveXml()
+
+ Saves the inmemory USB view as XML file
+ *****************************************************************************/
+HRESULT SaveXml(LPTSTR szfileName, DWORD dwCreationDisposition)
+{
+ HRESULT hr = S_OK;
+
+ if (gXmlViewInitialized)
+ {
+ try
+ {
+ String ^fileName = PACHAR_TO_STRING(szfileName);
+ XmlSerializer ^ serializer = gcnew XmlSerializer(UvcViewAll::typeid);
+ TextWriter ^ writer = nullptr;
+
+ if (dwCreationDisposition != CREATE_ALWAYS)
+ {
+ // Check if file exits and return failure if it does
+ if (File::Exists(fileName))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_FILE_EXISTS);
+ }
+ }
+
+ // Check if file name is NULL
+ if (String::IsNullOrEmpty(fileName))
+ {
+ hr = E_INVALIDARG;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ writer = gcnew StreamWriter(fileName);
+ serializer->Serialize(writer, (XmlGlobal::Instance())->ViewAll);
+ writer->Close();
+ }
+
+ // Release and reinit XML View for next iteration if requested
+ ReleaseXmlWriter();
+ InitXmlHelper();
+
+ }
+ catch(Exception ^ ex)
+ {
+ hr = (HRESULT) Marshal::GetHRForException(ex);
+ }
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+
+ return hr;
+}
+
+
+/*****************************************************************************
+
+ ReleaseXmlWriter()
+
+ *****************************************************************************/
+HRESULT ReleaseXmlWriter()
+{
+ HRESULT hr = S_OK;
+
+ if (gXmlViewInitialized)
+ {
+ gXmlViewInitialized = FALSE;
+ delete XmlGlobal::Instance();
+ }
+
+ return hr;
+}
+