Hi All,
I?m trying to write a USB class filter driver, the goal is to send a vendor specified command to the device when the PID/VID is match.
I filter the IOCTL_INTERNAL_USB_SUBMIT_URB and URB function URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, and register a completion routine ?GetDescriptorCompletionRoutine? to get the result VID/PID, and so far so good.
For test propose, I create & send a new GetDescriptor URB to the same IoTarget in GetDescriptorCompletionRoutine to check the code I send URB is ok.
So if the result VID/PID in GetDescriptorCompletionRoutine is match, I do the following:
Create WDFMEMORY for URB, and use UsbBuildGetDescriptorRequest to setup the URB for USB_DEVICE_DESCRIPTOR_TYPE.
Create a new WDFREQUEST with the completion routine?s parameter WDFIOTARGET.
Use WdfIoTargetFormatRequestForInternalIoctlOthers to build internal device control request.
Set completion routine ?TestCompletionRoutine?for this request
Send this new request with WDF_NO_SEND_OPTIONS
I suppose it should get the same result in TestCompletionRoutine. However it fail… following are my questions:
Q1. In GetDescriptorCompletionRoutine, I use following code to get point of URB:
WdfRequestGetParameters(Request, &RequestParameters);
pUrbBuffer = RequestParameters.Parameters.Others.Arg1;
However, in the TestCompletionRoutine, I found the Arg1 in RequestParameter point to an invalid address… And I use the following code to get the result URB:
pUrbBuffer = WdfMemoryGetBuffer(CompletionParams->Parameters.Others.Argument1.Ptr, NULL);
Where the CompletionParams is the parameter of completion routine, and the Argument1 point to the WDFMEMORY which I create in above step1.
Why the result for TestCompletionRoutine is different from GetDescriptorCompletionRoutine?
Q2. The result in TestCompletionRoutine is different from the GetDescriptorCompletionRoutine… The result VID/PID=8086/2659, it is the USB Root Hub which the device attached to…
What’s wrong? and how should I do for the expected result?
Q3. Actually it’s not big problem. I found the URB type is URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE(0x0b) in the EvtIoInternalDeviceControl callback, but it changed to URB_FUNCTION_CONTROL_TRANSFER(0x08) in Completion Routine. I don’t find the doc about it, so I’m curious is it normal?
Sorry for my long question, and thank your patience~
Regards,
Q1. In GetDescriptorCompletionRoutine, I use following code to get point of URB:
WdfRequestGetParameters(Request, &RequestParameters);
pUrbBuffer = RequestParameters.Parameters.Others.Arg1;
However, in the TestCompletionRoutine, I found the Arg1 in RequestParameter point to an invalid address… And I use the following code to get the result URB:
pUrbBuffer = WdfMemoryGetBuffer(CompletionParams->Parameters.Others.Argument1.Ptr, NULL);
Where the CompletionParams is the parameter of completion routine, and the Argument1 point to the WDFMEMORY which I create in above step1.
Why the result for TestCompletionRoutine is different from GetDescriptorCompletionRoutine?
URBs are somewhat difficult for KMDF to handle. They are internal
device ioctl requests, which means they do not necessarily follow the
rules obeyed by well-behaved IRPs from user mode. It might be better to
save some information in a request context that you can fetch later,
rather than relying on KMDF to crack the IRP/URB fields later on.
Q3. Actually it’s not big problem. I found the URB type is URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE(0x0b) in the EvtIoInternalDeviceControl callback, but it changed to URB_FUNCTION_CONTROL_TRANSFER(0x08) in Completion Routine. I don’t find the doc about it, so I’m curious is it normal?
Yes. There are a whole host of individual URB functions that are
actually just simple control endpoint transfers with different values of
bmRequestType. The host controller changes the URB after it makes that
translation.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
Why a class filter? Why not filter just your device? You can then avoid
loading in the stack of every USB device and also avoid the need to read the
descriptors
On Wed, Oct 19, 2011 at 4:59 AM, wrote:
> Hi All, > I?m trying to write a USB class filter driver, the goal is to send a vendor > specified command to the device when the PID/VID is match. > > I filter the IOCTL_INTERNAL_USB_SUBMIT_URB and URB function > URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, and register a completion routine > ?GetDescriptorCompletionRoutine? to get the result VID/PID, and so far so > good. > > For test propose, I create & send a new GetDescriptor URB to the same > IoTarget in GetDescriptorCompletionRoutine to check the code I send URB is > ok. > > So if the result VID/PID in GetDescriptorCompletionRoutine is match, I do > the following: > 1. Create WDFMEMORY for URB, and use UsbBuildGetDescriptorRequest to setup > the URB for USB_DEVICE_DESCRIPTOR_TYPE. > 2. Create a new WDFREQUEST with the completion routine?s parameter > WDFIOTARGET. > 3. Use WdfIoTargetFormatRequestForInternalIoctlOthers to build internal > device control request. > 4. Set completion routine ?TestCompletionRoutine?for this request > 5. Send this new request with WDF_NO_SEND_OPTIONS > I suppose it should get the same result in TestCompletionRoutine. However > it fail… following are my questions: > > Q1. In GetDescriptorCompletionRoutine, I use following code to get point of > URB: > WdfRequestGetParameters(Request, &RequestParameters); > pUrbBuffer = RequestParameters.Parameters.Others.Arg1; > However, in the TestCompletionRoutine, I found the Arg1 in RequestParameter > point to an invalid address… And I use the following code to get the > result URB: > pUrbBuffer = > WdfMemoryGetBuffer(CompletionParams->Parameters.Others.Argument1.Ptr, NULL); > Where the CompletionParams is the parameter of completion routine, and the > Argument1 point to the WDFMEMORY which I create in above step1. > Why the result for TestCompletionRoutine is different from > GetDescriptorCompletionRoutine? > > Q2. The result in TestCompletionRoutine is different from the > GetDescriptorCompletionRoutine… The result VID/PID=8086/2659, it is the > USB Root Hub which the device attached to… > What’s wrong? and how should I do for the expected result? > > Q3. Actually it’s not big problem. I found the URB type is > URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE(0x0b) in the > EvtIoInternalDeviceControl callback, but it changed to > URB_FUNCTION_CONTROL_TRANSFER(0x08) in Completion Routine. I don’t find the > doc about it, so I’m curious is it normal? > > Sorry for my long question, and thank your patience~ > Regards, > > — > 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 >
Thanks Tim and Dan’s great suggestion and information!
I have found a solution for the Q2.
In the failed scenario, I create a WDFMEMORY for the URB, fill it with 0, and use the marco UsbBuildGetDescriptorRequest to setup the URB.
I found the different value of UsbdDeviceHandle field in the URB header makes the result different.
I copy the UsbdDeviceHandle field in the URB which returned in GetDescriptorCompletionRoutine to the new created URB header, and it works!
However the DDK doc said that field should be treated as opaque and considered to be reserved for system use…
Is it correct to assign this handle by my filter? If not, what is the better approach?
Q2. The result in TestCompletionRoutine is different from the GetDescriptorCompletionRoutine… The result VID/PID=8086/2659, it is the USB Root Hub which the device attached to…
What’s wrong? and how should I do for the expected result?
Thanks Tim and Dan’s great suggestion and information!
I have found a solution for the Q2.
In the failed scenario, I create a WDFMEMORY for the URB, fill it with
0, and use the marco UsbBuildGetDescriptorRequest to setup the URB.
I found the different value of UsbdDeviceHandle field in the URB
header makes the result different.
I copy the UsbdDeviceHandle field in the URB which returned in
GetDescriptorCompletionRoutine to the new created URB header, and it
works!
However the DDK doc said that field should be treated as opaque and
considered to be reserved for system use…
Is it correct to assign this handle by my filter? If not, what is the
better approach?
In part, this depends on where you are doing your filtering. If your
filter lives below any of the standard system components (like usbport
or usbccgp), then it’s quite possible one of them has already tucked
interesting information in the “opaque” fields of the URB.
You need to understand why your modification worked. Once you
understand that, you should be able to decide whether it is safe or not.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
Hi Tim
I have a little misunderstanding for my filter location before…
After checking where is my filter located, and why my modification works, I realize what is the problem now.
Your comment provide a great help for me to clarify the problem! Thank you very much!
Regards,
In part, this depends on where you are doing your filtering. If your
filter lives below any of the standard system components (like usbport
or usbccgp), then it’s quite possible one of them has already tucked
interesting information in the “opaque” fields of the URB.
You need to understand why your modification worked. Once you
understand that, you should be able to decide whether it is safe or not.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.