Bulk stream transfer using double buffer

Real CPU SpeedHi,

I’m developing a USB 2.0 device driver.
I have tried to transfer stream data using BULK pipe.

The user sends DeviceIoControl( IOCTL_BULK_STREAM_START, … ) to start
data streaming, and the driver send device-allocated IRP.

I set the completion routine for a driver-allocated IRP, and in the completion routine
previous allocated IRP is resent to lower device.

My question is :
When the driver-allocated IRP is completed, I expected to be called the completion routine.

But when completed, system shut down. The softICE tells “Page fault” error message.

Followings are skeleton of my code.
What’s the problem?

========================================================================
NTSTATUS StartBulkTransfer(…)
{

//
// Set a completion routine
//
IoSetCompletionRoutine(streamObject->TransferObject->Irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

ntStatus = IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject->Irp);

Ezusb_KdPrint ((“return from IoCallDriver USBD %x\n”, ntStatus));
return STATUS_SUCCESS;
}

NTSTATUS BulkStreamTransferComplete(…) // Completion routine
{

IoInitializeIrp(Irp,
IoSizeOfIrp((pdx->StackDeviceObject->StackSize + 1)),
(CCHAR)(pdx->StackDeviceObject->StackSize + 1));

nextStack = IoGetNextIrpStackLocation(Irp);

nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

KeInitializeEvent(&event, NotificationEvent, FALSE);

Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);

// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = urb;

IoSetCompletionRoutine(Irp,
BulkStreamTransferComplete,
transferObject,
TRUE,
TRUE,
TRUE);

//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}

Real CPU SpeedYour code is very confusing. First in your dispatch routine, you should propagate the status returned by IoCallDriver. If you always return STATUS_SUCCESS bad things might happen if the lower driver returned something other than STATUS_SUCCESS. If you are going to pend the IRP then mark the IRP pending and return STATUS_PENDING. The completion routine seems to initialize an IRP and then overwrites the local variable IRP with a different IRP allocated by IoBuildDeviceIoControlRequest.

I think looking at your code, the driver verfier should be able to catch a lot of these problems. Run the driver verifier on your driver (use the verifier.exe tool) and it should bugcheck earlier and give a you much better picture of where the problem should be.


Nar Ganapathy
Windows Core OS group
This posting is provided “AS IS” with no warranties, and confers no rights.

“HyungJune Kim” wrote in message news:xxxxx@ntdev…
Hi,

I’m developing a USB 2.0 device driver.
I have tried to transfer stream data using BULK pipe.

The user sends DeviceIoControl( IOCTL_BULK_STREAM_START, … ) to start
data streaming, and the driver send device-allocated IRP.

I set the completion routine for a driver-allocated IRP, and in the completion routine
previous allocated IRP is resent to lower device.

My question is :
When the driver-allocated IRP is completed, I expected to be called the completion routine.

But when completed, system shut down. The softICE tells “Page fault” error message.

Followings are skeleton of my code.
What’s the problem?

========================================================================
NTSTATUS StartBulkTransfer(…)
{



//
// Set a completion routine
//
IoSetCompletionRoutine(streamObject->TransferObject->Irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

ntStatus = IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject->Irp);

Ezusb_KdPrint ((“return from IoCallDriver USBD %x\n”, ntStatus));
return STATUS_SUCCESS;
}

NTSTATUS BulkStreamTransferComplete(…) // Completion routine
{



IoInitializeIrp(Irp,
IoSizeOfIrp((pdx->StackDeviceObject->StackSize + 1)),
(CCHAR)(pdx->StackDeviceObject->StackSize + 1));

nextStack = IoGetNextIrpStackLocation(Irp);

nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

KeInitializeEvent(&event, NotificationEvent, FALSE);

Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);

// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = urb;

IoSetCompletionRoutine(Irp,
BulkStreamTransferComplete,
transferObject,
TRUE,
TRUE,
TRUE);

//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}

Real CPU SpeedDear Ganapathy,

Thank you for your reply.

As your comment, in the dispatch routine, the status returned by IoCallDriver is STATUS_PENDING.
But I think that the IRP to IoCallDriver is allocated by driver, which is different from the IRP of dispatch routine.
So I always returned STATUS_SUCCESS.

In order to reuse IRP, I have tried two cases:
One is to use IoBuildDeviceIoControlRequest, IoSetCompletionRoutine and then
IoCallDriver.

{

KeInitializeEvent(&event, NotificationEvent, FALSE);

irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

IoSetCompletionRoutine(irp,
BulkStreamTransferComplete,
&event,
TRUE,
TRUE,
TRUE
);

ntStatus = IoCallDriver(pdx->StackDeviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
Ezusb_KdPrint ((“Wait for single object\n”));

status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);

Ezusb_KdPrint ((“Wait for single object, returned %x\n”, status));
}
else
{
ioStatus.Status = ntStatus;
}

return ntStatus;
}

In this case, the system shut down in completion routine. In the completion routine,
I just return STATUS_MORE_PROCESSING_REQUIRED.

The other is to use IoAllocateIrp.

{

stackSize = (CCHAR) (pdx->StackDeviceObject->StackSize + 1);
irp = IoAllocateIrp(stackSize, FALSE);
IoInitializeIrp(irp, irp->Size, stackSize);

nextStack = IoGetNextIrpStackLocation(irp);

nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

//
// Set a completion routine
//
IoSetCompletionRoutine(irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

//
// Call the USB class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
ntStatus = IoCallDriver(pdx->StackDeviceObject,irp );

return STATUS_SUCCESS;
}

In this case, system also shut down.

In both case, if I remove completion routine, the system doesn’t shut down.
However I should resend IRP in completion routine for data streaming.
What’s the problem?

Regards,
HyungJune Kim

----- Original Message -----
From: Nar Ganapathy [MS]
Newsgroups: ntdev
To: NT Developers Interest List
Sent: Sunday, September 15, 2002 3:29 PM
Subject: [ntdev] Re: Bulk stream transfer using double buffer

Your code is very confusing. First in your dispatch routine, you should propagate the status returned by IoCallDriver. If you always return STATUS_SUCCESS bad things might happen if the lower driver returned something other than STATUS_SUCCESS. If you are going to pend the IRP then mark the IRP pending and return STATUS_PENDING. The completion routine seems to initialize an IRP and then overwrites the local variable IRP with a different IRP allocated by IoBuildDeviceIoControlRequest.

I think looking at your code, the driver verfier should be able to catch a lot of these problems. Run the driver verifier on your driver (use the verifier.exe tool) and it should bugcheck earlier and give a you much better picture of where the problem should be.


Nar Ganapathy
Windows Core OS group
This posting is provided “AS IS” with no warranties, and confers no rights.

“HyungJune Kim” wrote in message news:xxxxx@ntdev…
Hi,

I’m developing a USB 2.0 device driver.
I have tried to transfer stream data using BULK pipe.

The user sends DeviceIoControl( IOCTL_BULK_STREAM_START, … ) to start
data streaming, and the driver send device-allocated IRP.

I set the completion routine for a driver-allocated IRP, and in the completion routine
previous allocated IRP is resent to lower device.

My question is :
When the driver-allocated IRP is completed, I expected to be called the completion routine.

But when completed, system shut down. The softICE tells “Page fault” error message.

Followings are skeleton of my code.
What’s the problem?

========================================================================
NTSTATUS StartBulkTransfer(…)
{



//
// Set a completion routine
//
IoSetCompletionRoutine(streamObject->TransferObject->Irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

ntStatus = IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject->Irp);

Ezusb_KdPrint ((“return from IoCallDriver USBD %x\n”, ntStatus));
return STATUS_SUCCESS;
}

NTSTATUS BulkStreamTransferComplete(…) // Completion routine
{



IoInitializeIrp(Irp,
IoSizeOfIrp((pdx->StackDeviceObject->StackSize + 1)),
(CCHAR)(pdx->StackDeviceObject->StackSize + 1));

nextStack = IoGetNextIrpStackLocation(Irp);

nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

KeInitializeEvent(&event, NotificationEvent, FALSE);

Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);

// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = urb;

IoSetCompletionRoutine(Irp,
BulkStreamTransferComplete,
transferObject,
TRUE,
TRUE,
TRUE);

//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}


You are currently subscribed to ntdev as: xxxxx@hynix.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Real CPU SpeedAre you completing the original IRP in the dispatch routine ? If not you should return STATUS_PENDING and also mark the IRP pending. If you return STATUS_SUCCESS the caller assumes that the IRP has already been completed. Run the driver verifier on this code. It should catch the problem at the right place.


Nar Ganapathy
Windows Core OS group
This posting is provided “AS IS” with no warranties, and confers no rights.

“HyungJune Kim” wrote in message news:xxxxx@ntdev…
Dear Ganapathy,

Thank you for your reply.

As your comment, in the dispatch routine, the status returned by IoCallDriver is STATUS_PENDING.
But I think that the IRP to IoCallDriver is allocated by driver, which is different from the IRP of dispatch routine.
So I always returned STATUS_SUCCESS.

In order to reuse IRP, I have tried two cases:
One is to use IoBuildDeviceIoControlRequest, IoSetCompletionRoutine and then
IoCallDriver.

{


KeInitializeEvent(&event, NotificationEvent, FALSE);

irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

IoSetCompletionRoutine(irp,
BulkStreamTransferComplete,
&event,
TRUE,
TRUE,
TRUE
);

ntStatus = IoCallDriver(pdx->StackDeviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
Ezusb_KdPrint ((“Wait for single object\n”));

status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);

Ezusb_KdPrint ((“Wait for single object, returned %x\n”, status));
}
else
{
ioStatus.Status = ntStatus;
}

return ntStatus;
}

In this case, the system shut down in completion routine. In the completion routine,
I just return STATUS_MORE_PROCESSING_REQUIRED.

The other is to use IoAllocateIrp.

{


stackSize = (CCHAR) (pdx->StackDeviceObject->StackSize + 1);
irp = IoAllocateIrp(stackSize, FALSE);
IoInitializeIrp(irp, irp->Size, stackSize);

nextStack = IoGetNextIrpStackLocation(irp);

nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

//
// Set a completion routine
//
IoSetCompletionRoutine(irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

//
// Call the USB class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
ntStatus = IoCallDriver(pdx->StackDeviceObject,irp );

return STATUS_SUCCESS;
}

In this case, system also shut down.

In both case, if I remove completion routine, the system doesn’t shut down.
However I should resend IRP in completion routine for data streaming.
What’s the problem?

Regards,
HyungJune Kim

----- Original Message -----
From: Nar Ganapathy [MS]
Newsgroups: ntdev
To: NT Developers Interest List
Sent: Sunday, September 15, 2002 3:29 PM
Subject: [ntdev] Re: Bulk stream transfer using double buffer

Your code is very confusing. First in your dispatch routine, you should propagate the status returned by IoCallDriver. If you always return STATUS_SUCCESS bad things might happen if the lower driver returned something other than STATUS_SUCCESS. If you are going to pend the IRP then mark the IRP pending and return STATUS_PENDING. The completion routine seems to initialize an IRP and then overwrites the local variable IRP with a different IRP allocated by IoBuildDeviceIoControlRequest.

I think looking at your code, the driver verfier should be able to catch a lot of these problems. Run the driver verifier on your driver (use the verifier.exe tool) and it should bugcheck earlier and give a you much better picture of where the problem should be.


Nar Ganapathy
Windows Core OS group
This posting is provided “AS IS” with no warranties, and confers no rights.

“HyungJune Kim” wrote in message news:xxxxx@ntdev…
Hi,

I’m developing a USB 2.0 device driver.
I have tried to transfer stream data using BULK pipe.

The user sends DeviceIoControl( IOCTL_BULK_STREAM_START, … ) to start
data streaming, and the driver send device-allocated IRP.

I set the completion routine for a driver-allocated IRP, and in the completion routine
previous allocated IRP is resent to lower device.

My question is :
When the driver-allocated IRP is completed, I expected to be called the completion routine.

But when completed, system shut down. The softICE tells “Page fault” error message.

Followings are skeleton of my code.
What’s the problem?

========================================================================
NTSTATUS StartBulkTransfer(…)
{



//
// Set a completion routine
//
IoSetCompletionRoutine(streamObject->TransferObject->Irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

ntStatus = IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject->Irp);

Ezusb_KdPrint ((“return from IoCallDriver USBD %x\n”, ntStatus));
return STATUS_SUCCESS;
}

NTSTATUS BulkStreamTransferComplete(…) // Completion routine
{



IoInitializeIrp(Irp,
IoSizeOfIrp((pdx->StackDeviceObject->StackSize + 1)),
(CCHAR)(pdx->StackDeviceObject->StackSize + 1));

nextStack = IoGetNextIrpStackLocation(Irp);

nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

KeInitializeEvent(&event, NotificationEvent, FALSE);

Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);

// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = urb;

IoSetCompletionRoutine(Irp,
BulkStreamTransferComplete,
transferObject,
TRUE,
TRUE,
TRUE);

//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}


You are currently subscribed to ntdev as: xxxxx@hynix.com
To unsubscribe send a blank email to %%email.unsub%%

Real CPU Speed
Ganapathy,

Thank you for your response.

I completed the original IRP in dispatch routine.
I ran driver verifier.
When the system shutdown, BugCheck occurrs as following.

STOP : 0X000000D1 (0xA897A000, 0X00000002, 0X00000000, 0XEE95B795)
DRIVER_IRQL_NOT_LESS_OR_EQUAL

*** Address EE95B795 base at EE953000, DateStamp 3d857a43 - ezusb.sys

And verifer log file as following.

2002-09-17, Level: 0000001B
RaiseIrqls: 0
AcquireSpinLocks: 0
SynchronizeExecutions: 0
AllocationsAttempted: 561
AllocationsSucceeded: 561
AllocationsSucceededSpecialPool: 561
AllocationsWithNoTag: 0
AllocationsFailed: 0
AllocationsFailedDeliberately: 0
Trims: 0
UnTrackedPool: 0

Verified drivers:

Name: ezusb.sys, loads: 2, unloads: 1
CurrentPagedPoolAllocations: 0
CurrentNonPagedPoolAllocations: 3
PeakPagedPoolAllocations: 0
PeakNonPagedPoolAllocations: 119
PagedPoolUsageInBytes: 0
NonPagedPoolUsageInBytes: 52
PeakPagedPoolUsageInBytes: 0
PeakNonPagedPoolUsageInBytes: 9108

2002-09-17, Level: 0000001B
RaiseIrqls: 0
AcquireSpinLocks: 0
SynchronizeExecutions: 0
AllocationsAttempted: 561
AllocationsSucceeded: 561
AllocationsSucceededSpecialPool: 561
AllocationsWithNoTag: 0
AllocationsFailed: 0
AllocationsFailedDeliberately: 0
Trims: 0
UnTrackedPool: 0

Verified drivers:

Name: ezusb.sys, loads: 2, unloads: 1
CurrentPagedPoolAllocations: 0
CurrentNonPagedPoolAllocations: 3
PeakPagedPoolAllocations: 0
PeakNonPagedPoolAllocations: 119
PagedPoolUsageInBytes: 0
NonPagedPoolUsageInBytes: 52
PeakPagedPoolUsageInBytes: 0
PeakNonPagedPoolUsageInBytes: 9108

2002-09-17, Level: 0000001B
RaiseIrqls: 0
AcquireSpinLocks: 0
SynchronizeExecutions: 0
AllocationsAttempted: 561
AllocationsSucceeded: 561
AllocationsSucceededSpecialPool: 561
AllocationsWithNoTag: 0
AllocationsFailed: 0
AllocationsFailedDeliberately: 0
Trims: 0
UnTrackedPool: 0

Verified drivers:

Name: ezusb.sys, loads: 2, unloads: 1
CurrentPagedPoolAllocations: 0
CurrentNonPagedPoolAllocations: 3
PeakPagedPoolAllocations: 0
PeakNonPagedPoolAllocations: 119
PagedPoolUsageInBytes: 0
NonPagedPoolUsageInBytes: 52
PeakPagedPoolUsageInBytes: 0
PeakNonPagedPoolUsageInBytes: 9108

2002-09-17, Level: 0000001B
RaiseIrqls: 0
AcquireSpinLocks: 0
SynchronizeExecutions: 0
AllocationsAttempted: 2484
AllocationsSucceeded: 2484
AllocationsSucceededSpecialPool: 2484
AllocationsWithNoTag: 0
AllocationsFailed: 0
AllocationsFailedDeliberately: 0
Trims: 0
UnTrackedPool: 0

Verified drivers:

Name: ezusb.sys, loads: 3, unloads: 2
CurrentPagedPoolAllocations: 0
CurrentNonPagedPoolAllocations: 136
PeakPagedPoolAllocations: 0
PeakNonPagedPoolAllocations: 137
PagedPoolUsageInBytes: 0
NonPagedPoolUsageInBytes: 10432
PeakPagedPoolUsageInBytes: 0
PeakNonPagedPoolUsageInBytes: 10532

Any comment would be helpful.
Thanks.

----- Original Message -----
From: Nar Ganapathy[MS]
Newsgroups: ntdev
To: NT Developers Interest List
Sent: Tuesday, September 17, 2002 1:07 AM
Subject: [ntdev] Re: Bulk stream transfer using double buffer

Are you completing the original IRP in the dispatch routine ? If not you should return STATUS_PENDING and also mark the IRP pending. If you return STATUS_SUCCESS the caller assumes that the IRP has already been completed. Run the driver verifier on this code. It should catch the problem at the right place.


Nar Ganapathy
Windows Core OS group
This posting is provided “AS IS” with no warranties, and confers no rights.

“HyungJune Kim” wrote in message news:xxxxx@ntdev…
Dear Ganapathy,

Thank you for your reply.

As your comment, in the dispatch routine, the status returned by IoCallDriver is STATUS_PENDING.
But I think that the IRP to IoCallDriver is allocated by driver, which is different from the IRP of dispatch routine.
So I always returned STATUS_SUCCESS.

In order to reuse IRP, I have tried two cases:
One is to use IoBuildDeviceIoControlRequest, IoSetCompletionRoutine and then
IoCallDriver.

{


KeInitializeEvent(&event, NotificationEvent, FALSE);

irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

IoSetCompletionRoutine(irp,
BulkStreamTransferComplete,
&event,
TRUE,
TRUE,
TRUE
);

ntStatus = IoCallDriver(pdx->StackDeviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
Ezusb_KdPrint ((“Wait for single object\n”));

status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);

Ezusb_KdPrint ((“Wait for single object, returned %x\n”, status));
}
else
{
ioStatus.Status = ntStatus;
}

return ntStatus;
}

In this case, the system shut down in completion routine. In the completion routine,
I just return STATUS_MORE_PROCESSING_REQUIRED.

The other is to use IoAllocateIrp.

{


stackSize = (CCHAR) (pdx->StackDeviceObject->StackSize + 1);
irp = IoAllocateIrp(stackSize, FALSE);
IoInitializeIrp(irp, irp->Size, stackSize);

nextStack = IoGetNextIrpStackLocation(irp);

nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

//
// Set a completion routine
//
IoSetCompletionRoutine(irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

//
// Call the USB class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
ntStatus = IoCallDriver(pdx->StackDeviceObject,irp );

return STATUS_SUCCESS;
}

In this case, system also shut down.

In both case, if I remove completion routine, the system doesn’t shut down.
However I should resend IRP in completion routine for data streaming.
What’s the problem?

Regards,
HyungJune Kim

----- Original Message -----
From: Nar Ganapathy [MS]
Newsgroups: ntdev
To: NT Developers Interest List
Sent: Sunday, September 15, 2002 3:29 PM
Subject: [ntdev] Re: Bulk stream transfer using double buffer

Your code is very confusing. First in your dispatch routine, you should propagate the status returned by IoCallDriver. If you always return STATUS_SUCCESS bad things might happen if the lower driver returned something other than STATUS_SUCCESS. If you are going to pend the IRP then mark the IRP pending and return STATUS_PENDING. The completion routine seems to initialize an IRP and then overwrites the local variable IRP with a different IRP allocated by IoBuildDeviceIoControlRequest.

I think looking at your code, the driver verfier should be able to catch a lot of these problems. Run the driver verifier on your driver (use the verifier.exe tool) and it should bugcheck earlier and give a you much better picture of where the problem should be.


Nar Ganapathy
Windows Core OS group
This posting is provided “AS IS” with no warranties, and confers no rights.

“HyungJune Kim” wrote in message news:xxxxx@ntdev…
Hi,

I’m developing a USB 2.0 device driver.
I have tried to transfer stream data using BULK pipe.

The user sends DeviceIoControl( IOCTL_BULK_STREAM_START, … ) to start
data streaming, and the driver send device-allocated IRP.

I set the completion routine for a driver-allocated IRP, and in the completion routine
previous allocated IRP is resent to lower device.

My question is :
When the driver-allocated IRP is completed, I expected to be called the completion routine.

But when completed, system shut down. The softICE tells “Page fault” error message.

Followings are skeleton of my code.
What’s the problem?

========================================================================
NTSTATUS StartBulkTransfer(…)
{



//
// Set a completion routine
//
IoSetCompletionRoutine(streamObject->TransferObject->Irp,
BulkStreamTransferComplete,
&streamObject->TransferObject,
TRUE,
TRUE,
TRUE
);

pdx->StopBulkStream = FALSE;

ntStatus = IoCallDriver(pdx->StackDeviceObject,
streamObject->TransferObject->Irp);

Ezusb_KdPrint ((“return from IoCallDriver USBD %x\n”, ntStatus));
return STATUS_SUCCESS;
}

NTSTATUS BulkStreamTransferComplete(…) // Completion routine
{



IoInitializeIrp(Irp,
IoSizeOfIrp((pdx->StackDeviceObject->StackSize + 1)),
(CCHAR)(pdx->StackDeviceObject->StackSize + 1));

nextStack = IoGetNextIrpStackLocation(Irp);

nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

KeInitializeEvent(&event, NotificationEvent, FALSE);

Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);

// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);

// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = urb;

IoSetCompletionRoutine(Irp,
BulkStreamTransferComplete,
transferObject,
TRUE,
TRUE,
TRUE);

//
// submit the request
//
status = IoCallDriver(pdx->StackDeviceObject,Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}


You are currently subscribed to ntdev as: xxxxx@hynix.com
To unsubscribe send a blank email to %%email.unsub%%

You are currently subscribed to ntdev as: xxxxx@hynix.com
To unsubscribe send a blank email to xxxxx@lists.osr.com