[wdmaudiodev] Device Enumeration again ...
- From: "Jerry Evans" <jerry@xxxxxxxxxx>
- To: <wdmaudiodev@xxxxxxxxxxxxx>
- Date: Sun, 6 Apr 2003 16:14:31 +0100
Hi all.
I'm now getting much more detail about the various devices installed in the
system. However my enumerator has (I think) got a problem with
distinguishing between KSCATEGORY_RENDER and KSCATEGORY_CAPTURE categories.
It would appear to be getting _all_ entries for the KSCATEGORY_AUDIO hive.
It is worth noting I have also tried querying the registry using this:
SetupDiGetDeviceRegistryProperty(hDevInfo,&DevInfoData,SPDRP_DEVTYPE,NULL,(P
BYTE)&dw,sizeof(dw),&reqSize);
The theory here being that the enumerations indicate unambiguously what type
of device we have. The MSDN link is
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/k
march/devobjts_5hnr.asp Howver this fails with GetLastError() returning an
'invalid data' message.
I have taken the liberty of attaching the relevant C++ class which is
reasonably well commented. If anyone would care to comment on why the
enumeration returns both Capture AND Render devices I would be delighted. It
should only require a #include to an existing project with a call as shown
in the header comments.
TVMIA
Jerry
-- Attached file included as plaintext by Ecartis --
-- File: DEVENUM2.H
/*
KS device enumerator
Sample usage:
Chordia::CDeviceEnumerator enumerator;
std::vector<Chordia::CDeviceDescriptor> ipnames;
std::vector<Chordia::CDeviceDescriptor> opnames;
// do the enumeration for AUDIO + CAPTURE devices only
if (enumerator.enumerate(KSCATEGORY_AUDIO,KSCATEGORY_CAPTURE,ipnames) >
0)
{
for (std::vector<Chordia::CDeviceDescriptor>::iterator it =
ipnames.begin();
it != ipnames.end();
++it)
{
// stuff ....
}
}
STATIC_KSCATEGORY_AUDIO
STATIC_KSCATEGORY_RENDER
STATIC_KSCATEGORY_CAPTURE
(C) Jerry Evans 2003
jerry_ks@xxxxxxxxxxxxx
Permisssion to redistribute granted for source and binary formats.
Please do not modify any of this comment block
*/
//-----------------------------------------------------------------------------
// auto-include relevant libraries
//-----------------------------------------------------------------------------
#include <Setupapi.h>
#pragma comment( lib, "setupapi.lib")
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
namespace Chordia
{
class CDeviceDescriptor
{
public:
std::string m_handle;
std::string m_description;
std::string m_name;
std::string m_manufacturer;
UINT m_id;
CDeviceDescriptor() { m_id = 0;}
CDeviceDescriptor(const CDeviceDescriptor& arg)
{
m_id = arg.m_id;
m_handle = arg.m_handle;
m_description = arg.m_description;
m_name = arg.m_name;
m_manufacturer = arg.m_manufacturer;
}
CDeviceDescriptor& operator=(const CDeviceDescriptor& arg)
{
m_id = arg.m_id;
m_handle = arg.m_handle;
m_description = arg.m_description;
m_name = arg.m_name;
m_manufacturer = arg.m_manufacturer;
return (*this);
}
};
//-----------------------------------------------------------------------------
// Enumerate kernel devices and return internal handle name and descriptions
//-----------------------------------------------------------------------------
class CDeviceEnumerator
{
public:
CDeviceEnumerator() {}
// enumerate names of devices matching GUIDS
// size_t enumerate(IN const GUID category, IN const std::vector<GUID>&
guids, OUT std::vector<CDeviceDescriptor>& descs)
//
size_t enumerate(IN const GUID category, IN const GUID& mode, OUT
std::vector<CDeviceDescriptor>& descs)
{
std::map<std::string,UINT> id_map;
// Get a handle to the device set specified by the guid
HDEVINFO hDevInfo = SetupDiGetClassDevs(&category,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
// failure ?
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return 0;
}
//
DWORD index = 0;
// Loop through members of the set and get details for each
while (true)
{
SP_DEVICE_INTERFACE_DATA DID;
SP_DEVICE_INTERFACE_DATA DIDAlias;
SP_DEVINFO_DATA DevInfoData;
DID.cbSize = sizeof(DID);
DID.Reserved = 0;
DIDAlias.cbSize = sizeof(DIDAlias);
DIDAlias.Reserved = 0;
ZeroMemory(&DevInfoData,sizeof(DevInfoData));
DevInfoData.cbSize = sizeof(DevInfoData);
DevInfoData.Reserved = 0;
// enumerate all KS_CATEGORY_AUDIO ?
if (SetupDiEnumDeviceInterfaces(hDevInfo,
NULL,
&category,
index++,
&DID) == FALSE)
{
// This just means that we've enumerate all the
devices - it's not a real error
break;
}
// new scope so buffer will come & go
{
// Get details for the device registered in
this class
DWORD size =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
// use vector so it will clean up afterwards
std::vector<BYTE> buffer(size,0);
//
SP_DEVICE_INTERFACE_DETAIL_DATA*
pDevInterfaceDetails =
reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(&buffer[0]);
//
pDevInterfaceDetails->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
&DID,
pDevInterfaceDetails,
size,
NULL,
&DevInfoData))
{
continue;
}
// check additional category guids which may
(or may not) have been supplied
if (!SetupDiGetDeviceInterfaceAlias(hDevInfo,
&DID,
&mode,
&DIDAlias))
{
continue;
}
// Check if the this interface alias is enabled.
if (!DIDAlias.Flags || (DIDAlias.Flags &
SPINT_REMOVED))
{
continue;
}
//
CDeviceDescriptor desc;
desc.m_handle =
pDevInterfaceDetails->DevicePath;
// this is how I test device 'type' at the
moment !!!!
/*
CKsAudFilter filter;
if
(filter.Instantiate(pDevInterfaceDetails->DevicePath) == S_OK)
{
if (mode == KSCATEGORY_RENDER)
{
if (filter.CountRenderPins() ==
0)
{
continue;
}
}
if (mode == KSCATEGORY_CAPTURE)
{
if (filter.CountCapturePins()
== 0)
{
continue;
}
}
}
*/
//
DWORD reqSize = 0;
BYTE name[64];
DWORD dw = 0;
BOOL b =
SetupDiGetDeviceRegistryProperty(hDevInfo,
&DevInfoData,
SPDRP_DEVTYPE,
NULL,
(PBYTE)&dw,
sizeof(dw),
&reqSize);
// get friendly name
if (SetupDiGetDeviceRegistryProperty(hDevInfo,
&DevInfoData,
SPDRP_LOCATION_INFORMATION,
NULL, // don't need the reg type
&name[0],
sizeof(name),
&reqSize) == TRUE)
{
desc.m_name =
reinterpret_cast<TCHAR*>(name);
name[reqSize] = '\0';
}
// get device description
if (SetupDiGetDeviceRegistryProperty(hDevInfo,
&DevInfoData,
SPDRP_DEVICEDESC,
NULL, // don't need the reg type
&name[0],
sizeof(name),
&reqSize) == TRUE)
{
desc.m_description =
reinterpret_cast<TCHAR*>(name);
name[reqSize] = '\0';
}
// get the manufacturers name
if (SetupDiGetDeviceRegistryProperty(hDevInfo,
&DevInfoData,
SPDRP_MFG,
NULL, // don't need the reg type
&name[0],
sizeof(name),
&reqSize) == TRUE)
{
desc.m_manufacturer =
reinterpret_cast<TCHAR*>(name);
name[reqSize] = '\0';
}
// this gives us device numbering if we have
multiple (say) USB devices
std::string strDesc = desc.m_description;
UINT id = 1;
// find the name
std::map<std::string,UINT>::iterator imi =
id_map.find(strDesc);
if (imi != id_map.end())
{
// increment the count
id = ++imi->second;
}
else
{
// insert as <Name> <1>
id_map.insert(std::make_pair(strDesc,1));
}
//
desc.m_id = id;
descs.push_back(desc);
}
}
// clean up and go home
SetupDiDestroyDeviceInfoList(hDevInfo);
//
return descs.size();
}
};
//-----------------------------------------------------------------------------
// end namespace
//-----------------------------------------------------------------------------
};
//-----------------------------------------------------------------------------
// end file
//-----------------------------------------------------------------------------
******************
WDMAUDIODEV addresses:
Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx
Subscribe: mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe
Unsubscribe: mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe
Moderator: mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx
URL to WDMAUDIODEV page:
http://www.wdmaudiodev.de/
Other related posts: