📄 cioctl.c
字号:
if (inputBufferLength != sizeof(ISO_TRANSFER_CONTROL))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
if (outputBufferLength !=
isoControl->PacketCount * (isoControl->PacketSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR)))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
//
// make sure the ring buffers exist
//
if (!(pdx->DataRingBuffer && pdx->DescriptorRingBuffer))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
break;
}
dataBytesToRead = isoControl->PacketCount * isoControl->PacketSize;
dataBytesRead = ReadRingBuffer(pdx->DataRingBuffer,
MmGetSystemAddressForMdl(Irp->MdlAddress),
dataBytesToRead);
Ezusb_KdPrint(("Copied %d bytes from the data ring buffer\n",dataBytesRead));
descriptorBytesToRead = (dataBytesRead / isoControl->PacketSize) * sizeof(USBD_ISO_PACKET_DESCRIPTOR);
descriptorBytesRead = ReadRingBuffer(pdx->DescriptorRingBuffer,
((PUCHAR) MmGetSystemAddressForMdl(Irp->MdlAddress)) + dataBytesRead,
descriptorBytesToRead);
Ezusb_KdPrint(("Copied %d bytes from the desc ring buffer\n",descriptorBytesRead));
Irp->IoStatus.Information = dataBytesRead + descriptorBytesRead;
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case IOCTL_EZUSB_GET_DRIVER_VERSION:
{
PEZUSB_DRIVER_VERSION version = (PEZUSB_DRIVER_VERSION) ioBuffer;
if (outputBufferLength >= sizeof(EZUSB_DRIVER_VERSION))
{
version->MajorVersion = EZUSB_MAJOR_VERSION;
version->MinorVersion = EZUSB_MINOR_VERSION;
version->BuildVersion = EZUSB_BUILD_VERSION;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(EZUSB_DRIVER_VERSION);
}
else
{
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
}
break;
case IOCTL_EZUSB_SET_FEATURE:
{
//
// verify the input params
//
if (inputBufferLength != sizeof(SET_FEATURE_CONTROL))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
c_SetFeature(fdo,(PSET_FEATURE_CONTROL)Irp->AssociatedIrp.SystemBuffer);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
break;
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
UnlockDevice(fdo);
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp,IO_NO_INCREMENT);
return ntStatus;
}
NTSTATUS c_VendorRequest2(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp
)
{
PDEVICE_EXTENSION pdx = fdo->DeviceExtension;
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
PVENDOR_OR_CLASS_REQUEST_CONTROL requestControl =
(PVENDOR_OR_CLASS_REQUEST_CONTROL) Irp->AssociatedIrp.SystemBuffer;
ULONG bufferLength =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
PURB urb = NULL;
ULONG urbSize = 0;
ULONG transferFlags = 0;
USHORT urbFunction = 0;
//
// verify that the input parameter is correct (or at least that it's
// the right size
//
if (irpStack->Parameters.DeviceIoControl.InputBufferLength !=
sizeof(VENDOR_OR_CLASS_REQUEST_CONTROL))
{
ntStatus = STATUS_INVALID_PARAMETER;
return ntStatus;
}
//
// allocate and fill in the Usb request (URB)
//
urbSize = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
urb = ExAllocatePool(NonPagedPool,urbSize);
if (!urb)
{
return STATUS_NO_MEMORY;
}
RtlZeroMemory(urb,urbSize);
transferFlags = USBD_SHORT_TRANSFER_OK;
//
// get direction info from the input parms
//
if (requestControl->direction)
transferFlags |= USBD_TRANSFER_DIRECTION_IN;
//
// the type of request (class or vendor) and the recepient
// (device, interface, endpoint, other) combine to determine the
// URB function. The following ugly code transforms fields in
// the input param into an URB function
//
switch ((requestControl->requestType << 2) | requestControl->recepient)
{
case 0x04:
urbFunction = URB_FUNCTION_CLASS_DEVICE;
break;
case 0x05:
urbFunction = URB_FUNCTION_CLASS_INTERFACE;
break;
case 0x06:
urbFunction = URB_FUNCTION_CLASS_ENDPOINT;
break;
case 0x07:
urbFunction = URB_FUNCTION_CLASS_OTHER;
break;
case 0x08:
urbFunction = URB_FUNCTION_VENDOR_DEVICE;
break;
case 0x09:
urbFunction = URB_FUNCTION_VENDOR_INTERFACE;
break;
case 0x0A:
urbFunction = URB_FUNCTION_VENDOR_ENDPOINT;
break;
case 0x0B:
urbFunction = URB_FUNCTION_VENDOR_OTHER;
break;
default:
return STATUS_INVALID_PARAMETER;
}
urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
urb->UrbHeader.Function = urbFunction;
urb->UrbControlVendorClassRequest.TransferFlags = transferFlags;
urb->UrbControlVendorClassRequest.TransferBufferLength = bufferLength;
urb->UrbControlVendorClassRequest.TransferBufferMDL = Irp->MdlAddress;
urb->UrbControlVendorClassRequest.Request = requestControl->request;
urb->UrbControlVendorClassRequest.Value = requestControl->value;
urb->UrbControlVendorClassRequest.Index = requestControl->index;
//
// 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->UrbControlVendorClassRequest.TransferBufferLength;
Ezusb_KdPrint(("Successfully transfered 0x%x bytes\n",Irp->IoStatus.Information));
}
if (urb)
ExFreePool(urb);
return ntStatus;
}
ULONG c_VendorRequest(
IN PDEVICE_OBJECT fdo,
IN PVENDOR_REQUEST_IN pVendorRequest
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb = NULL;
ULONG length = 0;
PUCHAR buffer = NULL;
Ezusb_KdPrint (("Enter Ezusb_VendorRequest - yahoooo\n"));
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (urb)
{
RtlZeroMemory(urb,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
//
// fill in the URB
//
urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
urb->UrbControlVendorClassRequest.TransferBufferLength = pVendorRequest->wLength;
urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
urb->UrbControlVendorClassRequest.Request = pVendorRequest->bRequest;
urb->UrbControlVendorClassRequest.Value = pVendorRequest->wValue;
urb->UrbControlVendorClassRequest.Index = pVendorRequest->wIndex;
//
// very kludgey. The idea is: if its an IN then a buffer has been passed
// in from user mode. So, use the pointer to the system buffer as the transfer
// buffer. If the transfer is an out, then we need to allocate a transfer
// buffer. If the length of the transfer is 1, then put pVendorRequest->bData
// in the buffer. Otherwise, fill the buffer with an incrementing byte pattern.
// yuch
//
if (pVendorRequest->direction)
{
urb->UrbControlVendorClassRequest.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
urb->UrbControlVendorClassRequest.TransferBuffer = pVendorRequest;
}
else
{
urb->UrbControlVendorClassRequest.TransferFlags = 0;
buffer = ExAllocatePool(NonPagedPool, pVendorRequest->wLength);
urb->UrbControlVendorClassRequest.TransferBuffer = buffer;
if (pVendorRequest->wLength == 1)
{
buffer[0] = pVendorRequest->bData;
}
else
{
int i;
PUCHAR ptr = buffer;
for (i=0; i < pVendorRequest->wLength; i++)
{
*ptr = (UCHAR) i;
ptr++;
}
}
}
ntStatus = Ezusb_CallUSBD(fdo, urb);
//
// only return a length if this was an IN transaction
//
if (pVendorRequest->direction)
{
length = urb->UrbControlVendorClassRequest.TransferBufferLength;
}
else
{
length = 0;
}
ExFreePool(urb);
if (buffer)
ExFreePool(buffer);
}
return length;
}
//
// this is the number of bytes of firmware to download per setup transfer.
//
#define CHUNK_SIZE 64
NTSTATUS c_AnchorDownload(
PDEVICE_OBJECT fdo,
WORD offset,
PUCHAR downloadBuffer,
ULONG downloadSize
)
/*++
Routine Description:
Uses the ANCHOR LOAD vendor specific command to download code to the EZ-USB
device. The actual code is stored as data within the driver binary in the
global 'firmware' which is an EZUSB_FIRMWARE struct included in the file
firmware.c.
Arguments:
fdo - pointer to the device object for this instance of an Ezusb Device
downloadBuffer - pointer to the firmware image
downloadSize - total size (bytes) of the firmware image to download
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus;
PURB urb = NULL;
int i;
int chunkCount;
PUCHAR ptr = downloadBuffer;
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (urb)
{
chunkCount = ((downloadSize + CHUNK_SIZE - 1) / CHUNK_SIZE);
//
// The download will be split into CHUNK_SIZE pieces and
// downloaded with multiple setup transfers. For the Rev B parts
// CHUNK_SIZE should not exceed 64 bytes, as larger transfers can
// result in data corruption when other USB devices are present.
//
for (i = 0; i < chunkCount; i++)
{
RtlZeroMemory(urb,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
urb->UrbControlVendorClassRequest.TransferBufferLength =
((i == (chunkCount - 1)) && (downloadSize % CHUNK_SIZE)) ?
(downloadSize % CHUNK_SIZE) :
CHUNK_SIZE;
urb->UrbControlVendorClassRequest.TransferBuffer = ptr;
urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
urb->UrbControlVendorClassRequest.Request = ANCHOR_LOAD_INTERNAL;
urb->UrbControlVendorClassRequest.Value = (i * CHUNK_SIZE) + offset;
urb->UrbControlVendorClassRequest.Index = 0;
ntStatus = Ezusb_CallUSBD(fdo, urb);
if (!NT_SUCCESS(ntStatus))
break;
ptr += CHUNK_SIZE;
}
}
else
{
ntStatus = STATUS_NO_MEMORY;
}
if (urb)
ExFreePool(urb);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -