|
|
/*******************************************************************************
* * (C) COPYRIGHT MICROSOFT CORP., 1993-1995 * TITLE: USBITEM.CPP * VERSION: 1.0 * AUTHOR: jsenior * DATE: 10/28/1998 * ******************************************************************************** * * CHANGE LOG: * * DATE REV DESCRIPTION * ---------- ------- ---------------------------------------------------------- * 10/28/1998 jsenior Original implementation. * *******************************************************************************/ #include "UsbItem.h"
#include "resource.h"
// From root\wdm10\usb\hcd\uhcd\bandwdth.c
#define HCD_BW_PER_FRAME ((ULONG)12000) // bits/ms
#define HCD_TOTAL_USB_BW ((ULONG)12000*32)
// From root\wdm10\usb\inc\hcdi.h
#define USB_ISO_OVERHEAD_BYTES 9
#define USB_INTERRUPT_OVERHEAD_BYTES 13
#include "debug.h"
extern HINSTANCE gHInst;
UsbItem::~UsbItem() { if (configInfo) { DeleteChunk(configInfo); delete configInfo; } if (deviceInfo) { DeleteChunk(deviceInfo); delete deviceInfo; } DeleteChunk(sibling); delete sibling; DeleteChunk(child); delete child; }
UsbItem * UsbItem::AddLeaf(UsbItem* Parent, UsbDeviceInfo* DeviceInfo, UsbItemType Type, UsbConfigInfo* ConfigInfo, UsbImageList *ClassImageList) { //
// Fill in the parent's Child field
//
// If it's not null, walk the chain of children of this parent and add
// this node to the end of the chain.
//
if (Parent != 0) { //
// Create a new USBMGR_TVITEM
//
UsbItem *lastSibling = 0, *item = 0; item = new UsbItem(); AddChunk(item); if (0 == item) { USBERROR((_T("Out of Memory\n"))); return FALSE; }
if (Parent->child != 0) { //
// This parent already has a child. Look for the end of the chain of
// children.
//
lastSibling = Parent->child;
while (0 != lastSibling->sibling) { lastSibling = lastSibling->sibling; }
//
// Found the last sibling for this parent
//
lastSibling->sibling = item; } else { //
// No children for this parent yet
//
Parent->child = item; }
item->parent = Parent;
item->deviceInfo = DeviceInfo; item->configInfo = ConfigInfo; item->itemType = Type;
item->GetClassImageIndex(ClassImageList); return item; } else { // This item is the root (no parent)
deviceInfo = DeviceInfo; configInfo = ConfigInfo; itemType = Type;
GetClassImageIndex(ClassImageList); return this; } }
void UsbItem::GetClassImageIndex(UsbImageList *ClassImageList) { if (!configInfo || !configInfo->deviceClass.size()) { //
// No device class, so assign the default USB class
//
ClassImageList->GetClassImageIndex(TEXT("USB"), &imageIndex); } else { if (_tcsicmp(configInfo->deviceClass.c_str(), USBHID) == 0) { //
// This device is HID, so find out what its child is for the
// appropriate icon
//
CONFIGRET cr; DEVINST childDI; TCHAR buf[MAX_PATH]; ULONG len; cr = CM_Get_Child(&childDI, configInfo->devInst, 0); USBINFO( (_T("Found HID device: %s, devInst: %x\n"), configInfo->deviceDesc.c_str(), configInfo->devInst)); if (cr == CR_SUCCESS) { len = sizeof(buf); cr = CM_Get_DevNode_Registry_Property(childDI, CM_DRP_CLASS, NULL, buf, &len, 0); if (cr == CR_SUCCESS) { configInfo->deviceClass = buf; USBINFO( (_T("New class: %s\n"), buf)); }
len = sizeof(buf); cr = CM_Get_DevNode_Registry_Property(childDI, CM_DRP_DEVICEDESC, NULL, buf, &len, 0); if (cr == CR_SUCCESS) { configInfo->deviceDesc = buf; USBINFO( (_T("New name: %s\n"), configInfo->deviceDesc.c_str())); } } } ClassImageList->GetClassImageIndex(configInfo->deviceClass.c_str(), &imageIndex); } }
UINT UsbItem::EndpointBandwidth( ULONG MaxPacketSize, UCHAR EndpointType, BOOLEAN LowSpeed ) /*++
Return Value:
banwidth consumed in bits/ms, returns 0 for bulk and control endpoints
--*/ { ULONG bw = 0;
//
// control, iso, bulk, interrupt
//
ULONG overhead[4] = { 0, USB_ISO_OVERHEAD_BYTES, 0, USB_INTERRUPT_OVERHEAD_BYTES };
// return zero for control or bulk
if (!overhead[EndpointType]) { return 0; }
//
// Calculate bandwidth for endpoint. We will use the
// approximation: (overhead bytes plus MaxPacket bytes)
// times 8 bits/byte times worst case bitstuffing overhead.
// This gives bit times, for low speed endpoints we multiply
// by 8 again to convert to full speed bits.
//
//
// Figure out how many bits are required for the transfer.
// (multiply by 7/6 because, in the worst case you might
// have a bit-stuff every six bits requiring 7 bit times to
// transmit 6 bits of data.)
//
// overhead(bytes) * maxpacket(bytes/ms) * 8
// (bits/byte) * bitstuff(7/6) = bits/ms
bw = ((overhead[EndpointType]+MaxPacketSize) * 8 * 7) / 6;
if (LowSpeed) { bw *= 8; }
return bw; }
inline ULONG UsbItem::CalculateBWPercent(ULONG bw) { return (bw*100) / HCD_BW_PER_FRAME; }
int UsbItem::CalculateTotalBandwidth( ULONG NumPipes, BOOLEAN LowSpeed, USB_PIPE_INFO *PipeInfo ) { ULONG i = 0, bwConsumed, bwTotal = 0; PUSB_ENDPOINT_DESCRIPTOR epd = 0;
for (i = 0; i < NumPipes; i++) {
epd = &PipeInfo[i].EndpointDescriptor;
//
// We only take into account iso BW. Interrupt bw is accounted for
// in another way.
//
if (USB_ENDPOINT_TYPE_ISOCHRONOUS == (epd->bmAttributes & USB_ENDPOINT_TYPE_MASK)) { bwConsumed = EndpointBandwidth(epd->wMaxPacketSize, (UCHAR)(epd->bmAttributes & USB_ENDPOINT_TYPE_MASK), LowSpeed); bwTotal += bwConsumed; } }
bwTotal = CalculateBWPercent(bwTotal);
return bwTotal; }
BOOL UsbItem::ComputeBandwidth() { bandwidth = 0;
if (deviceInfo && deviceInfo->connectionInfo && !deviceInfo->connectionInfo->DeviceIsHub) { if (deviceInfo->connectionInfo->NumberOfOpenPipes > 0) { if (0 != (bandwidth = CalculateTotalBandwidth( deviceInfo->connectionInfo->NumberOfOpenPipes, deviceInfo->connectionInfo->LowSpeed, deviceInfo->connectionInfo->PipeList))) { return TRUE; } } else { // Device is not consuming any bandwidth
USBTRACE((_T("%s has no open pipes\n"), configInfo->deviceDesc.c_str())); } }
return FALSE; }
BOOL UsbItem::ComputePower() { power = 0;
if (IsHub()) { if (PortPower() == 100) { //
// Hub that is bus powered requires one unit of power for itself
// plus one unit for each of its ports
//
power = (1 + NumPorts()) > 4 ? 500 : 100 * (1 + NumPorts());
} else { //
// Self-powered hubs don't require any power from upstream
//
power = 0; } return TRUE; } if (deviceInfo && deviceInfo->configDesc) { power = deviceInfo->configDesc->MaxPower*2; return TRUE; } return FALSE; }
BOOL UsbItem::IsController() { if (itemType == HCD) { return TRUE; } return FALSE; }
BOOL UsbItem::IsHub() { if (itemType == RootHub || itemType == Hub) return TRUE;
if (deviceInfo) { if (deviceInfo->isHub) return TRUE;
if (deviceInfo->connectionInfo && deviceInfo->connectionInfo->DeviceIsHub) return TRUE; }
return FALSE; }
ULONG UsbItem::UsbVersion() { if (deviceInfo) { if (deviceInfo->connectionInfo) { return deviceInfo->connectionInfo->DeviceDescriptor.bcdUSB; #ifdef HUB_CAPS
} else if(hubCaps.HubIs2xCapable) { // Probably the root hub, check hub capabilities
return 0x200; #endif
} #if 0
else { return 0x200; } #endif
} return 0x100; }
BOOL UsbItem::IsDescriptionValidDevice() { if (!IsUnusedPort() && configInfo && configInfo->deviceDesc.c_str()) { return TRUE; } return FALSE; }
ULONG UsbItem::NumChildren() { UsbItem *item; ULONG i = 0; for (item = child; item != NULL; item = item->sibling) { if (item->IsDescriptionValidDevice()) { i++; } } return i; }
ULONG UsbItem::NumPorts() { UsbItem *item; ULONG i = 0; if (IsHub()) { for (item = child; item != NULL; item = item->sibling) { i++; } } return i; }
ULONG UsbItem::PortPower() { if (IsHub()) { if (deviceInfo->hubInfo.u.HubInformation.HubIsBusPowered) return 100; else return 500; } else { return 0; } }
BOOL UsbItem::Walk(UsbItemAction& Action) { if (sibling) { if (!sibling->Walk(Action)) return FALSE; }
if (child) { if (!child->Walk(Action)) return FALSE; }
return Action(this); }
BOOL UsbItem::ShallowWalk(UsbItemAction& Action) { if (sibling) { if (!sibling->ShallowWalk(Action)) return FALSE; }
return Action(this); }
BOOL UsbItem::GetDeviceInfo( String &HubName, ULONG index) { HANDLE hHubDevice; PUSB_NODE_CONNECTION_INFORMATION connectionInfo = 0; String driverKeyName; TCHAR buf[MAX_PATH];
//
// Try to open the hub device
//
hHubDevice = GetHandleForDevice(HubName);
if (hHubDevice == INVALID_HANDLE_VALUE) { goto GetDeviceInfoError; }
if (!GetPortAttributes(hHubDevice, &cxnAttributes, index)) { USBERROR( (_T("Couldn't get node connection attributes\n"))); goto GetDeviceInfoError; }
if (NULL == (connectionInfo = GetConnectionInformation(hHubDevice, index))) { USBERROR( (_T("Couldn't get node connection information\n"))); goto GetDeviceInfoError; }
//
// Allocate configuration information structure
//
configInfo = new UsbConfigInfo(); AddChunk(configInfo);
if (configInfo == 0) { goto GetDeviceInfoError; }
//
// If there is a device connected, get the Device Description
//
if (connectionInfo->ConnectionStatus != NoDeviceConnected) { driverKeyName = GetDriverKeyName(hHubDevice,index);
if (!driverKeyName.empty()) { GetConfigMgrInfo(driverKeyName, configInfo); }
if (configInfo->deviceDesc.empty()) { if (connectionInfo->DeviceIsHub) { if (connectionInfo->DeviceDescriptor.bcdUSB >= 0x200) { LoadString(gHInst, IDS_UNKNOWN20HUB, buf, MAX_PATH); } else { LoadString(gHInst, IDS_UNKNOWNHUB, buf, MAX_PATH); } } else { LoadString(gHInst, IDS_UNKNOWNDEVICE, buf, MAX_PATH); } configInfo->deviceDesc = buf; } if (configInfo->deviceClass.empty()) { configInfo->deviceClass = connectionInfo->DeviceIsHub ? TEXT("USB") : TEXT("Unknown"); }
itemType = connectionInfo->DeviceIsHub ? UsbItem::UsbItemType::Hub : UsbItem::UsbItemType::Device;
//
// Allocate some space for a USBDEVICEINFO structure to hold the
// info for this device.
//
deviceInfo = new UsbDeviceInfo(); AddChunk(deviceInfo);
if (deviceInfo == 0) { goto GetDeviceInfoError; }
if (NULL != (deviceInfo->configDescReq = GetConfigDescriptor(hHubDevice, index))) { deviceInfo->configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(deviceInfo->configDescReq+1); } deviceInfo->connectionInfo = connectionInfo; } else { //
// Empty port. Add "Port n"
//
LocalFree(connectionInfo);
itemType = UsbItem::UsbItemType::Empty;
LoadString(gHInst, IDS_UNUSEDPORT, buf, MAX_PATH); configInfo->deviceDesc = buf; UnusedPort = TRUE; configInfo->deviceClass = TEXT("USB");
} CloseHandle(hHubDevice); return TRUE;
GetDeviceInfoError: //
// Clean up any stuff that got allocated
//
if (hHubDevice != INVALID_HANDLE_VALUE) { CloseHandle(hHubDevice); hHubDevice = INVALID_HANDLE_VALUE; } if (deviceInfo) { DeleteChunk(deviceInfo); delete deviceInfo; } if (connectionInfo) { LocalFree(connectionInfo); } if (configInfo) { DeleteChunk(configInfo); delete configInfo; } return FALSE; }
//
// Recursively inserts items appropriately into a treeview
//
BOOL UsbItem::InsertTreeItem (HWND hWndTree, UsbItem *usbItem, HTREEITEM hParent, LPTV_INSERTSTRUCT item, PUsbItemActionIsValid IsValid, PUsbItemActionIsValid IsBold, PUsbItemActionIsValid IsExpanded) { if (!usbItem || !item) { return FALSE; }
if (IsValid(usbItem)) { HTREEITEM hItem;
ZeroMemory(item, sizeof(TV_INSERTSTRUCT));
// Get the image index
item->hParent = hParent; item->hInsertAfter = TVI_LAST; item->item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; // TVIF_CHILDREN
if (IsBold(usbItem)) { item->itemex.state = TVIS_BOLD; } if (IsExpanded(usbItem)) { item->itemex.state |= TVIS_EXPANDED; } item->itemex.stateMask = (UINT)~(TVIS_STATEIMAGEMASK | TVIS_OVERLAYMASK); item->itemex.pszText = (LPTSTR) usbItem->configInfo->deviceDesc.c_str(); item->itemex.cchTextMax = _tcsclen(usbItem->configInfo->deviceDesc.c_str()); item->itemex.iImage = usbItem->imageIndex; item->itemex.iSelectedImage = usbItem->imageIndex; if (usbItem->child) { item->itemex.cChildren = 1; } item->itemex.lParam = (USBLONG_PTR) usbItem;
if (NULL == (hItem = TreeView_InsertItem(hWndTree, item))) { int i = GetLastError(); return FALSE; } if (usbItem->child) { if (!InsertTreeItem(hWndTree, usbItem->child, hItem, item, IsValid, IsBold, IsExpanded)) { return FALSE; } } } if (usbItem->sibling) { if (!InsertTreeItem(hWndTree, usbItem->sibling, hParent, item, IsValid, IsBold, IsExpanded)) { return FALSE; } } return TRUE; }
BOOL UsbTreeView_DeleteAllItems(HWND hTreeDevices) { HTREEITEM hTreeRoot;
//
// Select the root and delete so as to delete whole tree.
// There is a paint bug in tree view that if you delete all when the
// root isn't selected, then it will paint badly.
//
if (NULL == (hTreeRoot = (HTREEITEM) SendMessage(hTreeDevices, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, (LPARAM)NULL))) { // Nothing to delete; successful
return TRUE; } if (!SendMessage(hTreeDevices, TVM_SELECTITEM, (WPARAM)TVGN_CARET, (LPARAM)hTreeRoot)) { // Can't select the root; YIKES!
return FALSE; }
//
// deleteAllOk = TreeView_DeleteAllItems(hTreeDevices);
//
return (BOOL) SendMessage(hTreeDevices, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); }
HTREEITEM TreeView_FindItem(HWND hWndTree, LPCTSTR text) { HTREEITEM hItemPrev, hItemNext; TCHAR buf[MAX_PATH];
TVITEM tvItem; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = buf; tvItem.cchTextMax = MAX_PATH;
if (NULL == (hItemNext = TreeView_GetRoot(hWndTree))) { return NULL; }
hItemPrev = hItemNext;
while (hItemPrev) {
//
// Drill all the way down, checking the nodes along the way.
//
while (hItemNext) { //
// Check this leaf
//
tvItem.hItem = hItemNext; if (TreeView_GetItem(hWndTree, &tvItem)) { if (!_tcscmp(tvItem.pszText, text)) { return hItemNext; } }
//
// Get the next child
//
hItemPrev = hItemNext; hItemNext = TreeView_GetNextItem(hWndTree, hItemPrev, TVGN_CHILD); }
//
// Find the first sibling on the way back up the tree
//
while (!hItemNext && hItemPrev) { //
// Get the sibling
//
hItemNext = TreeView_GetNextItem(hWndTree, hItemPrev, TVGN_NEXT); if (!hItemNext) { //
// Get the parent
//
hItemPrev = TreeView_GetNextItem(hWndTree, hItemPrev, TVGN_PARENT); } } }
return NULL; }
HANDLE UsbCreateFileA( IN LPCWSTR lpFileName, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, IN DWORD dwCreationDisposition, IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile) { CHAR usbDeviceName[MAX_PATH]; if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpFileName, -1, usbDeviceName, MAX_PATH, NULL, NULL)) { return INVALID_HANDLE_VALUE; } return CreateFileA (usbDeviceName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); }
//
// Get the index into the ImageList for this device's icon
//
BOOL UsbImageList::GetClassImageIndex(LPCTSTR DeviceClass, PINT ImageIndex) { #ifndef WINNT
IconItem *iconItem; BOOL found = FALSE; int i = 0; for (iconItem = iconTable.begin(); iconItem; iconItem = iconTable.next(), i++) { if (_tcsicmp(DeviceClass, iconItem->szClassName) == 0) { *ImageIndex = iconItem->imageIndex; return TRUE; } } #endif // ~WINNT
GUID classGuid; DWORD listSize;
if(SetupDiClassGuidsFromName(DeviceClass, &classGuid, 1, &listSize)) { return SetupDiGetClassImageIndex(&ClassImageList, &classGuid, ImageIndex); } return FALSE; }
BOOL UsbImageList::GetClassImageList() { ZeroMemory(&ClassImageList, sizeof(SP_CLASSIMAGELIST_DATA)); ClassImageList.cbSize = sizeof(SP_CLASSIMAGELIST_DATA); if (!SetupDiGetClassImageList(&ClassImageList)) { USBERROR((TEXT("Failed to get imagelist, error %x"), GetLastError())); return FALSE; } #ifndef WINNT
HICON hIcon; IconItem iconItem; HIMAGELIST imageList = ClassImageList.ImageList;
iconTable.clear();
hIcon = LoadIcon(gHInst, MAKEINTRESOURCE(IDI_IMAGE)); iconItem.imageIndex = ImageList_AddIcon(imageList, hIcon); iconItem.szClassName = TEXT("Image"); iconTable.push_back(iconItem);
hIcon = LoadIcon(gHInst, MAKEINTRESOURCE(IDI_MODEM)); iconItem.imageIndex = ImageList_AddIcon(imageList, hIcon); iconItem.szClassName = TEXT("Modem"); iconTable.push_back(iconItem);
hIcon = LoadIcon(gHInst, MAKEINTRESOURCE(IDI_INFRARED)); iconItem.imageIndex = ImageList_AddIcon(imageList, hIcon); iconItem.szClassName = TEXT("Infrared"); iconTable.push_back(iconItem);
hIcon = LoadIcon(gHInst, MAKEINTRESOURCE(IDI_CDROM)); iconItem.imageIndex = ImageList_AddIcon(imageList, hIcon); iconItem.szClassName = TEXT("CDROM"); iconTable.push_back(iconItem);
hIcon = LoadIcon(gHInst, MAKEINTRESOURCE(IDI_FLOPPY)); iconItem.imageIndex = ImageList_AddIcon(imageList, hIcon); iconItem.szClassName = TEXT("DiskDrive"); iconTable.push_back(iconItem);
hIcon = LoadIcon(gHInst, MAKEINTRESOURCE(IDI_MEDIA)); iconItem.imageIndex = ImageList_AddIcon(imageList, hIcon); iconItem.szClassName = TEXT("MEDIA"); iconTable.push_back(iconItem);
#endif // ~WINNT
return TRUE; }
|