سلام
من باید یک درایور برای usb طراحی کنم و می خوام بدونم فایلهای .sys را چطوری می سازند(کامپایل می کنند)
من باید یک درایور برای usb طراحی کنم و می خوام بدونم فایلهای .sys را چطوری می سازند(کامپایل می کنند)
/*++
Module Name:
ioctliso.c
--*/
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "usb100.h"
#include "Iso82930.h"
#include "IsoUsb.h"
#include "usbdlib.h"
NTSTATUS
IsoUsb_ProcessIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch table handler for IRP_MJ_DEVICE_CONTROL;
Handle DeviceIoControl() calls from User mode
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus;
ULONG length;
PUCHAR pch;
PURB urb;
USHORT temp;
USHORT temp2;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
IsoUsb_IncrementIoCount(DeviceObject);
deviceExtension = DeviceObject->DeviceExtension;
if ( !IsoUsb_CanAcceptIoRequests( DeviceObject ) )
{
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
IsoUsb_DecrementIoCount(DeviceObject);
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case 4: //Implemented for Compatability with Cypress Thermometer Driver.
pch = (PUCHAR) ioBuffer;
switch(pch[0])
{
case 0x0E: // Set LED Brightness
temp = pch[1]; // Store Brightness
length = VendorCommand(DeviceObject,
0x03, // WriteRAM
0x2C, // gbLEDBrightness
(USHORT)pch[1],
ioBuffer);
length = VendorCommand(DeviceObject,
0x03, // WriteRAM
0x2B, // gbLEDBrightnessUpdate
0x01, // TRUE
ioBuffer);
pch[0] = 0; //Status
pch[1] = temp; //Brightness
Irp->IoStatus.Information = 2;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 0x0B: // Read Thermometer
length = VendorCommand(DeviceObject,
0x02, // ReadRAM
0x33, // gbThermTempRead
0,
ioBuffer);
temp = pch[1]; // Store Temperature
length = VendorCommand(DeviceObject,
0x02, // ReadRAM
0x34, // gbThermTempRead2
0,
ioBuffer);
temp2 = pch[1]; // Store Sign
length = VendorCommand(DeviceObject,
0x02, // ReadRAM
0x7A, // gbButtonPushed
0,
ioBuffer);
pch[3] = pch[1]; //Move Button
pch[0] = 0; //Status
pch[1] = temp; //Temperature
pch[2] = temp2; //Sign
Irp->IoStatus.Information = 4;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 0x14: // Read Port
length = VendorCommand(DeviceObject,
0x04, // ReadPort
pch[1], // Address
0,
ioBuffer);
pch[0] = 0; //Status
// pch[1] = pch[2]; //Value // error: data cames back in [1]
Irp->IoStatus.Information = 2;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 0x15: // Write Port
length = VendorCommand(DeviceObject,
0x05, // WritePort
pch[1], // Address
pch[2], // Value
ioBuffer);
Irp->IoStatus.Information = 1;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 0x16: // Read RAM
length = VendorCommand(DeviceObject,
0x02, // ReadRAM
pch[1], // Address
0,
ioBuffer);
pch[0] = 0; //Status
// pch[1] = pch[2]; //Value // error: data cames back in [1]
Irp->IoStatus.Information = 2;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 0x17: // Write RAM
length = VendorCommand(DeviceObject,
0x03, // WriteRAM
pch[1], // Address
pch[2], // Value
ioBuffer);
Irp->IoStatus.Information = 1;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 0x18: // Read ROM
length = VendorCommand(DeviceObject,
0x01, // ReadROM
pch[1], // Address
0,
ioBuffer);
pch[0] = 0; //Status
// pch[1] = pch[2]; //Value // error: data cames back in [1]
Irp->IoStatus.Information = 2;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
default :
break;
ntStatus = STATUS_SUCCESS;
}
break;
case 8: //Reads a Vendor Command
pch = (PUCHAR) ioBuffer;
length = VendorCommand(DeviceObject, (UCHAR)pch[0], (USHORT)pch[1], (USHORT)pch[2], ioBuffer);
Irp->IoStatus.Information = length;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 12: // GetDescriptor(s)
pch = (PUCHAR) ioBuffer;
length = GetDescriptor(DeviceObject, (UCHAR)pch[0], (UCHAR)pch[1], (USHORT)pch[2], ioBuffer);
Irp->IoStatus.Information = length;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 16: // Get Status
pch = (PUCHAR) ioBuffer;
length = GetStatus(DeviceObject, (USHORT)pch[0], (USHORT)pch[1], ioBuffer);
Irp->IoStatus.Information = length;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 20: //IOCTL_ISOUSB_RESET_DEVICE:
ntStatus = IsoUsb_ResetDevice(DeviceObject);
break;
case 24: //Reconfigure Device (Enumerate)
ntStatus = IsoUsb_ConfigureDevice(DeviceObject);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
case 28: //UnConfigure Device
ntStatus = IsoUsb_StopDevice(DeviceObject);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = STATUS_SUCCESS;
break;
default:
ntStatus = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
IsoUsb_DecrementIoCount(DeviceObject);
return ntStatus;
}
ULONG
VendorCommand(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Request,
IN USHORT Value,
IN USHORT Index,
PVOID ioBuffer
)
{
NTSTATUS ntStatus;
PURB urb;
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (urb)
{
UsbBuildVendorRequest(urb,
URB_FUNCTION_VENDOR_ENDPOINT,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
(USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
0, // Reserved Bits
Request, // Request
Value, // Value
Index, // Index
ioBuffer, // Transfer Buffer
NULL, // TransferBufferMDL OPTIONAL
8, // Transfer Buffer Lenght
NULL); // Link OPTIONAL
ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);
ExFreePool(urb);
return(urb->UrbControlVendorClassRequest.TransferBufferLength);
}
else return(0);
}
ULONG
GetDescriptor(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR DescriptorType,
IN UCHAR Index,
IN USHORT LanguageId,
PVOID ioBuffer
)
{
NTSTATUS ntStatus;
PURB urb;
PUCHAR pch;
ULONG length;
pch = (PUCHAR) ioBuffer;
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb)
{
// Get Descriptor Length
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
DescriptorType,
Index,
LanguageId,
ioBuffer,
NULL,
0x01, // Transmit Lenght. Read First Byte.
NULL); // Link
ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);
ExFreePool(urb);
// Check Length of Incomming Data.
if (urb->UrbControlDescriptorRequest.TransferBufferLength == 0) return(0);
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
length = pch[0];
if (DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE) length = 1024;
if (urb)
{
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
DescriptorType,
Index,
LanguageId,
ioBuffer,
NULL,
length, // Length of Descriptor String
NULL); // Link
ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);
ExFreePool(urb);
return(urb->UrbControlDescriptorRequest.TransferBufferLength);
}
else return(0);
}
else return(0);
}
ULONG
GetStatus(
IN PDEVICE_OBJECT DeviceObject,
IN USHORT Op,
IN USHORT Index,
PVOID ioBuffer
)
{
NTSTATUS ntStatus;
PURB urb;
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST));
if (urb)
{
UsbBuildGetStatusRequest(urb,
Op, // Operation
Index, // Index
ioBuffer, // Transfer Buffer
NULL, // TransferBufferMDL OPTIONAL
NULL); // Link OPTIONAL
ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);
ExFreePool(urb);
return(urb->UrbControlGetStatusRequest.TransferBufferLength);
}
else return(0);
}
NTSTATUS
IsoUsb_ResetDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Checks port status; if OK, return success and do no more;
If bad, attempt reset
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
ULONG portStatus;
ISOUSB_KdPrint(DBGLVL_MEDIUM,("Enter IsoUsb_ResetDevice()\n"));
//
// Check the port state, if it is disabled we will need
// to re-enable it
//
ntStatus = IsoUsb_GetPortStatus(DeviceObject, &portStatus);
if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&
portStatus & USBD_PORT_CONNECTED) {
//
// port is disabled, attempt reset
//
ISOUSB_KdPrint( DBGLVL_DEFAULT,("IsoUsb_ResetDevice() will reset\n"));
ntStatus = IsoUsb_ResetParentPort(DeviceObject);
}
return ntStatus;
}
NTSTATUS
IsoUsb_GetPortStatus(
IN PDEVICE_OBJECT DeviceObject,
IN PULONG PortStatus
)
/*++
Routine Description:
returns the port status for our device
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
ISOUSB_KdPrint( DBGLVL_DEFAULT,("enter IsoUsb_GetPortStatus\n"));
deviceExtension = DeviceObject->DeviceExtension;
*PortStatus = 0;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
// IoBuildDeviceIoControlRequest allocates and sets up an IRP for a device control request
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_GET_PORT_STATUS,
deviceExtension->TopOfStackDeviceObject, //next-lower driver's device object, representing the target device.
NULL, // no input or output buffers
0,
NULL,
0,
TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
&event, // event to be signalled on completion ( we wait for it below )
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
// IoGetNextIrpStackLocation gives a higher level driver access to the next-lower
// driver's I/O stack location in an IRP so the caller can set it up for the lower driver.
nextStack = IoGetNextIrpStackLocation(irp);
ISOUSB_ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = PortStatus;
ISOUSB_KdPrint( DBGLVL_DEFAULT,("IsoUsb_GetPortStatus() calling USBD port status api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
ISOUSB_KdPrint( DBGLVL_DEFAULT,("IsoUsb_GetPortStatus() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
ISOUSB_KdPrint( DBGLVL_DEFAULT,("Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
ISOUSB_KdPrint( DBGLVL_DEFAULT,("IsoUsb_GetPortStatus() Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
ISOUSB_KdPrint( DBGLVL_DEFAULT,("IsoUsb_GetPortStatus() Port status = %x\n", *PortStatus));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
ISOUSB_KdPrint( DBGLVL_DEFAULT,("Exit IsoUsb_GetPortStatus (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_ResetParentPort(
IN IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Reset the our parent port
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
ISOUSB_KdPrint( DBGLVL_HIGH,("enter IsoUsb_ResetParentPort\n"));
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_RESET_PORT,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
&event,
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
ISOUSB_ASSERT(nextStack != NULL);
ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_ResetParentPort() calling USBD enable port api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_ResetParentPort() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_ResetParentPort() Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_ResetParentPort() Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
ISOUSB_KdPrint( DBGLVL_HIGH,("Exit IsoUsb_ResetPort (%x)\n", ntStatus));
return ntStatus;
}
دیدگاه