www.pudn.com > cypressdrv.zip > IOCTLISO.C


/*++ 
 
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; 
}