20楼#
发布于:2002-03-28 21:36
USB等时传输
例程如下: NTSTATUS Iso_ReadWrite(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN BOOLEAN Read) { NTSTATUS ntStatus = STATUS_SUCCESS; PUSBD_PIPE_INFORMATION pipeHandle; PFILE_OBJECT fileObject; PIO_STACK_LOCATION irpStack, nextStack; PDEVICE_EXTENSION deviceExtension; PURB urb; PUSB_RW_CONTEXT context = NULL; if (!Irp->MdlAddress) { // this is NULL for a 0-len request; just return SUCCESS goto IsoUsb_Read_Reject; } Pub_IncrementIoCount(DeviceObject); deviceExtension = DeviceObject->DeviceExtension; //=========================================== if (!Pub_CanAcceptIoRequests(DeviceObject)) { ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Status = ntStatus; //=========================================== Pub_DecrementIoCount(DeviceObject); IoCompleteRequest (Irp, IO_NO_INCREMENT); return ntStatus; } irpStack = IoGetCurrentIrpStackLocation (Irp); fileObject = irpStack->FileObject; pipeHandle = fileObject->FsContext; if (!pipeHandle) { ntStatus = STATUS_INVALID_HANDLE; goto IsoUsb_Read_Reject; } // submit the write request to USB //============================================================= Usb_ResetPipe(DeviceObject, pipeHandle, FALSE); //============================================================ urb = Usb_BuildIsoRequest(DeviceObject, Irp, pipeHandle, TRUE); if (urb) { nextStack = IoGetNextIrpStackLocation(Irp); ASSERT(nextStack != NULL); ASSERT(DeviceObject->StackSize>1); nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; nextStack->Parameters.Others.Argument1 = urb; nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; //======================================================= IoSetCompletionRoutine(Irp, Usb_IsoReadWrite_Complete, urb, // pass URB as context TRUE, // invoke on success TRUE, // invoke on error TRUE); // invoke on cancel ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); goto IsoUsb_Read_Done; } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } IsoUsb_Read_Reject: Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); IsoUsb_Read_Done: return ntStatus; } NTSTATUS Usb_ResetPipe( IN PDEVICE_OBJECT DeviceObject, IN PUSBD_PIPE_INFORMATION Pipe, IN BOOLEAN IsoClearStall ) { NTSTATUS ntStatus; PURB urb; urb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST)); if (urb) { urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST); urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE; urb->UrbPipeRequest.PipeHandle = Pipe->PipeHandle; //============================================================== ntStatus = Usb_CallUSBD(DeviceObject, urb); ExFreePool(urb); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } if (NT_SUCCESS(ntStatus) && IsoClearStall && (Pipe->PipeType == UsbdPipeTypeIsochronous)) { urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_FEATURE_REQUEST)); if (urb) { UsbBuildFeatureRequest(urb, URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT, USB_FEATURE_ENDPOINT_STALL, Pipe->EndpointAddress, NULL); //=============================================================== ntStatus = Usb_CallUSBD(DeviceObject, urb); ExFreePool(urb); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } } return ntStatus; } PURB Usb_BuildIsoRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PUSBD_PIPE_INFORMATION PipeHandle, IN BOOLEAN Read) { ULONG siz; ULONG length, packetSize, numPackets, i; PURB urb = NULL; PIO_STACK_LOCATION irpSp; LARGE_INTEGER byteOffset; irpSp = IoGetCurrentIrpStackLocation(Irp); length = MmGetMdlByteCount(Irp->MdlAddress); byteOffset = irpSp->Parameters.Read.ByteOffset; packetSize = PipeHandle->MaximumPacketSize; numPackets = length/packetSize; if (numPackets*packetSize < length) { numPackets++; } siz = GET_ISO_URB_SIZE(numPackets); urb = ExAllocatePool(NonPagedPool, siz); if (urb) { RtlZeroMemory(urb, siz); urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) siz; urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER; urb->UrbIsochronousTransfer.PipeHandle = PipeHandle->PipeHandle; urb->UrbIsochronousTransfer.TransferFlags = Read ? USBD_TRANSFER_DIRECTION_IN : 0; urb->UrbIsochronousTransfer.TransferBufferMDL = Irp->MdlAddress; urb->UrbIsochronousTransfer.TransferBufferLength = length; if (byteOffset.HighPart) {//======================================== urb->UrbIsochronousTransfer.StartFrame = Usb_GetCurrentFrame(DeviceObject, Irp) + byteOffset.LowPart; } else { // start sending/receiving right away urb->UrbIsochronousTransfer.TransferFlags |= USBD_START_ISO_TRANSFER_ASAP; } urb->UrbIsochronousTransfer.NumberOfPackets = numPackets; urb->UrbIsochronousTransfer.UrbLink = NULL; for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) { urb->UrbIsochronousTransfer.IsoPacket[ i ].Offset = i * packetSize; } } return urb; } ULONG Usb_GetCurrentFrame ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION nextStack; NTSTATUS ntStatus; struct _URB_GET_CURRENT_FRAME_NUMBER urb; deviceExtension = DeviceObject->DeviceExtension; // Initialize the URB // urb.Hdr.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER; urb.Hdr.Length = sizeof(urb); urb.FrameNumber = (ULONG)-1; // Set the IRP parameters to pass the URB down the stack // nextStack = IoGetNextIrpStackLocation(Irp); nextStack->Parameters.Others.Argument1 = &urb; nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; // Since this Irp is borrowed for URB_FUNCTION_GET_CURRENT_FRAME_NUMBER // before it is passed down later for the real URB request after this // routine returns, set a completion routine which stop further completion // of the Irp. // IoSetCompletionRoutine( Irp, Usb_IsoCompletionStop, // this routine does nothing but return STATUS_MORE_PROCESSING_REQUIRED NULL, // Context TRUE, // InvokeOnSuccess TRUE, // InvokeOnError TRUE); // InvokeOnCancel // Now pass the Irp down the stack // ntStatus = IoCallDriver( deviceExtension->TopOfStackDeviceObject, Irp); // Don\'t need to wait for completion because // URB_FUNCTION_GET_CURRENT_FRAME_NUMBER will never return STATUS_PENDING return urb.FrameNumber; } NTSTATUS Usb_IsoCompletionStop ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS Usb_IsoReadWrite_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { NTSTATUS ntStatus = STATUS_SUCCESS; PURB urb = Context; PUSBD_PIPE_INFORMATION pipeHandle; PFILE_OBJECT fileObject; PIO_STACK_LOCATION irpStack; ULONG i; if (Irp->PendingReturned) { IoMarkIrpPending(Irp); } // ISSUE: check here for interesting iso error conditions for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) { if (!USBD_SUCCESS( urb->UrbIsochronousTransfer.IsoPacket[ i ].Status)) { ntStatus = STATUS_UNSUCCESSFUL; // set error return code } } Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength; irpStack = IoGetCurrentIrpStackLocation (Irp); fileObject = irpStack->FileObject; // get pipe handle pipeHandle = fileObject->FsContext; Pub_DecrementIoCount(DeviceObject); ExFreePool(urb); return ntStatus; } [编辑 - 3/29/02 作者: plasma] |
|
21楼#
发布于:2002-03-28 21:44
USB等时传输流控制
例程如下: NTSTATUS Usb_StartIsoStream( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { ULONG i; NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; ULONG inputBufferLength; ULONG outputBufferLength; PULONG_PTR streamObjectHandle; PISOUSB_STREAM_OBJECT streamObject; LARGE_INTEGER dueTime; BOOLEAN inQueue; PUSBD_PIPE_INFORMATION PipeInfo; PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation (Irp); streamObjectHandle = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; if (outputBufferLength < sizeof(*streamObjectHandle)) { Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER; } streamObject = ExAllocatePool(NonPagedPool, sizeof(ISOUSB_STREAM_OBJECT)); if (streamObject) { RtlZeroMemory(streamObject, sizeof(ISOUSB_STREAM_OBJECT)); // hard code to 5th pipe; this is the iso in pipe on our test board PipeInfo = &(deviceExtension->UsbInterface->Pipes[4]); deviceExtension->PipeInfo[4].fPipeOpened = TRUE; // set flag for this pipe opened deviceExtension->OpenPipeCount++; // try to power up device if its not already in D0 Usb_SelfSuspendOrActivate(DeviceObject, FALSE); streamObject->DeviceObject = DeviceObject; streamObject->PipeInfo = PipeInfo; streamObject->IsoStreamStarted = TRUE; // event to be set when PendingIrps == 0; signals stream can be stopped KeInitializeEvent(&streamObject->NoPendingIrpEvent, NotificationEvent, FALSE); // This initializes the pair of IRP/URBS that we will keep endlessly recycling // until the Iso stream is stoppped; at least one of these pairs will always be in // use and one will be available so continuous throughput is maintained. for (i=0; i< ISOUSB_MAX_IRP; i++) { //=============================================================== ntStatus = Usb_StartTransfer(DeviceObject, streamObject, i); if (!NT_SUCCESS(ntStatus)) { ; break; } } // We are returning the pointer to our stream object as an untyped handle to the user *streamObjectHandle = (ULONG_PTR) streamObject; // start the timeout DPC KeInitializeTimer(&streamObject->TimeoutTimer); //==================================================== KeInitializeDpc(&streamObject->TimeoutDpc, Usb_StreamTimeoutDPC, streamObject); dueTime.QuadPart = -10000 * ISOUSB_STREAM_TIMEOUT_INTERVAL; inQueue = KeSetTimer(&streamObject->TimeoutTimer, dueTime, &streamObject->TimeoutDpc); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } // We are returning the size of our stream object pointer to the user Irp->IoStatus.Information = sizeof(*streamObjectHandle); Irp->IoStatus.Status = ntStatus; return ntStatus; } NTSTATUS Usb_StartTransfer( IN PDEVICE_OBJECT DeviceObject, IN PISOUSB_STREAM_OBJECT StreamObject, IN ULONG Index) { NTSTATUS ntStatus = STATUS_SUCCESS; CCHAR stackSize; PDEVICE_EXTENSION deviceExtension; PISOUSB_TRANSFER_OBJECT transferObject; ULONG packetSize, numPackets, maxXferSize; maxXferSize = StreamObject->PipeInfo->MaximumTransferSize; // We set this packetSize = StreamObject->PipeInfo->MaximumPacketSize; // USBD sets this numPackets = maxXferSize / packetSize; deviceExtension = DeviceObject->DeviceExtension; transferObject = ExAllocatePool(NonPagedPool, sizeof(ISOUSB_TRANSFER_OBJECT)); if (transferObject) { PIRP irp; RtlZeroMemory(transferObject,sizeof(ISOUSB_TRANSFER_OBJECT)); StreamObject->TransferObjectList[Index] = transferObject; transferObject->StreamObject = StreamObject; stackSize = (CCHAR)(deviceExtension->TopOfStackDeviceObject->StackSize + 1); transferObject->Irp = irp = IoAllocateIrp(stackSize, FALSE); transferObject->DataBuffer = ExAllocatePool(NonPagedPool, numPackets * StreamObject->PipeInfo->MaximumPacketSize); transferObject->Urb = ExAllocatePool(NonPagedPool, GET_ISO_URB_SIZE(numPackets)); if (transferObject->Urb && transferObject->DataBuffer) { PIO_STACK_LOCATION nextStack; NTSTATUS status; //============================================================= Usb_InitializeStreamUrb(DeviceObject, transferObject); nextStack = IoGetNextIrpStackLocation(irp); ASSERT(nextStack != NULL); nextStack->Parameters.Others.Argument1 = transferObject->Urb; nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; //========================================================= IoSetCompletionRoutine(irp, Usb_IsoIrp_Complete, transferObject, //pass transfer object as Context TRUE, // Invoke on Success TRUE, // Invoke on Error TRUE); // Invoke on Cancel // // submit the request // StreamObject->PendingIrps++; // increment this stream\'s pending irp count Pub_IncrementIoCount(DeviceObject); // also increment global pending IRP count status = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; if (transferObject->DataBuffer) { ExFreePool(transferObject->DataBuffer); } if (transferObject->Urb) { ExFreePool(transferObject->Urb); } } } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } return ntStatus; } NTSTATUS Usb_IsoIrp_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { NTSTATUS status; PDEVICE_EXTENSION deviceExtension; PDEVICE_OBJECT deviceObject; PISOUSB_TRANSFER_OBJECT transferObject; PISOUSB_STREAM_OBJECT streamObject; PIO_STACK_LOCATION nextStack; transferObject = Context; streamObject = transferObject->StreamObject; deviceObject = streamObject->DeviceObject; deviceExtension = deviceObject->DeviceExtension; streamObject->PendingIrps--; // Decrement this stream\'s pending irp count if (!streamObject->PendingIrps) { // back to 0? signal no pending irps event KeSetEvent(&streamObject->NoPendingIrpEvent, 1, FALSE); } Pub_DecrementIoCount(deviceObject); // also deccrement global pending IRP count // Check the IRP and URB status in the transferObject // Here is where a driver for a real device would collect and/or process data in the buffers //========================================================== status = Usb_ProcessTransfer(transferObject); if(!NT_SUCCESS(status)) { Usb_ResetParentPort(DeviceObject); } // See if a stop stream has been requested.. if(streamObject->IsoStreamStarted) {// this is set FALSE when we get a stop stream ioctl request // Last xfer was OK and no stop has been requested; // Resubmit the whole thing again and recycle it.. //======================================================= Usb_InitializeStreamUrb(DeviceObject, transferObject); nextStack = IoGetNextIrpStackLocation(Irp); ASSERT(nextStack != NULL); nextStack->Parameters.Others.Argument1 = transferObject->Urb; nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; IoSetCompletionRoutine(Irp, Usb_IsoIrp_Complete, transferObject, //pass transfer object as Context TRUE, // Invoke on Success TRUE, // Invoke on Error TRUE); // Invoke on Cancel // increment this stream object\'s pending irp count streamObject->PendingIrps++; // increment this stream object\'s total times recycled count streamObject->TimesRecycled++; // also increment global pending IRP count Pub_IncrementIoCount(deviceObject); // // Resubmit the request... // Note that if the driver has actually done a fair amount of data processing // or copying from packet buffers, you may want to schedule a dpc // to resubmit instead of doing it here // status = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } return STATUS_MORE_PROCESSING_REQUIRED; } //================================================= NTSTATUS Usb_ProcessTransfer(IN PISOUSB_TRANSFER_OBJECT TransferObject) { NTSTATUS ntStatus; USBD_STATUS usbdStatus; PIRP irp; PURB urb; PISOUSB_STREAM_OBJECT StreamObject; ULONG i; irp = TransferObject->Irp; StreamObject = TransferObject->StreamObject; urb = TransferObject->Urb; ntStatus = irp->IoStatus.Status; if (!NT_SUCCESS(ntStatus)) { ; } else { } // now check the urb header usbdStatus = urb->UrbHeader.Status; if (!USBD_SUCCESS(usbdStatus)) { ; } else { } // check the Urb packets for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) { StreamObject->TotalPacketsProcessed++; if (!USBD_SUCCESS(urb->UrbIsochronousTransfer.IsoPacket[ i ].Status)) { ntStatus = STATUS_UNSUCCESSFUL; // set error return code StreamObject->ErrorPacketCount++; } else { // Successfull; // Note that here is the place we would do any data processing/copying to frame // buffers, for example , if we were a video capture device, etc ... StreamObject->TotalBytesProcessed += urb->UrbIsochronousTransfer.IsoPacket[ i ].Length; } } return ntStatus; } NTSTATUS Usb_StopIsoStream( IN PDEVICE_OBJECT DeviceObject, IN PISOUSB_STREAM_OBJECT StreamObject, IN PIRP Irp ) { PUSBD_PIPE_INFORMATION pipe; int i; PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ULONG packetSize, numPackets, maxXferSize; // validate the input parm; its DeviceObject member should match our DeviceObject // See if we were called with a bogus or NULL StreamObject parm; // This could happen if user calls without ever having successfully started a stream if (!StreamObject || (StreamObject->DeviceObject != DeviceObject)) return STATUS_INVALID_PARAMETER; maxXferSize = StreamObject->PipeInfo->MaximumTransferSize; // We set this packetSize = StreamObject->PipeInfo->MaximumPacketSize; // USBD sets this numPackets = maxXferSize / packetSize; // Tell Usb_StreamTimeoutDPC() not to reschedule itself on next timeout // This also flags Usb_IsoIrp_Complete() to stop recycling the pair of stream IRP/Urbs StreamObject->IsoStreamStarted = FALSE; // Wait for any io request pending for this stream object to // complete before returning success. // This event is set when streamObject->PendingIrpCount goes to 0 KeWaitForSingleObject( &StreamObject->NoPendingIrpEvent, Suspended, KernelMode, FALSE, NULL); // Free all the buffers, URBS, and Irps associated with our stream object for (i=0; i< ISOUSB_MAX_IRP; i++) { PISOUSB_TRANSFER_OBJECT transferObject; transferObject = StreamObject->TransferObjectList[ i ]; IoFreeIrp(transferObject->Irp); ExFreePool(transferObject->Urb); ExFreePool(transferObject->DataBuffer); ExFreePool(transferObject); } ExFreePool(StreamObject); // also free the stream object itself // Close our Iso input pipe; // Hard-code to 5th pipe; this is the iso input pipe on our test board pipe = &(deviceExtension->UsbInterface->Pipes[4]); deviceExtension->PipeInfo[4].fPipeOpened = FALSE; // set flag for this pipe closed deviceExtension->OpenPipeCount--; // ISSUE? Not sure why this is neccesary, but it is... Usb_ResetParentPort(DeviceObject); // try to power down device if we just closed the last open pipe Usb_SelfSuspendOrActivate(DeviceObject, TRUE); return STATUS_SUCCESS; } NTSTATUS Usb_InitializeStreamUrb( IN PDEVICE_OBJECT DeviceObject, IN PISOUSB_TRANSFER_OBJECT TransferObject) { NTSTATUS ntStatus = STATUS_SUCCESS; ULONG siz; ULONG packetSize, numPackets, maxXferSize, i; PURB urb; PISOUSB_STREAM_OBJECT streamObject = TransferObject->StreamObject; urb = TransferObject->Urb; maxXferSize = streamObject->PipeInfo->MaximumTransferSize; // We set this packetSize = streamObject->PipeInfo->MaximumPacketSize; // USBD sets this numPackets = maxXferSize / packetSize; siz = GET_ISO_URB_SIZE(numPackets); RtlZeroMemory(urb, siz); urb->UrbIsochronousTransfer.Hdr.Length = (USHORT) siz; urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER; urb->UrbIsochronousTransfer.PipeHandle = streamObject->PipeInfo->PipeHandle; // We are reading from the device urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN; // A device will always use either TransferBufferMDL or TransferBuffer, NEVER both urb->UrbIsochronousTransfer.TransferBufferMDL = NULL; urb->UrbIsochronousTransfer.TransferBuffer = TransferObject->DataBuffer; urb->UrbIsochronousTransfer.TransferBufferLength = numPackets * packetSize; // start sending/receiving right away urb->UrbIsochronousTransfer.TransferFlags |= USBD_START_ISO_TRANSFER_ASAP; urb->UrbIsochronousTransfer.NumberOfPackets = numPackets; urb->UrbIsochronousTransfer.UrbLink = 0; for (i=0; i< urb->UrbIsochronousTransfer.NumberOfPackets; i++) { urb->UrbIsochronousTransfer.IsoPacket[ i ].Offset = i * packetSize; } return ntStatus; } VOID Usb_StreamTimeoutDPC( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { PDEVICE_EXTENSION deviceExtension; PDEVICE_OBJECT deviceObject; PISOUSB_STREAM_OBJECT streamObject; BOOLEAN inQueue; LARGE_INTEGER dueTime; streamObject = DeferredContext; deviceObject = streamObject->DeviceObject; deviceExtension = deviceObject->DeviceExtension; // schedule next one if (streamObject->IsoStreamStarted) { KeInitializeTimer(&streamObject->TimeoutTimer); KeInitializeDpc(&streamObject->TimeoutDpc, Usb_StreamTimeoutDPC, streamObject); dueTime.QuadPart = -10000 * ISOUSB_STREAM_TIMEOUT_INTERVAL; inQueue = KeSetTimer(&streamObject->TimeoutTimer, dueTime, &streamObject->TimeoutDpc); ASSERT(inQueue == FALSE); // assert timer not already in system queue } } [编辑 - 3/29/02 作者: plasma] |
|
22楼#
发布于:2002-03-28 21:57
自定义头文件:
#define BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE (64 *1024) #define USB_MAX_TRANSFER_SIZE 256 // used to track driver-generated io irps for read/write processing typedef struct _USB_RW_CONTEXT { PURB Urb; PDEVICE_OBJECT DeviceObject; PIRP Irp; PMDL Mdl; } USB_RW_CONTEXT, *PUSB_RW_CONTEXT; // used to track information on pipes in use; // currently just to flag if opened or closed typedef struct USB_PIPEINFO { BOOLEAN fPipeOpened; } USB_PIPEINFO, *PUSB_PIPEINFO; #define ISOUSB_MAX_IRP 2 // number of transfer objects to keep recycling #define ISOUSB_STREAM_TIMEOUT_INTERVAL 100 // MS typedef struct _ISOUSB_TRANSFER_OBJECT { struct _ISOUSB_STREAM_OBJECT *StreamObject; PIRP Irp; PURB Urb; PUCHAR DataBuffer; } ISOUSB_TRANSFER_OBJECT, *PISOUSB_TRANSFER_OBJECT; typedef struct _ISOUSB_STREAM_OBJECT { PDEVICE_OBJECT DeviceObject; ULONG PendingIrps; PISOUSB_TRANSFER_OBJECT TransferObjectList[ISOUSB_MAX_IRP]; PUSBD_PIPE_INFORMATION PipeInfo; KDPC TimeoutDpc; KTIMER TimeoutTimer; KEVENT NoPendingIrpEvent; BOOLEAN IsoStreamStarted; ULONG TimesRecycled; ULONG TotalPacketsProcessed; ULONG TotalBytesProcessed; ULONG ErrorPacketCount; } ISOUSB_STREAM_OBJECT, *PISOUSB_STREAM_OBJECT; // // A structure representing the instance information associated with // this particular device. // typedef struct _DEVICE_EXTENSION { // 提交Urbs的设备目标 PDEVICE_OBJECT TopOfStackDeviceObject; // The bus driver object PDEVICE_OBJECT PhysicalDeviceObject; DEVICE_POWER_STATE CurrentDevicePowerState; //USB configuration information 句柄 USBD_CONFIGURATION_HANDLE UsbConfigurationHandle; //以下是带自定义部分 PUSB_CONFIGURATION_DESCRIPTOR UsbConfigurationDescriptor; // ptr to the USB device descriptor // for this device PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor; // we support one interface // this is a copy of the info structure // returned from select_configuration or // select_interface PUSBD_INTERFACE_INFORMATION UsbInterface; //Bus drivers set the appropriate values in this structure in response //to an IRP_MN_QUERY_CAPABILITIES IRP. Function and filter drivers might //alter the capabilities set by the bus driver. DEVICE_CAPABILITIES DeviceCapabilities; // used to save the currently-being-handled system-requested power irp request PIRP PowerIrp; // used to save base Irp (user-originated via IOCTL) of staged read/write request PIRP BaseIrp; // used to save URB of short, non-staged read/write requests PURB BaseUrb; // count of self-staged irps pending ULONG StagedPendingIrpCount; // count of self-staged bytes read or written so far ULONG StagedBytesTransferred; // set when PendingIoCount goes to 0; flags device can be removed KEVENT RemoveEvent; // set when Bulk_AsyncReadWrite_Complete() finishes or cancels last staged io irp KEVENT StagingDoneEvent; // set when PendingIoCount goes to 1 (1st increment was on add device) // this indicates no IO requests outstanding, either user, system, or otherwise KEVENT NoPendingIoEvent; // set to signal driver-generated power request is finished KEVENT SelfRequestedPowerIrpEvent; // spinlock used to protect inc/dec iocount logic KSPIN_LOCK IoCountSpinLock; // incremented when device is added and any IO request is received; // decremented when any io request is completed or passed on, and when device is removed ULONG PendingIoCount; // count of open pipes ULONG OpenPipeCount; // ptr to array of structs to track pipeinfo; // in this basic sample it\'s only used to track if open/closed; PUSB_PIPEINFO PipeInfo; // save ptr to array of info on self-generated IRPS for staged read/writes; // will allocate this separately PUSB_RW_CONTEXT PendingIoIrps; // Name buffer for our named Functional device object link // The name is generated based on the driver\'s class GUID UNICODE_STRING DeviceLinkNameBuffer; //flag set when processing IRP_MN_REMOVE_DEVICE BOOLEAN DeviceRemoved; // flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE BOOLEAN RemoveDeviceRequested; // flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE BOOLEAN StopDeviceRequested; // flag set when device has been successfully started BOOLEAN DeviceStarted; // flag set when IRP_MN_WAIT_WAKE is received and we\'re in a power state // where we can signal a wait BOOLEAN EnabledForWakeup; // used to flag that we\'re currently handling a self-generated power request BOOLEAN SelfPowerIrp; // default power state to power down to on self-suspend ULONG PowerDownLevel; // default maximum transfer per io ULONG MaximumTransferSize; // spinlock used to protect test of deviceExtension->BaseIrp in // Bulk_StagedReadWrite() KSPIN_LOCK FastCompleteSpinlock; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // function prototypes 功能函数原型 NTSTATUS PnP(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS Usb_StartIsoStream(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS Usb_StopIsoStream( IN PDEVICE_OBJECT DeviceObject, IN PISOUSB_STREAM_OBJECT StreamObject, IN PIRP Irp); NTSTATUS Usb_IsoIrp_Complete( IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp, IN PVOID Context); NTSTATUS sys_Control(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); VOID Unload(IN PDRIVER_OBJECT DriverObject); NTSTATUS Usb_StartDevice(IN PDEVICE_OBJECT DeviceObject); NTSTATUS Usb_StopDevice(IN PDEVICE_OBJECT DeviceObject); NTSTATUS PnP_RemoveDevice(IN PDEVICE_OBJECT DeviceObject); NTSTATUS Usb_CallUSBD(IN PDEVICE_OBJECT DeviceObject,IN PURB Urb); NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject); NTSTATUS Usb_ConfigureDevice(IN PDEVICE_OBJECT DeviceObject); NTSTATUS Pub_IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,IN PVOID Context); NTSTATUS pwr_PoRequestCompletion( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus); NTSTATUS pwr_PoSelfRequestCompletion( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus); PURB Usb_BuildIsoRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PUSBD_PIPE_INFORMATION PipeHandle, IN BOOLEAN Read); NTSTATUS Usb_GetPortStatus(IN PDEVICE_OBJECT DeviceObject, IN PULONG PortStatus); NTSTATUS Usb_ResetParentPort(IN IN PDEVICE_OBJECT DeviceObject); NTSTATUS pwr_SelfRequestPowerIrp( IN PDEVICE_OBJECT DeviceObject, IN POWER_STATE PowerState); BOOLEAN pwr_SetDevicePowerState( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_POWER_STATE DeviceState); NTSTATUS Usb_IsoReadWrite_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); NTSTATUS pwr_PowerIrp_Complete( IN PDEVICE_OBJECT NullDeviceObject, IN PIRP Irp, IN PVOID Context); NTSTATUS AddDevice_QueryCapabilities( IN PDEVICE_OBJECT PdoDeviceObject, IN PDEVICE_CAPABILITIES DeviceCapabilities); NTSTATUS Iso_ReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN BOOLEAN Read); NTSTATUS win32_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS win32_Write(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS win32_Create(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS Usb_AbortPipes(IN PDEVICE_OBJECT DeviceObject); NTSTATUS win32_IOCTL(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS Usb_SelectInterface( IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor); NTSTATUS Usb_ResetDevice(IN PDEVICE_OBJECT DeviceObject); NTSTATUS win32_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS Usb_ResetPipe(IN PDEVICE_OBJECT DeviceObject, IN PUSBD_PIPE_INFORMATION Pipe, IN BOOLEAN IsoClearStall); VOID Pub_IncrementIoCount(IN PDEVICE_OBJECT DeviceObject); LONG Pub_DecrementIoCount( IN PDEVICE_OBJECT DeviceObject); NTSTATUS pwr( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS Usb_SelfSuspendOrActivate( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN fSuspend); BOOLEAN Pub_CanAcceptIoRequests( IN PDEVICE_OBJECT DeviceObject); ULONG Usb_GetCurrentFrame ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS Usb_IsoCompletionStop ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); PUSB_PIPEINFO win32_PipeWithName( IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING FileName); NTSTATUS Bulk_ReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN BOOLEAN Read); NTSTATUS Bulk_SingleUrbReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN BOOLEAN Read); PURB Bulk_BuildAsyncRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PUSBD_PIPE_INFORMATION PipeHandle, IN BOOLEAN Read); NTSTATUS Bulk_AsyncReadWrite_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); NTSTATUS Bulk_SimpleReadWrite_Complete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); BOOLEAN Usb_CancelPendingIo(IN PDEVICE_OBJECT DeviceObject); NTSTATUS Usb_StartTransfer( IN PDEVICE_OBJECT DeviceObject, IN PISOUSB_STREAM_OBJECT StreamObject, IN ULONG Index); NTSTATUS Usb_ProcessTransfer(IN PISOUSB_TRANSFER_OBJECT TransferObject); NTSTATUS Usb_InitializeStreamUrb( IN PDEVICE_OBJECT DeviceObject, IN PISOUSB_TRANSFER_OBJECT TransferObject); VOID Usb_StreamTimeoutDPC( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); [编辑 - 3/29/02 作者: plasma] |
|
23楼#
发布于:2002-03-28 22:10
自定义驱动程序与Windows应用程序交互控制码
#define ISOUSB_IOCTL_INDEX 0x8000 #define IOCTL_ISOUSB_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_UNKNOWN, \\ ISOUSB_IOCTL_INDEX,\\ METHOD_BUFFERED, \\ FILE_ANY_ACCESS) #define IOCTL_ISOUSB_RESET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, \\ ISOUSB_IOCTL_INDEX+1,\\ METHOD_BUFFERED, \\ FILE_ANY_ACCESS) #define IOCTL_ISOUSB_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, \\ ISOUSB_IOCTL_INDEX+2,\\ METHOD_BUFFERED, \\ FILE_ANY_ACCESS) #define IOCTL_ISOUSB_STOP_ISO_STREAM CTL_CODE(FILE_DEVICE_UNKNOWN, \\ ISOUSB_IOCTL_INDEX+3,\\ METHOD_BUFFERED, \\ FILE_ANY_ACCESS) #define IOCTL_ISOUSB_START_ISO_STREAM CTL_CODE(FILE_DEVICE_UNKNOWN, \\ ISOUSB_IOCTL_INDEX+4,\\ METHOD_BUFFERED, \\ FILE_ANY_ACCESS) [编辑 - 3/29/02 作者: plasma] |
|
24楼#
发布于:2002-03-28 22:31
应该可以换页了吧!
以上是整理 DDK 中的 USB 驱动例程,下面把这个工程文件打包如下。工程开发环境是VC++6.0,调试WINDOWS 2000 DDK。 下在后请先修改 nmakedrv.bat 愿我的这部分工作能为您、为国人做出点贡献! 一些地方我不是很清楚,希望在大家共同探讨,多把经验帖出来,促进共同进步,促进国人共同提高! |
|
25楼#
发布于:2002-03-28 22:37
上一贴没有换页只好再来一次,这回附带的是自解压文件。
以上是整理 DDK 中的 USB 驱动例程,下面把这个工程文件打包如下。工程开发环境是VC++6.0,调试WINDOWS 2000 DDK。 下在后请先修改 nmakedrv.bat 愿我的这部分工作能为您、为国人做出点贡献! 一些地方我不是很清楚,希望在大家共同探讨,多把经验贴出来,促进共同进步,促进国人共同提高! |
|
26楼#
发布于:2002-03-29 10:16
接口信息结构:
typedef struct _USBD_PIPE_INFORMATION { // OUTPUT // 这一段由USBD填写 USHORT MaximumPacketSize; // 最大传输包大小 UCHAR EndpointAddress; // 8位端点地址(包含方向),有端点描述符获得 UCHAR Interval; // 中断管道轮寻时间(ms) USBD_PIPE_TYPE PipeType; // 管道传输类型 USBD_PIPE_HANDLE PipeHandle; // INPUT // 这一段由客户驱动填写 ULONG MaximumTransferSize; // Maximum size for a single request // in bytes. ULONG PipeFlags; // } USBD_PIPE_INFORMATION, *PUSBD_PIPE_INFORMATION; // values for PipeFlags field in USBD_PIPE_INFORMATION field #define USBD_PF_CHANGE_MAX_PACKET 0x00000001 #define USBD_PF_DOUBLE_BUFFER 0x00000002 #define USBD_PF_FAST_ISO 0x00000004 #define USBD_PF_VALID_MASK (USBD_PF_CHANGE_MAX_PACKET | \\ USBD_PF_DOUBLE_BUFFER) // USBD interface information structure // this structure is returned for each interface opened thru an // SELECT_CONFIGURATION or SELECT_INTERFACE request. typedef struct _USBD_INTERFACE_INFORMATION { USHORT Length; // 结构长度(包括管道信息结构长度) // INPUT // Interface number and Alternate setting this // structure is associated with UCHAR InterfaceNumber; UCHAR AlternateSetting; // OUTPUT // 这一段由USBD填写 UCHAR Class; UCHAR SubClass; UCHAR Protocol; UCHAR Reserved; USBD_INTERFACE_HANDLE InterfaceHandle; ULONG NumberOfPipes; // INPUT/OUPUT // see PIPE_INFORMATION #ifdef OSR21_COMPAT USBD_PIPE_INFORMATION Pipes[0]; #else USBD_PIPE_INFORMATION Pipes[1]; #endif } USBD_INTERFACE_INFORMATION, *PUSBD_INTERFACE_INFORMATION; |
|
27楼#
发布于:2002-04-11 10:00
Thanks very much
:~) |
|
28楼#
发布于:2002-04-11 15:22
例程中既有\"USB等时传输\"又有\"USB等时传输流控制 \",好象
各成一套体系,两者有什么区别和联系? |
|
29楼#
发布于:2002-04-11 18:13
楼上的大侠问的好, 二者有何区别和联系??能否详述?
|
|
30楼#
发布于:2002-04-12 14:51
老兄的耐性和毅力值得尊敬!谢谢!继续努力
|
|
|
31楼#
发布于:2002-04-12 15:24
在工程目录中创建下列4个编译配置文件 请教老兄一个问题,makefile.inc有什么用呢? 我开发驱动怎么没用到呢?? 谢谢! |
|
|
32楼#
发布于:2002-04-12 16:29
我用的是CYPRESS公司的AN2131开发板,现在可以使用HEX2C将HEX文件生成C文件,是否可以直接用DDK生成SYS文件,而不需另外编写程序就能使用新的USB设备?另外请教如何设置和使用DDK?请各位高手赐教,非常感谢
|
|
33楼#
发布于:2002-04-12 16:41
makefile.inc有什么用呢?谢谢请指教
|
|
|
34楼#
发布于:2002-04-12 17:12
文件 Makefile.inc 是在当前工程目录下自己建立的,只要把
PostBuildSteps: $(TARGET) !if \"$(DDKBUILDENV)\"==\"free\" rebase -B 0x10000 -X . $(TARGET) !endif copy $(TARGET) $(WINDIR)\\system32\\drivers 存入即可。 它的作用我已经在注释中写了。 主要是在编译驱动文件时,会自动将编译好的驱动程序copy到系统目录system32\\drivers下,免去了手工copy。 完成这一过程的前提是停止以前编译的驱动程序,如果是类似于USB设备,只要拔下设备,驱动程序就会停止,完成上述copy,再插入设备,新的驱动程序就会启动。 |
|
35楼#
发布于:2002-04-13 08:37
哦,就是重新编译后,不必重新安装驱动了, 可以自动更新了!
谢谢! |
|
|
36楼#
发布于:2002-04-13 14:43
plasma, 能不能讲解一下你的例子中“USB等时传输”和
“USB等时传输流控制 ”有什么联系和区别,谢谢。 |
|
37楼#
发布于:2002-04-13 16:40
Plasma,能不能请教你几个问题,我现在使用的是CYPRESS公司的AN2131开发板,根据文档的说明,可以使用CYPRESS\\USB\\DRIVERS\\HEX2C下面的HEX2C将我自己的HEX文件转换成***.C文件,然后用该文件代替CYPRESS\\USB\\DRIVERS\\EZLOADER下的firmware.C,再用DDK编译生成***.SYS文件。我想请教你,如何使用DDK编译,是不是需要对安装完的DDK进行一些环境的配置,还是直接使用CHECKED或FREE进行编译,再修改一些相关的文件就可以让计算机能使用新的USB设备?在这个过程中是否需要C++?请各位高手不要笑我的问题而不吝赐教,在下非常感谢!!
|
|
38楼#
发布于:2002-04-22 17:01
plasma这样的人少,所以中国的程序员们进步极慢!!!!!!!!!!!!!!!!!!
|
|
39楼#
发布于:2002-04-24 15:06
真的非常感谢你!你太好了!
|
|
|