Hi,
My UMDF receives data from the device and should pass it to several applications which are performing read operations. All applications should receive all of the data.
The applications write ioctls to the driver through a one joint control queue, shared by all of them.
I thought about a certain design for this, I’m not sure this is the way to do it in UMDF, so I would appreciate a few feedbacks and suggestions.
As I wrote, WRITE operations are not an issue since the control queue is sequential and joint.
For READ operations, I defined a default parallel read queue in the device, which has the same implementation as CMyReadWriteQueue in FX2 (with minor adjustments) and this queue receives the data from the device.
I also defined secondary manual CMyReadWriteQueue queues, each one belongs to an application (according to the process id).
When the request of the default queue gets to OnCompletion, it goes over all the other secondary queues, copies the memory of the request to their pending requests and completes them.
Is this the way to do this? Will it work? And if not, do you have any suggestions of other ways to do it?
And another technical question - is there a point in the FX2 sample code, prior to OnCompletion, where I can say that that’s the place where the data first arrived from the device (where the read operation has received its data and now all is left is to send it to the host and complete the request)?
Thanks,
Gadi
xxxxx@n-trig.com wrote:
Hi,
My UMDF receives data from the device and should pass it to several applications which are performing read operations. All applications should receive all of the data.
That’s an unusual design, filled with pitfalls. How is the driver going
to know how many applications to expect? What if one or more of the
applications is delayed, and doesn’t queue up a read by the time a
packet arrives? You surely don’t want to hold the data in your driver,
waiting for the stragglers.
I would suggest that a better design would be to move the complexity out
of the driver into an application, by using a client/server model. Have
a single application that talks to your driver, and then spews the data
out to other registered applications via a named pipe, or some similar
IPC mechanism.
When the request of the default queue gets to OnCompletion, it goes over all the other secondary queues, copies the memory of the request to their pending requests and completes them.
And what if an application is late? Does it just miss out on that
packet? The synchronization issues are mind-boggling.
And another technical question - is there a point in the FX2 sample code, prior to OnCompletion, where I can say that that’s the place where the data first arrived from the device (where the read operation has received its data and now all is left is to send it to the host and complete the request)?
When you send your request to the USB I/O target, the request is out of
your control. The USB subsystem will schedule the request, fetch the
data, and complete the request. The FIRST indication you get that the
request has been completed is the OnCompletion handler.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
I’ve done something similar in an internal sample that I was working on.
On suggestion - you don’t want to make your manual queues
per-process-id. You should just make them per-file-object. Setup the
queue in your create callback, purge it in your cleanup callback &
destroy it in your close callback.
And make sure that in your OnCompletion callback you synchronize with
any incoming create/cleanup/close requests which would want to modify
the list of manual queues at the same time you’re walking through it.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Wednesday, January 31, 2007 8:23 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Distributing data to different queues in UMDF
Hi,
My UMDF receives data from the device and should pass it to several
applications which are performing read operations. All applications
should receive all of the data.
The applications write ioctls to the driver through a one joint control
queue, shared by all of them.
I thought about a certain design for this, I’m not sure this is the way
to do it in UMDF, so I would appreciate a few feedbacks and suggestions.
As I wrote, WRITE operations are not an issue since the control queue is
sequential and joint.
For READ operations, I defined a default parallel read queue in the
device, which has the same implementation as CMyReadWriteQueue in FX2
(with minor adjustments) and this queue receives the data from the
device.
I also defined secondary manual CMyReadWriteQueue queues, each one
belongs to an application (according to the process id).
When the request of the default queue gets to OnCompletion, it goes over
all the other secondary queues, copies the memory of the request to
their pending requests and completes them.
Is this the way to do this? Will it work? And if not, do you have any
suggestions of other ways to do it?
And another technical question - is there a point in the FX2 sample
code, prior to OnCompletion, where I can say that that’s the place where
the data first arrived from the device (where the read operation has
received its data and now all is left is to send it to the host and
complete the request)?
Thanks,
Gadi
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
Hi,
Thanks for the quick replies.
2 questions -
- Why is it better to do it per-file-object? I don’t see the difference.
- What I’m doing now is in OnRead of ReadWriteQueue, after ForwardFormattedRequest to the target, I want to create dummy requests, one for each manual queue, so when I do OnCompletion for the original request in the parallel default queue, I will be able to do RetrieveNextRequest for the dummy request, and put inside it and the data of the original request (whose completion caused the OnCompletion callback to be called). This way I will be able to complete all the requests I have put in the manual queues (hope I’m in the right way… Will completing them cause the data to be read by the application?).
Back to OnRead, I create a dummy request, with a memory the same size as pOutputMemory, I format the request for read and then I forward it to the manual queue (in order to retrieve it in the OnCompletion(.
Apparently, forwarding it to the manual queue fails (Hresult is 0x800710dd - ERROR_INVALID_OPERATION). I have looked at the restrictions of this method and didn’t find any violation I am doing.
What am I doing wrong? (I attach the code to make it clearer), and is this mechanism (Putting a request in a manual queue in OnRead and completing it on the original request’s OnCompletion callback) correct?
Thanks,
Gadi
The code inside OnRead (a part of it):
***************************
IWDFIoRequest *pWdfManualRequest = NULL;
IWDFMemory * pManualOutputMemory = NULL;
IWDFDevice* FxDevice = GetDevice()->GetFxDevice();
IWDFDriver * FxDriver = NULL;
FxDevice->GetDriver(&FxDriver);
hr = FxDevice->CreateRequest( NULL, //pCallbackInterface
NULL, //pParentObject
&pWdfManualRequest);
hr = FxDriver->CreateWdfMemory(OutputMemorySize,NULL,pWdfManualRequest,&pManualOutputMemory);
hr = GetDevice()->GetInputPipe()->FormatRequestForRead(
pWdfManualRequest,
NULL, //pFile
pManualOutputMemory,
NULL, //Memory offset
NULL //DeviceOffset
);
if (FAILED(hr))
{
pWdfManualRequest->Complete(hr);
}
hr = pWdfManualRequest->ForwardToIoQueue(it->ReadQueue);
*******************fails here. hr = 0x800710dd**************
The code of OnCompletion:
********************
IWDFMemory *fxMemory;
IWDFMemory *DefaultRequestMemory;
//
// Copy the result to the request buffer.
//
fxRequest->GetOutputMemory(&fxMemory);
pWdfRequest->GetOutputMemory(&DefaultRequestMemory);
hr = fxMemory->CopyFromMemory(DefaultRequestMemory,NULL);
SizeOfData = fxMemory->GetSize();
fxMemory->Release();
DefaultRequestMemory->Release();
if (S_OK == hr) {
fxRequest->CompleteWithInformation(hr,
SizeOfData);
}
else {
fxRequest->Complete(hr);
}
-
because drivers don’t really know anything about processes. Sure you
can get the PID off of a request, but how do you know when that process
exits or, worse, when some new process is then assigned the same PID?
Drivers know about the open handles that processes have - these are file
objects. -
You’ve misunderstood how drivers work.
Your driver services requests that come from clients. The only way you
can get data back to the app is to complete a request **FROM THE
CLIENT**. We allow you to make your own requests so you can send them
to lower drivers. You can’t forward a request you create to any of your
own queues - you can only send it to an i/o target.
Here’s what you need to do:
-
In OnRead you queue the request on the appropriate manual queue.
-
When you get data from the device you walk through all your manual
queues and attempt to pull the next request off each of them. If there
is a request then copy the data in and complete it. If not then that
client loses its chance to get the data.
If losing the data is absolutely unacceptable in #2 then you’ll need to
build some sort of buffering system where you hold onto the data until
every client has had a chance to read it. However this is very
complicated to get right and still won’t help because if you have a
client that’s not acting well you’re eventually going to run out of
buffer space.
A better option is to let the client send multiple read requests at one
time. You don’t need to do anything different to allow this in your
driver - just keep forwarding requests to manual queues. This lets the
app decide how much memory it wants to commit to making sure it doesn’t
lose a packet.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Thursday, February 01, 2007 8:22 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Distributing data to different queues in UMDF
Hi,
Thanks for the quick replies.
2 questions -
- Why is it better to do it per-file-object? I don’t see the
difference. - What I’m doing now is in OnRead of ReadWriteQueue, after
ForwardFormattedRequest to the target, I want to create dummy requests,
one for each manual queue, so when I do OnCompletion for the original
request in the parallel default queue, I will be able to do
RetrieveNextRequest for the dummy request, and put inside it and the
data of the original request (whose completion caused the OnCompletion
callback to be called). This way I will be able to complete all the
requests I have put in the manual queues (hope I’m in the right way…
Will completing them cause the data to be read by the application?).
Back to OnRead, I create a dummy request, with a memory the same size as
pOutputMemory, I format the request for read and then I forward it to
the manual queue (in order to retrieve it in the OnCompletion(.
Apparently, forwarding it to the manual queue fails (Hresult is
0x800710dd - ERROR_INVALID_OPERATION). I have looked at the restrictions
of this method and didn’t find any violation I am doing.
What am I doing wrong? (I attach the code to make it clearer), and is
this mechanism (Putting a request in a manual queue in OnRead and
completing it on the original request’s OnCompletion callback) correct?
Thanks,
Gadi
The code inside OnRead (a part of it):
***************************
IWDFIoRequest *pWdfManualRequest = NULL;
IWDFMemory * pManualOutputMemory = NULL;
IWDFDevice* FxDevice =
GetDevice()->GetFxDevice();
IWDFDriver * FxDriver = NULL;
FxDevice->GetDriver(&FxDriver);
hr = FxDevice->CreateRequest( NULL,
//pCallbackInterface
NULL, //pParentObject
&pWdfManualRequest);
hr =
FxDriver->CreateWdfMemory(OutputMemorySize,NULL,pWdfManualRequest,&pManu
alOutputMemory);
hr =
GetDevice()->GetInputPipe()->FormatRequestForRead(
pWdfManualRequest,
NULL, //pFile
pManualOutputMemory,
NULL, //Memory offset
NULL //DeviceOffset
);
if (FAILED(hr))
{
pWdfManualRequest->Complete(hr);
}
hr =
pWdfManualRequest->ForwardToIoQueue(it->ReadQueue);
*******************fails here. hr = 0x800710dd**************
The code of OnCompletion:
********************
IWDFMemory *fxMemory;
IWDFMemory *DefaultRequestMemory;
//
// Copy the result to the request buffer.
//
fxRequest->GetOutputMemory(&fxMemory);
pWdfRequest->GetOutputMemory(&DefaultRequestMemory);
hr =
fxMemory->CopyFromMemory(DefaultRequestMemory,NULL);
SizeOfData = fxMemory->GetSize();
fxMemory->Release();
DefaultRequestMemory->Release();
if (S_OK == hr) {
fxRequest->CompleteWithInformation(hr,
SizeOfData);
}
else {
fxRequest->Complete(hr);
}
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
Hi,
This helped a lot.
There are a few things I still don’t fully understand:
I understand that I must define one of the queues as non-manual default queue (the data didn’t flow if there was no such queue), defined as a CMyReadWriteQueue as in FX2.
I create manual queues for each file object, and they are part of a class such as CMyReadWriteQueue, so I will be able to use their OnRead and OnCompletion methods.
How do they interact with the default queue?
Is it like this - OnRead of the default queue sends the request to the device (as in FX2), and OnRead of the manual queues just queues the request to the manual queue of the file?
Somehow the request has to get to the device, and if I just queue it to the manual queue it won’t get there, so it has to be sent from the default queue - but how does this queue get its requests if each file has a queue of its own?
And when the data gets back to OnCompletion of the default queue (it won’t return to the manual queues because their requests were not sent to the device), in OnCompletion of the default queue I walk through all the manual queues and attempt to pull the next request off each of them. If there is a request then I copy the data in and complete it. Do I copy the data that came from the request that was completed by the default queue (as we are currently in OnCompletion of the default queue) into the buffers of the requests of the manual queues? Will completing the requests with the data inside cause it to get the application?
Is this design correct? Should I keep the default parallel queue that actually communicates with the device and later completes the requests of the manual queues? Or should it be one of the manual queues? Should the manual queues communicate with the device directly?
How do the requests get divided between the default queue and the manuals? That is, a read request reaches the driver, do I send it to the device via the default queue and also queue it to a manual queue? Can I duplicate it and put it in the manual queue?
All of this is a bit confusing, I hope you will be able to help me make some sense of it
Thanks,
Gadi
p.s.
Can you publish the relevant code sections of what you have written which does the same?
When a request comes in to the device, the framework looks to see if a
particular queue is tagged to receive those. If so it puts the request
there. Otherwise it puts the request into the default queue (if there
is one). If there’s no default queue then it fails the request or
forwards it to the next driver (depending on whether or not your driver
is a filter).
You’ll need one device level queue into which the framework will put
read requests. You can do this by creating a default queue, or by
creating a non-default queue and then using
IWDFRequest::ConfigureRequestDispatching() to tell the framework where
read requests should go. See CMyDevice::Configure in the Fx2 sample for
an example - the fx2 driver gets I/O controls to the control queue in
the same way. Let’s call this your “top-level read queue”. In the
OnRead callback for this top-level read queue you’ll get the request’s
file object, get the queue for the file object, and forward the request
into that queue. Forwarding the request will move it from the default
queue to the manual queue.
In the background you have code which reads from the interrupt pipe.
This creates a request, sets the request’s callback object to something
(perhaps the top-level read queue, perhaps the device, perhaps a new
request-specific callback that you allocate. It doesn’t matter as long
as the object implements IRequestCallbackRequestCompletion. The Fx2
driver has two classes which implement that interface.
CMyReadWriteQueue implements it for the requests that it handles.
CMyDevice also implements it for the background reading of the interrupt
pipe & for the CMyDevice methods that the CMyControlQueue invokes.
It’s important that you understand why one OnCompletion method is
invoked over another. It has nothing to do with whether it’s
implemented on the queue object or the device object. When you call
IWDFIoRequest::SetCompletionCallback() you provide a pointer to any
object that implements IRequestCallbackReqeustCompletion. This can be
an object you create specifically for that request. In the Fx2 driver I
put the interface on whichever object sent the I/O request but that was
simply to avoid more memory allocations. I could just have easily
defined CMyControlRequest that had an OnCompletion callback that invoked
methods on the device callback object to put the results back.
To summarize:
So the app sends you a bunch of read requests. Your top-level read
queue’s OnRead callback is invoked. That callback forwards the requests
to the appropriate manual queue.
In the background you have code on one of your objects (probably the
device) which issues reads on the interrupt pipe. It sets a completion
callback on the read requests. In that completion callback it acquires
the device object’s lock and walks through the list of files. For each
file it pulls one or more requests off the manual queue, copies the data
from the device into the app’s request’s data buffer, sets the
information property to indicate how many bytes the I/O manager should
return, then completes the app’s request. This gets the data back to
the app.
Once the OnCompletion callback has run through all of the files it
unlocks the device then deletes the interrupt pipe read request,
allocates a new one, sets its completion callback, and sends a new read
down to the interrupt pipe.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Monday, February 05, 2007 8:11 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Distributing data to different queues in UMDF
Hi,
This helped a lot.
There are a few things I still don’t fully understand:
I understand that I must define one of the queues as non-manual default
queue (the data didn’t flow if there was no such queue), defined as a
CMyReadWriteQueue as in FX2.
I create manual queues for each file object, and they are part of a
class such as CMyReadWriteQueue, so I will be able to use their OnRead
and OnCompletion methods.
How do they interact with the default queue?
Is it like this - OnRead of the default queue sends the request to the
device (as in FX2), and OnRead of the manual queues just queues the
request to the manual queue of the file?
Somehow the request has to get to the device, and if I just queue it to
the manual queue it won’t get there, so it has to be sent from the
default queue - but how does this queue get its requests if each file
has a queue of its own?
And when the data gets back to OnCompletion of the default queue (it
won’t return to the manual queues because their requests were not sent
to the device), in OnCompletion of the default queue I walk through all
the manual queues and attempt to pull the next request off each of them.
If there is a request then I copy the data in and complete it. Do I
copy the data that came from the request that was completed by the
default queue (as we are currently in OnCompletion of the default queue)
into the buffers of the requests of the manual queues? Will completing
the requests with the data inside cause it to get the application?
Is this design correct? Should I keep the default parallel queue that
actually communicates with the device and later completes the requests
of the manual queues? Or should it be one of the manual queues? Should
the manual queues communicate with the device directly?
How do the requests get divided between the default queue and the
manuals? That is, a read request reaches the driver, do I send it to the
device via the default queue and also queue it to a manual queue? Can I
duplicate it and put it in the manual queue?
All of this is a bit confusing, I hope you will be able to help me make
some sense of it
Thanks,
Gadi
p.s.
Can you publish the relevant code sections of what you have written
which does the same?
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
Thanks for the elaborated reply.
The thing is, my interrupt eps are occupied for HID transfers, and interact with the HID class driver.
So I cannot use them as the interrupt pipe you’ve mentioned.
I need that all read messages will come from the bulk EP (or control).
How can overcome this issue? Is it necessary at all to handle it for my design? (When a read message arrives, distributing it to all apps)
Thanks,
Gadi
I’m unclear if you’re asking a hardware question (“Is it okay for me to
get this sort of data on my bulk or control pipes”) or a driver question
(“Does it matter which pipe I use in my driver”).
I can’t answer the first question, but there are plenty of USB experts
here who can probably help.
To the second question - it doesn’t really matter. UMDF couldn’t care
less where you get the data from. Once you find some way to get the
device to send you the data you put it in the request buffers and
complete them.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Wednesday, February 14, 2007 8:46 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Distributing data to different queues in UMDF
Thanks for the elaborated reply.
The thing is, my interrupt eps are occupied for HID transfers, and
interact with the HID class driver.
So I cannot use them as the interrupt pipe you’ve mentioned.
I need that all read messages will come from the bulk EP (or control).
How can overcome this issue? Is it necessary at all to handle it for my
design? (When a read message arrives, distributing it to all apps)
Thanks,
Gadi
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
It was a software design question.
I cannot use 2 pipes, as I only have one endpoint (bulk) (except the control end point, which I don’t know if it is okay to use it for this purpose, and if it is okay, then how).
So, a request arrives to OnRead of the default queue. I want to forward it to the appropriate manual queue, but I also want to ForwardFormattedRequest it, that is send it to the device.
If I do both, I get and ERROR_ACCESS_DENIED, which is logical, because the request can be either forwarded to a manual queue or sent to the device for handling.
If I forward it to the manual queue, no one will initiate the OnCompletion of the default queue, because it was never sent to the device.
If I ForwardFormattedRequest to the device, I cannot forward it to the manual queue, and even though OnCompletion of the default queue will be called, I will not be able to retrieve requests from the manual queues and complete them, as they were never put there.
Thanks,
Gadi
You can’t do both things with one request. It cannot belong to two owners, nor be in two places at once.
To repeat Peter’s earlier reply:
First, take your incoming requests, and place them in a manual queue or queues- that is as far as they go- they are going to sit there until canceled by the caller or the OS or you decide to pull them off and complete them.
Create a request object, owned by your device, and periodically send it to the real device and read what it has for you. When THIS request completes, pull a request off each of the manual queues and copy data and complete them as you see fit based upon how the request that has just been completed (for instance, if the read failed, maybe you don’t touch any of the queued requests but reissue it- your scenario isn’t well enough defined so far to be certain).
There are a lot of things missing here, but that is because the information needed to fill them in is missing. For instance, if you just want all waiting reads to get data as soon as it arrives, you could use fewer queues- probably two that get ping-ponged (once the lower request completes you begin routing incoming requests to the queue you are not about to drain, assuming you won’t send another read down below until you have completed all the requests in the queue you are draining). But if there is some implied ordering to these reads and apps could have multiple requests outstanding, then maybe the initial proposal makes more sense- except that, as Tim pointed out initially, you’ve got trouble if some app is slow in asking to read an event).
Similarly, perhaps you only send the read request down when you know there’s a request from above to service- can’t tell for certain from what’s been mentioned so far.
But the main point is you cannot possibly do this with a single request- you have one of your own you send down the stack, and zero or more from above that you complete when this one completes.
IRequestCallbackRequestCompletion is a callback interface for request
objects. You can tell that’s the case because it begins with
IRequestCallback. It doesn’t matter whether your queue callback object
implements this interface because the queue will NEVER call it.
The queue only uses interfaces that start with IQueueCallback…
(the exception to this rule are the IPnpCallback interfaces, which can
be registered on the device object)
You want to call IWDFIoRequest::SetCompletionCallback to set the
completion callback on the request. This callback will be triggered
once the LOWER driver completes the request.
So you get a read request and forward it to your manual queue.
You implement IQueueCallbackStateChange on your manual queue’s callback
object. When the state of the queue changes from empty to not-empty (or
not-empty to empty) this interface’s OnStateChange method will get
called. Check the flags in that callback to see if there is a new
request in the queue for your driver to process.
When there’s a new request you pull it off the queue, format it, set its
completion routine and forward it to the next driver. In the completion
routine you try to remove the next request from the queue and send it
down.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Thursday, February 22, 2007 7:39 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Distributing data to different queues in UMDF
It was a software design question.
I cannot use 2 pipes, as I only have one endpoint (bulk) (except the
control end point, which I don’t know if it is okay to use it for this
purpose, and if it is okay, then how).
So, a request arrives to OnRead of the default queue. I want to forward
it to the appropriate manual queue, but I also want to
ForwardFormattedRequest it, that is send it to the device.
If I do both, I get and ERROR_ACCESS_DENIED, which is logical, because
the request can be either forwarded to a manual queue or sent to the
device for handling.
If I forward it to the manual queue, no one will initiate the
OnCompletion of the default queue, because it was never sent to the
device.
If I ForwardFormattedRequest to the device, I cannot forward it to the
manual queue, and even though OnCompletion of the default queue will be
called, I will not be able to retrieve requests from the manual queues
and complete them, as they were never put there.
Thanks,
Gadi
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
Thanks for the elaborated replies. This helped a lot.
A question about copying the data from the request I created into the ones in the manual queue:
I implemented it like this -
I do not allocate a memory for the request that arrived to OnRead and was transfered to the manual queue (as I presume that whoever sent this request already allocated a memory).
For the request I create (the equivalent to “Interrupt” in InitiatePendingRequest) I do allocate a memory, like this:
hr = FxDriver->CreateWdfMemory( 1000,
NULL, //pCallbackInterface
FxRequest, //pParetObject
&FxMemory );
In OnCompletion of the request which returned from the device (in CMyReadWriteQueue),
I get the read data from the request like this:
pUsbComplParams->GetPipeReadParameters(&wdfMemory, &bytesRead, NULL);
and then I want to get the memory object of the request in the manual queue:
fxRequest->GetOutputMemory(&fxMemory);
And then I try to copy the data into it:
hr = fxMemory->CopyFromMemory(wdfMemory,0);
and this results in an error : 0x8007007A, which is ERROR_INSUFFICIENT_BUFFER.
What am I doing wrong? Should I extract the data into a buffer and copy Memory to Buffer and then Buffer to Memory?
Or did I miss a certain allocation? (the data is much smaller than 1000, so this cannot be the reason).
Thanks,
Gadi
How big is the buffer that you’re trying to copy into? You’re trying to
copy 1000 bytes into it (regardless of how many bytes were returned …
the memory object doesn’t know how much of its data is valid) so it had
better be big enough or you’ll get an error.
Do you validate that the read request you get from the app has a large
enough buffer to hold the data that you’re returning? Presumably
there’s a maximum number of bytes your device will try to send on the
interrupt pipe.
You probably want to get the data buffer then only copy as many bytes as
the device sent you.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Monday, February 26, 2007 8:07 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Distributing data to different queues in UMDF
Thanks for the elaborated replies. This helped a lot.
A question about copying the data from the request I created into the
ones in the manual queue:
I implemented it like this -
I do not allocate a memory for the request that arrived to OnRead and
was transfered to the manual queue (as I presume that whoever sent this
request already allocated a memory).
For the request I create (the equivalent to “Interrupt” in
InitiatePendingRequest) I do allocate a memory, like this:
hr = FxDriver->CreateWdfMemory( 1000,
NULL, //pCallbackInterface
FxRequest, //pParetObject
&FxMemory );
In OnCompletion of the request which returned from the device (in
CMyReadWriteQueue),
I get the read data from the request like this:
pUsbComplParams->GetPipeReadParameters(&wdfMemory, &bytesRead, NULL);
and then I want to get the memory object of the request in the manual
queue:
fxRequest->GetOutputMemory(&fxMemory);
And then I try to copy the data into it:
hr = fxMemory->CopyFromMemory(wdfMemory,0);
and this results in an error : 0x8007007A, which is
ERROR_INSUFFICIENT_BUFFER.
What am I doing wrong? Should I extract the data into a buffer and copy
Memory to Buffer and then Buffer to Memory?
Or did I miss a certain allocation? (the data is much smaller than 1000,
so this cannot be the reason).
Thanks,
Gadi
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer
Hi,
A question about using File objects as identifiers for applications.
The issue is that I use different handles in the application for reading and writing.
My device supports only BULK IN, and therefore I write to the device using the Control ep, and reading from it using the bulk ep. The result is that I use different handles in the app, and they are different File objects in the driver.
So if I register an app when it commences, I use my Control handle (because when I register it I use my WRITE handle), and when I’m in OnRead I use my Bulk handle, and they are not the same.
I tried to do a workaround, registering an app in its first read (and therefore registering it with the Bulk File obj), but this doesn’t take in consideration what will happen when I want to remove the app.
Removing it must be done by the WRITE handle, and there I do not know what the corresponding File object of the Bulk handle is.
Is there an elegant way to do this? Or is there another way to identify an app in all its handles and threads?
Thanks,
Gadi
Why does your application use different handles for reading and writing?
That seems to be the cause of your problems.
I would think that your driver should decide which pipe to read from or
write to based on the operation, not based on the handle the request
came in on.
-p
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@n-trig.com
Sent: Wednesday, March 07, 2007 7:35 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Distributing data to different queues in UMDF
Hi,
A question about using File objects as identifiers for applications.
The issue is that I use different handles in the application for reading
and writing.
My device supports only BULK IN, and therefore I write to the device
using the Control ep, and reading from it using the bulk ep. The result
is that I use different handles in the app, and they are different File
objects in the driver.
So if I register an app when it commences, I use my Control handle
(because when I register it I use my WRITE handle), and when I’m in
OnRead I use my Bulk handle, and they are not the same.
I tried to do a workaround, registering an app in its first read (and
therefore registering it with the Bulk File obj), but this doesn’t take
in consideration what will happen when I want to remove the app.
Removing it must be done by the WRITE handle, and there I do not know
what the corresponding File object of the Bulk handle is.
Is there an elegant way to do this? Or is there another way to identify
an app in all its handles and threads?
Thanks,
Gadi
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer