From: altrdstate on
I'm currently writing a KMDF based driver that will upon insertion of
a USB device, download firmware to it and then reset the USB bus
causing re-enumeration. I'm not entirely clear on the best way to
implement this, my current plan is as follows:

* From EvtPrepareHardware, I start a timer which causes TimerExpired
to be called
* In TimerExpired, I do a USB control transfer to check device state,
upload a block of data and then set another timer.

I thought this should be working, but I'm running into an access
violation somewhere in the USB stack, and I'm not sure how to debug
this further. When I call this function from EvtPrepareHardware
itself, everything works fine, but calling it from TimerExpired causes
the access violation. The call stack at that moment is as follows:
(using KMDF 1.5)

nt!DbgBreakPoint
Wdf01000!imp_WdfUsbTargetDeviceSendControlTransferSynchronously+0x186
mydriver!WdfUsbTargetDeviceSendControlTransferSynchronously+0x29
mydriver!TimerExpired

Now I have two questions:
1. Should I be using this design or would you suggest a different way?
(the protocol requires me to sleep every now and then, and since you
can't just use Sleep() I decided to go for the design as described).
2. What could be causing the access violation? Is it not allowed to
call USB stack functions from TimerExpired?

My TimerExpired function looks something like this:

VOID TimerExpired(IN WDFTIMER Timer)
{
NTSTATUS status;
WDFDEVICE Device;
PDEVICE_CONTEXT pDeviceContext;
WDF_USB_CONTROL_SETUP_PACKET thePacket;
BYTE buf[16];
DWORD len, nbytes;
WDF_MEMORY_DESCRIPTOR memoryDescriptor;

Device = WdfTimerGetParentObject(Timer);
pDeviceContext = GetDeviceContext(Device);

WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS(
&thePacket,
BmRequestDeviceToHost,
BmRequestToInterface,
0x05,
0,
0
);

pDeviceContext = GetDeviceContext(Device);

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor,
(PVOID) buf,
*len);

status = WdfUsbTargetDeviceSendControlTransferSynchronously(
pDeviceContext-
>WdfUsbTargetDevice,
WDF_NO_HANDLE, // Optional
WDFREQUEST
NULL, //
PWDF_REQUEST_SEND_OPTIONS
&thePacket,
&memoryDescriptor, //
MemoryDescriptor
&nbytes); // BytesTransferred
}

From: altrdstate on
An update:

I copy/pasted to make it easier to read, but forgot to change
something... this is not the source of the problem ;-)

> WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor,
> (PVOID) buf,
> *len);

Should be:

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor,
(PVOID) buf,
len);


>
> status = WdfUsbTargetDeviceSendControlTransferSynchronously(
> pDeviceContext->WdfUsbTargetDevice,
>
> WDF_NO_HANDLE, // Optional
> WDFREQUEST
> NULL, //
> PWDF_REQUEST_SEND_OPTIONS
> &thePacket,
> &memoryDescriptor, //
> MemoryDescriptor
> &nbytes); // BytesTransferred
>
> }


From: Eliyas Yakub [MSFT] on
You are calling the synchronous function from a timer which runs at
DISPATCH_LEVEL. All synchronous function must be called at PASSIVE_LEVEL. So
to fix your problem, queue a workitem from your timer and call this function
from the workitem callback.

-Eliyas


From: Doron Holan [MS] on
or send an async i/o from the timer and process the results in the
completion routine...

d

--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.


"Eliyas Yakub [MSFT]" <eliyasy(a)online.discussion.microsoft.com> wrote in
message news:eMcs1QtoHHA.3968(a)TK2MSFTNGP06.phx.gbl...
> You are calling the synchronous function from a timer which runs at
> DISPATCH_LEVEL. All synchronous function must be called at PASSIVE_LEVEL.
> So to fix your problem, queue a workitem from your timer and call this
> function from the workitem callback.
>
> -Eliyas
>