JP> I have a similar problem with multiple PCI wave input devices. Each device is identical, JP> but they are physically connected to different audio sources and it is important for the JP> application to be able to distinguish them reliably and consistently across reboots. I still JP> don't have a really satisfactory solution to this. This should solve your problem(AVStream driver type): NTSTATUS card_c::RegisterChannelsToSystem_Wave ( ) { #ifdef DBG_AND_LOGGER Procedure_Start_Local( "card_c::RegisterChannelsToSystem_Wave" ); #endif NTSTATUS Status = STATUS_UNSUCCESSFUL; WCHAR buffer_friendlyName[64]; WCHAR buffer_interfaceName[32]; unsigned long cardType; unsigned long i; unsigned long j; KSFILTER_DESCRIPTOR* pFilterDescriptor; unsigned long serialNumber; //Define card type. if ( type == CARD_TYPE_424 ) { cardType = 424; pFilterDescriptor = (KSFILTER_DESCRIPTOR*) &FilterDescriptor_Wave96; } else if ( type == CARD_TYPE_496 ) { cardType = 496; pFilterDescriptor = (KSFILTER_DESCRIPTOR*) &FilterDescriptor_Wave96; } else { cardType = 824; pFilterDescriptor = (KSFILTER_DESCRIPTOR*) &FilterDescriptor_Wave48; } //Get card serial number. for ( serialNumber = 0; serialNumber < WAVE8_MAX_CARDS; serialNumber++ ) { //Check for empty space. if ( glClass.cards[serialNumber] == NULL ) { //We found an empty space. Status = STATUS_SUCCESS; break; } } //Define filters. if ( SUCCESS( Status ) ) { //Convert serialNumber to 1 based number. ++serialNumber; //Register channels. for ( i = 0; i < numberOfStereoChannels; i++ ) { //Convert stereo to mono (channel numbers) and convert //to 1 based number. j = i*2 + 1; //Create strings. swprintf( buffer_friendlyName, L"WavePro%d(%d) ch. %d-%d", cardType, serialNumber, j, j+1 ); swprintf( buffer_interfaceName, L"GLI%d(%d) %d-%d", cardType, serialNumber, j, j+1 ); //Register filter interface. Status = RegisterFilterInterface( buffer_interfaceName, buffer_friendlyName ); //Register filter to system. if ( SUCCESS( Status ) ) { Status = KsCreateFilterFactory( cardDeviceObject->FunctionalDeviceObject, pFilterDescriptor, buffer_interfaceName, NULL, 0, NULL, NULL, &pFilterFactories[i] ); } if ( Status != STATUS_SUCCESS ) { break; } } } #ifdef DBG_AND_LOGGER Procedure_Exit( "card_c::RegisterChannelsToSystem_Wave", Status ); #endif return Status; } NTSTATUS card_c::UnregisterChannelsFromSystem_Wave ( ) { #ifdef DBG_AND_LOGGER Procedure_Start_Local( "card_c::UnregisterChannelsFromSystem_Wave" ); #endif NTSTATUS Status = STATUS_UNSUCCESSFUL; WCHAR buffer_interfaceName[32]; unsigned long cardType; unsigned long i; unsigned long j; unsigned long serialNumber; //Define card type. if ( type == CARD_TYPE_424 ) { cardType = 424; } else if ( type == CARD_TYPE_496 ) { cardType = 496; } else { cardType = 824; } //Get serialNumber. //Be carefull as this procedure can be called even if card failed to install. for ( serialNumber = 0; serialNumber < WAVE8_MAX_CARDS; serialNumber++ ) { //Check if the card was installed. if ( glClass.cards[serialNumber] == this ) { //We found it. Status = STATUS_SUCCESS; break; } } if ( Status != STATUS_SUCCESS ) { //Card wasn't installed -> find first empty space. for ( serialNumber = 0; serialNumber < WAVE8_MAX_CARDS; serialNumber++ ) { if ( glClass.cards[serialNumber] == NULL ) { //We found it. Status = STATUS_SUCCESS; break; } } } //Define filters. if ( SUCCESS( Status ) ) { //Convert serialNumber to 1 based number. ++serialNumber; //Unregister. for ( i = 0; i < numberOfStereoChannels; i++ ) { if ( pFilterFactories[i] == NULL ) { //There are no more pFilterFactories after 1st NULL. break; } //Convert stereo to mono (channel numbers) and convert //to 1 based number. j = i*2 + 1; //Create strings. swprintf( buffer_interfaceName, L"GLI%d(%d) %d-%d", cardType, serialNumber, j, j+1 ); //Disable filter factory. DisableFilterInterface( buffer_interfaceName ); //Release filter factories KsDeleteFilterFactory( pFilterFactories[i] ); pFilterFactories[i] = NULL; } } #ifdef DBG_AND_LOGGER Procedure_Exit( "card_c::UnregisterChannelsFromSystem_Wave", Status ); #endif return Status; } UNICODE_STRING FriendlyName_USTR = { sizeof( FRIENDLY_NAME ), sizeof( FRIENDLY_NAME ), &FRIENDLY_NAME }; UNICODE_STRING CLSID_USTR = { sizeof( sCLSID ), sizeof( sCLSID ), &sCLSID }; NTSTATUS card_c::RegisterFilterInterface ( IN PWCHAR interfaceName, IN PWCHAR friendlyName ) { #ifdef DBG_AND_LOGGER Procedure_Start_Local( "card_c::RegisterFilterInterface" ); #endif NTSTATUS Status; HANDLE hKey_interface = 0; GUID* interfaceClassGuid; UNICODE_STRING referenceName; UNICODE_STRING symbolicLinkName; //Convert PWCHAR to UNICODE_STRING. RtlInitUnicodeString( &referenceName, interfaceName ); //Register interface and set it's registry values. for ( int i = 0; i< 3; i++ ) { //Get class GUID. switch ( i ) { case 0 : interfaceClassGuid = (GUID*) &KSCATEGORY_AUDIO; break; case 1 : interfaceClassGuid = (GUID*) &KSCATEGORY_RENDER; break; case 2 : interfaceClassGuid = (GUID*) &KSCATEGORY_CAPTURE; break; default:; } //Register Interface Status = IoRegisterDeviceInterface( cardDeviceObject->PhysicalDeviceObject, interfaceClassGuid, &referenceName, &symbolicLinkName ); //Set CLSID and FriendlyName interface values. if ( SUCCESS( Status ) ) { //Open interface registry handle. Status = IoOpenDeviceInterfaceRegistryKey( &symbolicLinkName, KEY_WRITE, &hKey_interface ); //Set registry values. if ( SUCCESS( Status ) ) { //Set CLSID value. Status = ZwSetValueKey( hKey_interface, &CLSID_USTR, 0, REG_SZ, &guid_CLSID_Value_W, sizeof( guid_CLSID_Value_W ) + sizeof( WCHAR ) ); //Set FriendlyName value. if ( SUCCESS( Status ) ) { Status = ZwSetValueKey( hKey_interface, &FriendlyName_USTR, 0, REG_SZ, friendlyName, ( wcslen( friendlyName ) + 1 )*sizeof( WCHAR ) ); } //Release resources ZwClose( hKey_interface ); } if ( SUCCESS( Status ) ) { //Enable interface. Status = IoSetDeviceInterfaceState( &symbolicLinkName, TRUE ); } //Release resources RtlFreeUnicodeString( &symbolicLinkName ); } //Failed? if ( Status != STATUS_SUCCESS ) { break; } } #ifdef DBG_AND_LOGGER Procedure_Exit( "card_c::RegisterFilterInterface", Status ); #endif return Status; } NTSTATUS card_c::DisableFilterInterface ( IN PWCHAR interfaceName ) { #ifdef DBG_AND_LOGGER Procedure_Start_Local( "card_c::DisableFilterInterface" ); #endif NTSTATUS Status; HANDLE hKey_interface = 0; GUID* interfaceClassGuid; UNICODE_STRING referenceName; UNICODE_STRING symbolicLinkName; //Convert PWCHAR to UNICODE_STRING. RtlInitUnicodeString( &referenceName, interfaceName ); //Register interface and set it's registry values. for ( int i = 0; i< 3; i++ ) { //Get class GUID. switch ( i ) { case 0 : interfaceClassGuid = (GUID*) &KSCATEGORY_AUDIO; break; case 1 : interfaceClassGuid = (GUID*) &KSCATEGORY_RENDER; break; case 2 : interfaceClassGuid = (GUID*) &KSCATEGORY_CAPTURE; break; default:; } //Get Interface Status = IoRegisterDeviceInterface( cardDeviceObject->PhysicalDeviceObject, interfaceClassGuid, &referenceName, &symbolicLinkName ); if ( SUCCESS( Status ) ) { //Disable interface->we don't want that system will link //the interface to our driver when is not present anymore. Status = IoSetDeviceInterfaceState( &symbolicLinkName, FALSE ); //Release resources RtlFreeUnicodeString( &symbolicLinkName ); } } #ifdef DBG_AND_LOGGER Procedure_Exit( "card_c::DisableFilterInterface", Status ); #endif return Status; } ****************** 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/