?? liubo2004666_ezusbsys.c
字號:
} else {
// Failed getting data buffer (configurationDescriptor) memory
ntStatus = STATUS_NO_MEMORY;
goto Exit_EzusbConfigureDevice;
}//if-else
} else {
// failed getting urb memory
ntStatus = STATUS_NO_MEMORY;
goto Exit_EzusbConfigureDevice;
}//if-else
/*
// We have the configuration descriptor for the configuration
// we want.
//
// Now we issue the SelectConfiguration command to get
// the pipes associated with this configuration.
*/
if (configurationDescriptor) {
// Get our pipes
ntStatus = Ezusb_SelectInterfaces(fdo,
configurationDescriptor,
NULL // Device not yet configured
);
} //if
Exit_EzusbConfigureDevice:
// Clean up and exit this routine
if (urb != NULL) {
ExFreePool(urb); // Free urb memory
}//if
if (configurationDescriptor != NULL) {
ExFreePool(configurationDescriptor);// Free data buffer
}//if
Ezusb_KdPrint (("exit Ezusb_ConfigureDevice (%x)\n", ntStatus));
return ntStatus;
}//Ezusb_ConfigureDevice
NTSTATUS
Ezusb_SelectInterfaces(
IN PDEVICE_OBJECT fdo,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN PUSBD_INTERFACE_INFORMATION Interface
)
/*++
Routine Description:
Initializes an Ezusb Device with multiple interfaces
Arguments:
fdo - pointer to the device object for this instance of the Ezusb Device
ConfigurationDescriptor - pointer to the USB configuration descriptor containing the interface and endpoint
descriptors.
Interface - pointer to a USBD Interface Information Object
- If this is NULL, then this driver must choose its interface based on driver-specific
criteria, and the driver must also CONFIGURE the device.
- If it is NOT NULL, then the driver has already been given an interface and
the device has already been configured by the parent of this device driver.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION pdx;
NTSTATUS ntStatus;
PURB urb;
ULONG j;
UCHAR alternateSetting, MyInterfaceNumber;
PUSBD_INTERFACE_INFORMATION interfaceObject;
USBD_INTERFACE_LIST_ENTRY interfaceList[2];
Ezusb_KdPrint (("enter Ezusb_SelectInterfaces\n"));
pdx = fdo->DeviceExtension;
MyInterfaceNumber = SAMPLE_INTERFACE_NBR;
// Search the configuration descriptor for the first interface/alternate setting
interfaceList[0].InterfaceDescriptor =
USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
ConfigurationDescriptor,
-1, // Interface - don't care
-1, // Alternate Setting - don't care
-1, // Class - don't care
-1, // SubClass - don't care
-1); // Protocol - don't care
ASSERT(interfaceList[0].InterfaceDescriptor != NULL);
interfaceList[1].InterfaceDescriptor = NULL;
interfaceList[1].Interface = NULL;
urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,&interfaceList[0]);
if (!urb)
{
Ezusb_KdPrint ((" USBD_CreateConfigurationRequestEx failed\n"));
}
DumpBuffer(urb, urb->UrbHeader.Length);
interfaceObject = (PUSBD_INTERFACE_INFORMATION) (&(urb->UrbSelectConfiguration.Interface));
/*
// We set up a default max transfer size for the endpoints. Your driver will
// need to change this to reflect the capabilities of your device's endpoints.
*/
for (j=0; j<interfaceList[0].InterfaceDescriptor->bNumEndpoints; j++)
interfaceObject->Pipes[j].MaximumTransferSize = (64 * 1024) - 1;
ntStatus = Ezusb_CallUSBD(fdo, urb);
DumpBuffer(urb, urb->UrbHeader.Length);
if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(urb->UrbHeader.Status))
{
// Save the configuration handle for this device
pdx->ConfigurationHandle =
urb->UrbSelectConfiguration.ConfigurationHandle;
pdx->Interface = ExAllocatePool(NonPagedPool,
interfaceObject->Length);
// save a copy of the interfaceObject information returned
RtlCopyMemory(pdx->Interface, interfaceObject, interfaceObject->Length);
// Dump the interfaceObject to the debugger
Ezusb_KdPrint (("---------\n"));
Ezusb_KdPrint (("NumberOfPipes 0x%x\n", pdx->Interface->NumberOfPipes));
Ezusb_KdPrint (("Length 0x%x\n", pdx->Interface->Length));
Ezusb_KdPrint (("Alt Setting 0x%x\n", pdx->Interface->AlternateSetting));
Ezusb_KdPrint (("Interface Number 0x%x\n", pdx->Interface->InterfaceNumber));
// Dump the pipe info
for (j=0; j<interfaceObject->NumberOfPipes; j++)
{
PUSBD_PIPE_INFORMATION pipeInformation;
pipeInformation = &pdx->Interface->Pipes[j];
Ezusb_KdPrint (("---------\n"));
Ezusb_KdPrint (("PipeType 0x%x\n", pipeInformation->PipeType));
Ezusb_KdPrint (("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
Ezusb_KdPrint (("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
Ezusb_KdPrint (("Interval 0x%x\n", pipeInformation->Interval));
Ezusb_KdPrint (("Handle 0x%x\n", pipeInformation->PipeHandle));
Ezusb_KdPrint (("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
}
Ezusb_KdPrint (("---------\n"));
}
Ezusb_KdPrint (("exit Ezusb_SelectInterfaces (%x)\n", ntStatus));
return ntStatus;
}/* Ezusb_SelectInterfaces */
NTSTATUS
Ezusb_Read_Write(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
Return Value:
NT status code
STATUS_SUCCESS: Read was done successfully
STATUS_INVALID_PARAMETER_3: The Endpoint Index does not specify an IN pipe
STATUS_NO_MEMORY: Insufficient data memory was supplied to perform the READ
This routine fills the status code into the Irp
--*/
{
PDEVICE_EXTENSION pdx = fdo->DeviceExtension;
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
PBULK_TRANSFER_CONTROL bulkControl =
(PBULK_TRANSFER_CONTROL)Irp->AssociatedIrp.SystemBuffer;
ULONG bufferLength =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
PURB urb = NULL;
ULONG urbSize = 0;
ULONG transferFlags = 0;
PUSBD_INTERFACE_INFORMATION interfaceInfo = NULL;
PUSBD_PIPE_INFORMATION pipeInfo = NULL;
USBD_PIPE_HANDLE pipeHandle = NULL;
Ezusb_KdPrint(("enter Ezusb_Read_Write()\n"));
//
// verify that the selected pipe is valid, and get a handle to it. If anything
// is wrong, return an error
//
interfaceInfo = pdx->Interface;
if (!interfaceInfo)
{
Ezusb_KdPrint(("Ezusb_Read_Write() no interface info - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
if (bulkControl->pipeNum > interfaceInfo->NumberOfPipes)
{
Ezusb_KdPrint(("Ezusb_Read_Write() invalid pipe - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
pipeInfo = &(interfaceInfo->Pipes[bulkControl->pipeNum]);
if (!((pipeInfo->PipeType == UsbdPipeTypeBulk) ||
(pipeInfo->PipeType == UsbdPipeTypeInterrupt)))
{
Ezusb_KdPrint(("Ezusb_Read_Write() invalid pipe - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
pipeHandle = pipeInfo->PipeHandle;
if (!pipeHandle)
{
Ezusb_KdPrint(("Ezusb_Read_Write() invalid pipe - Exiting\n"));
return STATUS_UNSUCCESSFUL;
}
if (bufferLength > pipeInfo->MaximumTransferSize)
{
Ezusb_KdPrint(("Ezusb_Read_Write() invalid transfer size - Exiting\n"));
return STATUS_INVALID_PARAMETER;
}
//
// allocate and fill in the Usb request (URB)
//
urbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
urb = ExAllocatePool(NonPagedPool,urbSize);
if (!urb)
{
Ezusb_KdPrint(("Ezusb_Read_Write() unable to alloc URB - Exiting\n"));
return STATUS_NO_MEMORY;
}
transferFlags = USBD_SHORT_TRANSFER_OK;
//
// get direction info from the endpoint address
//
if (USB_ENDPOINT_DIRECTION_IN(pipeInfo->EndpointAddress))
transferFlags |= USBD_TRANSFER_DIRECTION_IN;
UsbBuildInterruptOrBulkTransferRequest(urb, //ptr to urb
(USHORT) urbSize, //size of urb
pipeHandle, //usbd pipe handle
NULL, //TransferBuffer
Irp->MdlAddress, //mdl
bufferLength, //bufferlength
transferFlags, //flags
NULL); //link
//
// Call the USB Stack.
//
ntStatus = Ezusb_CallUSBD(fdo, urb);
//
// If the transfer was successful, report the length of the transfer to the
// caller by setting IoStatus.Information
//
if (NT_SUCCESS(ntStatus))
{
Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
Ezusb_KdPrint(("Successfully transfered 0x%x bytes\n",Irp->IoStatus.Information));
}
//
// free the URB
//
ExFreePool(urb);
return ntStatus;
}
NTSTATUS
Ezusb_Create(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
This is the Entry point for CreateFile calls from user mode apps (apps may open "\\.\Ezusb-x\yyzz"
where yy is the interface number and zz is the endpoint address).
Here is where you would add code to create symbolic links between endpoints
(i.e., pipes in USB software terminology) and User Mode file names. You are
free to use any convention you wish to create these links, although the above
convention offers a way to identify resources on a device by familiar file and
directory structure nomenclature.
Arguments:
fdo - pointer to the device object for this instance of the Ezusb device
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION )fdo->DeviceExtension;
Ezusb_KdPrint(("Enter Ezusb_Create()\n"));
if (!pdx->Started)
{
return STATUS_UNSUCCESSFUL;
}
// increment the open handle counter
pdx->OpenHandles++;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// Create all the symbolic links here
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
return ntStatus;
}//Ezusb_Create
NTSTATUS
Ezusb_Close(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
Entry point for CloseHandle calls from user mode apps to close handles they have opened
Arguments:
fdo - pointer to the device object for this instance of the Ezusb device
Irp - pointer to an irp
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION )fdo->DeviceExtension;
Ezusb_KdPrint(("Enter Ezusb_Close()\n"));
// decrement the open handle counter
pdx->OpenHandles--;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
return ntStatus;
}//Ezusb_Close
NTSTATUS
Ezusb_ProcessIOCTL(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
/*++
Routine Description:
This where all the DeviceIoControl codes are handled. You can add mor
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -