How to use "Devcon" to install drivers when 2 devices possess the same hardware ID?

Hi all,
I have developed a AVStream PCI driver for PCI capture card.
I would like to plug in 2 PCI capture cards, and then capture AVI files.
As for my PCI devices, they have identical hardware ID. The only different ID bewteen them is instance ID.
The following are the information got from devcon.exe:
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0 Name: DEV0
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&08F0 Name: DEV1
Since I would like to let 2 devices have different friendly name, I generate 2 inf files for each device.
If I install drivers from device manager, I can install each device manually with the specific inf file. That is, I install DEV0.inf for DEV0 device and install DEV1.inf for DEV1 device.
Therefore, the devices both work fine.
In addition, the following is hardware information in my inf file:
%SPCT6100.DeviceDesc%=SPCT6100,PCI\VEN_0216&DEV_6100
If I only plug one device, and use devcon.exe with following command to update driver, it also works fine:
devcon update DEV0.inf PCI\VEN_0216&DEV_6100
My question is as below:
When I plug 2 PCI cards, and use above devcon command, the system will update the driver for both devices. But if I use following command:
devcon update DEV0.inf PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0
devcon will return failed.
In other words, I can’t use devcon.exe to update DEV0.inf for Dev0 device only.
Does anyone know how to use “devcon” to install device with instance ID? Or does anynoe know how to install device driver by program when 2 devices possess identical hardware ID?

Thanks a lot!
Gordon

> As for my PCI devices, they have identical hardware ID. The only different ID bewteen them is

instance ID.
The following are the information got from devcon.exe:
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0 Name: DEV0
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&08F0 Name: DEV1
Since I would like to let 2 devices have different friendly name, I generate 2 inf files for each device.

You cannot. They have the same hardware ID, so, they will share the same INF.

The friendly names will be generated by Windows automatically as “Your Device #0” and “Your Device #1”, or so.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim S. Shatskih wrote:

> As for my PCI devices, they have identical hardware ID. The only different ID bewteen them is
> instance ID.
> The following are the information got from devcon.exe:
> PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0 Name: DEV0
> PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&08F0 Name: DEV1
> Since I would like to let 2 devices have different friendly name, I generate 2 inf files for each device.

You cannot. They have the same hardware ID, so, they will share the same INF.

The friendly names will be generated by Windows automatically as “Your Device #0” and “Your Device #1”, or so.

Or by your coinstaller.

-PA

>>You cannot. They have the same hardware ID, so, they will share the same INF.

>The friendly names will be generated by Windows automatically as “Your Device
>#0” and “Your Device #1”, or so.

Hi Maxim,
Thanks for your response!
There is another reason thay I need to use different inf files for the 2 PCI devices:
I use avshws of WDK 6001 as my sample code. In the sample code, there are some static functions, e.g. ‘DPC’ and Distatch functions.
If I let 2 device share the same AVStream driver(sys file) and service name(in INF), the static functions of the driver will be interfered by another device.
Therefore, in this case, I can only use one device(e.g. DEV0), and another device will not able to work.
However, if I let 2 devices use different driver name and different service name , they work fine.
So, if I let 2 devices to share the same AVStream driver, should I eliminate all the static functions in the driver?
Is there any way to eliminate the static functions(e.g. dispatch function) in AVStream driver?
Thanks a lot!
Gordon

>>Or by your coinstaller.
Hi PA,
Thanks for your response!
Could you explain the meaning of above words? Do you mean I can determine the friendly name by coinstaller?
Thanks a lot!
Gordon

xxxxx@sunplusct.com wrote:

>> Or by your coinstaller.
Hi PA,
Thanks for your response!
Could you explain the meaning of above words? Do you mean I can determine the friendly name by coinstaller?

Your coinstaller can provide whatever friendly name you want, for every
instance.

Regards,
–PA

xxxxx@sunplusct.com wrote:

>> You cannot. They have the same hardware ID, so, they will share the same INF.
>> The friendly names will be generated by Windows automatically as “Your Device
>> #0” and “Your Device #1”, or so.
>>

There is another reason thay I need to use different inf files for the 2 PCI devices:
I use avshws of WDK 6001 as my sample code. In the sample code, there are some static functions, e.g. ‘DPC’ and Distatch functions.
If I let 2 device share the same AVStream driver(sys file) and service name(in INF), the static functions of the driver will be interfered by another device.

Wrong. This just shows that you misunderstand how static functions
work. It’s doesn’t matter whether the CODE is static. What matters is
whether the DATA are static. In this case, all of those functions
receive a context pointer that identifies which device is being operated
on. That’s all you need. The context pointer points to the data
structures for THIS device, and since there are separate data structures
for each device, they all remain separate.

Now, if you foolishly added global variables to your driver, you have
broken this contract, but that’s a programming error on your part.

Therefore, in this case, I can only use one device(e.g. DEV0), and another device will not able to work.

You are WRONG. Virtually every driver ever written works this way,
where multiple devices share a single copy of the code.

You can even have different TYPES of devices use the same driver code.
I have an AVStream driver for a family of video capture devices. They
all use the same static functions, but the context pointer gives me a
C++ object which can then use virtual functions to call the appropriate
code for this device, while still allowing a single copy of those
functions that can be shared.

However, if I let 2 devices use different driver name and different service name , they work fine.
So, if I let 2 devices to share the same AVStream driver, should I eliminate all the static functions in the driver?
Is there any way to eliminate the static functions(e.g. dispatch function) in AVStream driver?

You don’t need to eliminate the static functions.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

e.g. ‘DPC’ and Distatch functions.

If I let 2 device share the same AVStream driver(sys file) and service name(in INF), the static functions of the driver will be interfered by another device.
Therefore, in this case, I can only use one device(e.g. DEV0), and another device will not able to work.

Not so.

You must avoid static data in the driver. As about static code - it is OK, it is just reused for both device instances (for 2 device extensions).


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Hi Tim,

>hat matters is
>whether the DATA are static. In this case, all of those functions
>receive a context pointer that identifies which device is being operated
>on. That’s all you need. The context pointer points to the data
>structures for THIS device, and since there are separate data structures
>for each device, they all remain separate.
Thanks for your help!
I still have following questions:
Question1:
How to get the object pointer of ‘CCaptureDevice::m_Device’ in AVStream driver’s DPC and ISR routine?
In other words, followings are my DPC and ISR routine:
VOID CCaptureDevice::DpcFor_DSPIRQ(PKDPC Dpc,PVOID DeferredContext,PVOID Arg1,PVOID Arg2)
{

}
BOOL CCaptureDevice::Isr_DSPIRQ(PKINTERRUPT Interupt, PVOID ServiceContext)
{
PDEVICE_OBJECT FdoData = (PDEVICE_OBJECT)ServiceContext;

}
In these functions, how can I get the current ‘m_Device’ pointer?
Question2:
In my case, my 2 devices have the same hardware ID. If I use one INF to setup the 2 devices, they will have the same display name in Graphedit’s ‘Video Capture Source’ group.
Is there any way to let 2 deivces have unique source filter name?
Thanks!
Gordon

Hi PA,

>Your coinstaller can provide whatever friendly name you want, for every instance.
Do you mean if I use coinstaller to install 2 devices with the same hardware ID, it can provide different friendly name for each device?
Can I see example in WDK’s sample code?
Thanks!
Gordon

xxxxx@sunplusct.com wrote:

I still have following questions:
Question1:
How to get the object pointer of ‘CCaptureDevice::m_Device’ in AVStream driver’s DPC and ISR routine?
In other words, followings are my DPC and ISR routine:
VOID CCaptureDevice::DpcFor_DSPIRQ(PKDPC Dpc,PVOID DeferredContext,PVOID Arg1,PVOID Arg2)
{

}
BOOL CCaptureDevice::Isr_DSPIRQ(PKINTERRUPT Interupt, PVOID ServiceContext)
{
PDEVICE_OBJECT FdoData = (PDEVICE_OBJECT)ServiceContext;

}
In these functions, how can I get the current ‘m_Device’ pointer?

So, you are already passing your DEVICE_OBJECT into the ISR? And in all
your exploration, you never encountered the function
KsGetDeviceForDeviceObject?

Question2:
In my case, my 2 devices have the same hardware ID. If I use one INF to setup the 2 devices, they will have the same display name in Graphedit’s ‘Video Capture Source’ group.
Is there any way to let 2 deivces have unique source filter name?

Why? What is the point of doing so? Even if you displayed them as
“Capture Device A” and “Capture Device B”, how would you tell the
difference?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim,
Thanks for your reply!

>in all your exploration, you never encountered the function KsGetDeviceForDeviceObject?
I use following codes to get device pointer:
BOOL CCaptureDevice::Isr_DSPIRQ(PKINTERRUPT Interupt, PVOID ServiceContext)
{
PDEVICE_OBJECT FdoData = (PDEVICE_OBJECT)ServiceContext;
PKSDEVICE pDevice;
pDevice=KsGetDeviceForDeviceObject(FdoData);

}
But the system crashes when it goes to ‘KsGetDeviceForDeviceObject’.
Do you know what’s the reason?

>Why? What is the point of doing so? Even if you displayed them as
>“Capture Device A” and “Capture Device B”, how would you tell the
>difference?
The reason is as in following:
I use Graphedit to test, and the connection is as below:
DeviceA –> my transform filter –> Render
DeviceB –> my transform filter –> Render
There are some setting values in my design and I save the values in registry. The setting value in DeviceA and DeviceB may be different.
For example, I may set resolution heigh for DeviceA and set resolution low for DeviceB. And I will set following values in registry:
HKLM,Software\Spect\DevA"Resolution",0x10001,0x01
HKLM,Software\Spect\DevB"Resolution",0x10001,0x00
Since DeviceA and Device B share the same transform filter, the transform filter needs to distinguish which source filter is connecting to it.
As for my original design, the transform filter use following method to get the upstream:
pUpstream->QueryFilterInfo(&Info);
So, the transform filter can get source filter’s name from ‘Info.achName’. For instance, if the filter get the source filter’s name as ‘DeviceB’, then it will read following registry path to get the setting value:
Software\Spect\DevB"Resolution"
However, if my 2 devices have the same source filter name, how can I tell the transform filter which source filter is connecting to it?
Do you know how to solve the problem?
Many thanks!
Gordon

xxxxx@sunplusct.com wrote:

Hi Tim,
Thanks for your reply!

>> in all your exploration, you never encountered the function KsGetDeviceForDeviceObject?
>>
I use following codes to get device pointer:
BOOL CCaptureDevice::Isr_DSPIRQ(PKINTERRUPT Interupt, PVOID ServiceContext)
{
PDEVICE_OBJECT FdoData = (PDEVICE_OBJECT)ServiceContext;
PKSDEVICE pDevice;
pDevice=KsGetDeviceForDeviceObject(FdoData);

}
But the system crashes when it goes to ‘KsGetDeviceForDeviceObject’.
Do you know what’s the reason?

You probably need to set a breakpoint on that statement or use KdPrint
to make sure that ServiceContext really contains your device object. As
long as you are passing the correct device object to IoConnectInterrupt,
it should work fine.

The reason is as in following:
I use Graphedit to test, and the connection is as below:
DeviceA –> my transform filter –> Render
DeviceB –> my transform filter –> Render
There are some setting values in my design and I save the values in registry. The setting value in DeviceA and DeviceB may be different.
For example, I may set resolution heigh for DeviceA and set resolution low for DeviceB. And I will set following values in registry:
HKLM,Software\Spect\DevA"Resolution",0x10001,0x01
HKLM,Software\Spect\DevB"Resolution",0x10001,0x00
Since DeviceA and Device B share the same transform filter, the transform filter needs to distinguish which source filter is connecting to it.

But how do you tell them apart physically? You don’t, right? All you
care about is that they use different registry settings. All you need
to do is make sure that the “first” device uses one set of registry
keys, and the “second” device uses another set of registry keys, for
some definition of “first” and “second”. You don’t care which slot the
“first” device is in, right? If so, then that’s easy. There are
SEVERAL ways to do this.

You can tell the two devices apart by fetching the UINumber from the
DEVICE_CAPABILITIES structure in the QueryCapabilities callback in your
KSDEVICE_DISPATCH structure. That number will be different for the two
boards. You could, for example, make that available as a custom
property that your transform filter could query. That way, it could
save its state using that UINumber as a subkey.

Alternatively, you could just keep an “instance number” as a static
global in your driver. Every time you create a new filter, save the
“instance number” and bump it for next time. Again, you report that as
a property. so the transform filter can tell the difference between
“first” and “second”.

As for my original design, the transform filter use following method to get the upstream:
pUpstream->QueryFilterInfo(&Info);
So, the transform filter can get source filter’s name from ‘Info.achName’. For instance, if the filter get the source filter’s name as ‘DeviceB’, then it will read following registry path to get the setting value:
Software\Spect\DevB"Resolution"
However, if my 2 devices have the same source filter name, how can I tell the transform filter which source filter is connecting to it?
Do you know how to solve the problem

There are many, many, many ways to solve this problem. Duplicating
driver code is absolutely the WRONG way to do it.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim,

>There are many, many, many ways to solve this problem. Duplicating
>driver code is absolutely the WRONG way to do it.
I have solved above problem. Thank you very much!

>You can tell the two devices apart by fetching the UINumber from the
>DEVICE_CAPABILITIES structure in the QueryCapabilities callback in your
>KSDEVICE_DISPATCH structure.
By the way, I still have another question.
I have added QueryCapabilities callback in my KSDEVICE_DISPATCH structure, and I can get correct UINumber in the callback function.
In addition, following is my device’s hardware ID and instance ID:
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0
My question is as below:
I would like to get the instance ID of my device, but it seems that there is no instance ID member in DEVICE_CAPABILITIES structure.
Do you know how to get ‘instance ID’ in AVStream driver?
Thanks for your help!
Gordon

My QueryCapabilities callback function is as in following:
NTSTATUS
CCaptureDevice::QueryCapabilities (
IN PKSDEVICE Device,
IN PIRP Irp,
IN OUT PDEVICE_CAPABILITIES Capabilities
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_CAPABILITIES pdc;
PIO_STACK_LOCATION irpStack;
irpStack = IoGetCurrentIrpStackLocation(Irp);
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
Capabilities = pdc;
KdPrint((“Query-UniqueID:%x”,pdc->UniqueID ));
KdPrint((“Query-UINumber:%x”,pdc->UINumber ));
return ntStatus;
}

Deice instance IDs are not exposed to drivers, avstream or plain old wdm.

d

Sent from my phone with no t9, all spilling mistakes are not intentional.

-----Original Message-----
From: xxxxx@sunplusct.com
Sent: Wednesday, November 05, 2008 3:30 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to use “Devcon” to install drivers when 2 devices possess the same hardware ID?

Hi Tim,
>>There are many, many, many ways to solve this problem. Duplicating
>>driver code is absolutely the WRONG way to do it.
I have solved above problem. Thank you very much!

>>You can tell the two devices apart by fetching the UINumber from the
>>DEVICE_CAPABILITIES structure in the QueryCapabilities callback in your
>>KSDEVICE_DISPATCH structure.
By the way, I still have another question.
I have added QueryCapabilities callback in my KSDEVICE_DISPATCH structure, and I can get correct UINumber in the callback function.
In addition, following is my device’s hardware ID and instance ID:
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0
My question is as below:
I would like to get the instance ID of my device, but it seems that there is no instance ID member in DEVICE_CAPABILITIES structure.
Do you know how to get ‘instance ID’ in AVStream driver?
Thanks for your help!
Gordon

My QueryCapabilities callback function is as in following:
NTSTATUS
CCaptureDevice::QueryCapabilities (
IN PKSDEVICE Device,
IN PIRP Irp,
IN OUT PDEVICE_CAPABILITIES Capabilities
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_CAPABILITIES pdc;
PIO_STACK_LOCATION irpStack;
irpStack = IoGetCurrentIrpStackLocation(Irp);
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
Capabilities = pdc;
KdPrint((“Query-UniqueID:%x”,pdc->UniqueID ));
KdPrint((“Query-UINumber:%x”,pdc->UINumber ));
return ntStatus;
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@sunplusct.com wrote:

>> You can tell the two devices apart by fetching the UINumber from the
>> DEVICE_CAPABILITIES structure in the QueryCapabilities callback in your
>> KSDEVICE_DISPATCH structure.
>>
By the way, I still have another question.
I have added QueryCapabilities callback in my KSDEVICE_DISPATCH structure, and I can get correct UINumber in the callback function.
In addition, following is my device’s hardware ID and instance ID:
PCI\VEN_0216&DEV_6100&SUBSYS_00000000&REV_01\4&BC67B8D&0&00F0
My question is as below:
I would like to get the instance ID of my device, but it seems that there is no instance ID member in DEVICE_CAPABILITIES structure.
Do you know how to get ‘instance ID’ in AVStream driver?

You don’t need the instance ID. If you want to write to the hardware
registry key, you can use IoOpenDeviceRegistryKey.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>Deice instance IDs are not exposed to drivers, avstream or plain old wdm.

Is it done intentionally or is it just an bug-like overlooking in IoGetDeviceProperly API?


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

intentional

d

Sent from my phone with no t9, all spilling mistakes are not intentional.

-----Original Message-----
From: Maxim S. Shatskih
Sent: Thursday, November 06, 2008 1:34 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] RE:How to use “Devcon” to install drivers when 2 devices possess the same hardware ID?

>Deice instance IDs are not exposed to drivers, avstream or plain old wdm.

Is it done intentionally or is it just an bug-like overlooking in IoGetDeviceProperly API?


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

>intentional

And what was the motivation? why other PnP IDs are available by IoGetDeviceProperty, and instance ID is not?


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

The full blown instance id is not exposed b/c it would subsequently be abused. Bus or device instance IDs are provided, but they are not the full ID. If the full instance ID was given, many drivers would then use that as a path in the registry, breaking the abstraction of the devnode store as well searching for the string in other stringss, such as the device interface instance string

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Thursday, November 06, 2008 6:28 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Re:RE:How to use “Devcon” to install drivers when 2 devices possess the same hardware ID?

intentional

And what was the motivation? why other PnP IDs are available by IoGetDeviceProperty, and instance ID is not?


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer