It should be a simple problem to you.
One switch of the DEVICE_IO_CONTROL_CODE in my IRP_MJ_DEVICE_CONTROL
dispatch routine ,
i use UsbBuildVendorRequest marco like this .
Inside the BulkUsb_CallUSBD ,The status returned by IoCallDriver is IRP
pending ,
the USB trasfer between driver and firware had been completed,but
KeWaitForSingleObject function in BulkUsb_CallUSBD is never return.. ???
in dispatch routine:
PURB OutputPinURB;
USHORT URBsiz;
USHORT OutputPin;
URBsiz=sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
OutputPinURB=ExAllocatePool(NonPagedPool,URBsiz);
OutputPin=Extension->OutputPin;
UsbBuildVendorRequest(OutputPinURB,
URB_FUNCTION_CLASS_INTERFACE ,
URBsiz,
0,//FLAG
0,
0x22,
OutputPin,
0,
NULL, //BUFFER
NULL,
0,
NULL);
//then , call the BulkUsb function , to pass the urb done
Status= BulkUsb_CallUSBD(DeviceObject,OutputPinURB);
BulkUsb_CallUSBD : there is almode no any modification of sample code
"BulkUSB" , except "deviceExtension->TopDeviceObject"
changed as "deviceExtension->LowerDeviceObject" .
NTSTATUS
BulkUsb_CallUSBD(
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
/*++
Routine Description:
Passes a URB to the USBD class driver
The client device driver passes USB request block (URB) structures
to the class driver as a parameter in an IRP with Irp->MajorFunction
set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location
Parameters.DeviceIoControl.IoControlCode field set to
IOCTL_INTERNAL_USB_SUBMIT_URB.
Arguments:
DeviceObject - pointer to the physical device object (PDO)
Urb - pointer to an already-formatted Urb request block
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PSERIAL_DEVICE_EXTENSION deviceExtension;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
SerialDump(SERIRPPATH,("enter BulkUsb_CallUSBD\n"));
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceExtension->LowerDeviceObject, //Points to the
next-lower driver's device object
NULL, // optional input bufer; none needed here
0, // input buffer len if used
NULL, // optional output bufer; none needed here
0, // output buffer len if used
TRUE, // If InternalDeviceControl is TRUE the target
driver's Dispatch
// outine for IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_SCSI
// is called; otherwise, the Dispatch routine for
// IRP_MJ_DEVICE_CONTROL is called.
&event, // event to be signalled on completion
&ioStatus); // Specifies an I/O status block to be set when
the request is completed the lower driver.
//
// As an alternative, we could call KeDelayExecutionThread, wait for
some
// period of time, and try again....but we keep it simple for right now
//
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Call the class driver to perform the operation. If the returned
status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
BULKUSB_ASSERT(nextStack != NULL);
//
// pass the URB to the USB driver stack
//
nextStack->Parameters.Others.Argument1 = Urb;
ntStatus = IoCallDriver(deviceExtension->LowerDeviceObject, irp);
SerialDump(SERIRPPATH,("BulkUsb_CallUSBD() return from IoCallDriver USBD
%x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
} else {
ioStatus.Status = ntStatus;
}
SerialDump(SERIRPPATH,("BulkUsb_CallUSBD() URB status = %x status = %x
irp status %x\n",
Urb->UrbHeader.Status, status, ioStatus.Status));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
SerialDump(SERIRPPATH,("exit BulkUsb_CallUSBD (%x)\n", ntStatus));
return ntStatus;
}