windows-nt/Source/XPSP1/NT/printscan/print/drivers/kernelmode/usbprint/ioctl.c
2020-09-26 16:20:57 +08:00

1244 lines
38 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ioctl.c
Abstract:
Device driver for USB printers
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
Revision History:
5-4-96 : created
--*/
#define DRIVER
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include <usb.h>
#include <usbdrivr.h>
#include "usbdlib.h"
#include "usbprint.h"
#include "ioctl.h"
#include "usbdlib.h"
#include "ntddpar.h"
int USBPRINT_GetLptStatus(IN PDEVICE_OBJECT DeviceObject);
NTSTATUS HPUsbIOCTLVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
NTSTATUS HPUsbIOCTLVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
NTSTATUS HPUsbVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,IN PUCHAR buffer,IN ULONG length);
NTSTATUS HPUsbVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,IN PUCHAR buffer,IN ULONG length,OUT PULONG pBytesRead);
NTSTATUS USBPRINT_SoftReset(IN PDEVICE_OBJECT DeviceObject)
/*++
Routine Description:
Issues the class specific "Soft reset" command to the printer
Arguments:
DeviceObject - pointer to the device object for this instance of the printer device.
Return Value:
ntStatus of the URB
--*/
{
NTSTATUS ntStatus;
PURB urb;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
PDEVICE_EXTENSION deviceExtension;
LARGE_INTEGER timeOut;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_SoftReset\n"));
deviceExtension = DeviceObject->DeviceExtension;
urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBP_TAG);
if (urb) {
UsbBuildVendorRequest(urb, //urb
URB_FUNCTION_CLASS_INTERFACE, //request target
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), //request len
USBD_TRANSFER_DIRECTION_OUT|USBD_SHORT_TRANSFER_OK, //flags
0, //reserved bits
2, //request code
0, //wValue
deviceExtension->Interface->InterfaceNumber<<8, //wIndex
NULL, //return buffer address
NULL, //mdl
0, //return length
NULL); //link param
timeOut.QuadPart = FAILURE_TIMEOUT;
ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: urb->Hdr.Status=%d\n",((struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *)urb)->Hdr.Status));
if (NT_SUCCESS(ntStatus) &&
urb->UrbControlVendorClassRequest.TransferBufferLength > 2)
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: CallUSBD succeeded\n"));
}
else
{
USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; CallUSBD failed"));
}
ExFreePool(urb);
} /*end if URB OK*/
else
{
USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; urb allocation failed"));
ntStatus=STATUS_NO_MEMORY;
}
return ntStatus;
} /*end function Get1284_Id*/
int USBPRINT_Get1284Id(IN PDEVICE_OBJECT DeviceObject,PVOID pIoBuffer,int iLen)
/*++
Routine Description:
Requests and returns Printer 1284 Device ID
Arguments:
DeviceObject - pointer to the device object for this instance of the printer device.
pIoBuffer - pointer to IO buffer from user mode
iLen - Length of *pIoBuffer;
Return Value:
Success: Length of data written to *pIoBuffer (icluding lenght field in first two bytes of data)
Failure: -1
--*/
{
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
int iReturn = -1;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
PDEVICE_EXTENSION deviceExtension;
LARGE_INTEGER timeOut;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_Get1284\n"));
deviceExtension = DeviceObject->DeviceExtension;
urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBP_TAG);
if (urb) {
siz = iLen;
UsbBuildVendorRequest(urb, //urb
URB_FUNCTION_CLASS_INTERFACE, //request target
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), //request len
USBD_TRANSFER_DIRECTION_IN|USBD_SHORT_TRANSFER_OK, //flags
0, //reserved bits
0, //request code
0, //wValue
deviceExtension->Interface->InterfaceNumber<<8, //wIndex
pIoBuffer, //return buffer address
NULL, //mdl
iLen, //return length
NULL); //link param
timeOut.QuadPart = FAILURE_TIMEOUT;
ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: urb->Hdr.Status=%d\n",((struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *)urb)->Hdr.Status));
if (NT_SUCCESS(ntStatus) &&
urb->UrbControlVendorClassRequest.TransferBufferLength > 2)
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: CallUSBD succeeded\n"));
iReturn= *((unsigned char *)pIoBuffer);
iReturn<<=8;
iReturn+=*(((unsigned char *)pIoBuffer)+1);
if ( iReturn > 0 && iReturn < iLen )
{
*(((char *)pIoBuffer)+iReturn)='\0';
USBPRINT_KdPrint3 (("'USBPRINT.SYS: return size ==%d\n",iReturn));
}
else
{
iReturn = -1;
}
}
else
{
USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; CallUSBD failed\n"));
iReturn=-1;
}
ExFreePool(urb);
} /*end if URB OK*/
else
{
USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; urb allocation failed"));
iReturn=-1;
}
return iReturn;
} /*end function Get1284_Id*/
int USBPRINT_GetLptStatus(IN PDEVICE_OBJECT DeviceObject)
/*++
Routine Description:
Requests and returns Printer status byte from USB printer
Arguments:
DeviceObject - pointer to the device object for this instance of the printer device.
Return Value:
Success: status value 0-255
Failure: -1
--*/
{
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
unsigned char RETURN_BUFF[1];
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
PDEVICE_EXTENSION deviceExtension;
LARGE_INTEGER timeOut;
RETURN_BUFF[0] = 0;
timeOut.QuadPart = FAILURE_TIMEOUT;
deviceExtension = DeviceObject->DeviceExtension;
urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBP_TAG);
if (urb) {
siz = sizeof(RETURN_BUFF);
UsbBuildVendorRequest(urb,
URB_FUNCTION_CLASS_INTERFACE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_IN|USBD_SHORT_TRANSFER_OK,
0, //reserved bits
1, //request code
0,
deviceExtension->Interface->InterfaceNumber,
RETURN_BUFF, //return buffer address
NULL, //mdl
sizeof(RETURN_BUFF), //return length
NULL); //link param
ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: urb->Hdr.Status=%d\n",((struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *)urb)->Hdr.Status));
ExFreePool(urb);
if (NT_SUCCESS(ntStatus))
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: CallUSBD succeeded\n"));
return (int) RETURN_BUFF[0];
}
else
{
USBPRINT_KdPrint1(("'USBPRINT.SYS: Error; CallUSBD failed"));
return -1;
}
} /*end if URB OK*/
else {
return -1;
}
} /*end function GetLptStatus*/
PUSB_CONFIGURATION_DESCRIPTOR
USBPRINT_GetConfigDescriptor(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this printer
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
LARGE_INTEGER timeOut;
timeOut.QuadPart = FAILURE_TIMEOUT;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_GetConfigDescriptor\n"));
deviceExtension = DeviceObject->DeviceExtension;
urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBP_TAG);
if (urb) {
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR)+256;
get_config_descriptor_retry2:
configurationDescriptor = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
if (configurationDescriptor) {
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
siz,
NULL);
ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Configuration Descriptor = %x, len %x\n",
configurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength));
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS(ntStatus) &&
(urb->UrbControlDescriptorRequest.TransferBufferLength >=
sizeof(USB_CONFIGURATION_DESCRIPTOR)) &&
(configurationDescriptor->wTotalLength >=
sizeof(USB_CONFIGURATION_DESCRIPTOR)))
{
//
// The Get Config Descriptor request did not return an error
// AND at least enough data was transferred to fill a Config
// Descriptor AND the Config Descriptor wLength is at least the
// size of a Config Descriptor
//
if (configurationDescriptor->wTotalLength > siz)
{
//
// The request buffer is not big enough to hold the
// entire set of descriptors. Free the current buffer
// and retry with a buffer which should be big enough.
//
siz = configurationDescriptor->wTotalLength;
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
goto get_config_descriptor_retry2;
}
else if (configurationDescriptor->wTotalLength >
urb->UrbControlDescriptorRequest.TransferBufferLength)
{
//
// The request buffer is greater than or equal to the
// Config Descriptor wLength, but less data was transferred
// than wLength. Return NULL to indicate a device error.
//
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
}
//
// else everything is OK with the Config Descriptor, return it.
//
}
else
{
//
// The Get Config Descriptor request returned an error OR
// not enough data was transferred to fill a Config Descriptor
// OR the Config Descriptor wLength is less than the size of
// a Config Descriptor. Return NULL to indicate a device error.
//
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
}
ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
USBPRINT_KdPrint2 (("'USBPRINT.SYS: exit USBPRINT_GetConfigDescriptor\n"));
return configurationDescriptor;
}
typedef enum _CLOCKMASTER_OP {
TakeControl,
FreeControl,
ChangeClock,
GetClock
} CLOCKMASTER_OP;
NTSTATUS
USBPRINT_ClockMaster(
IN PDEVICE_OBJECT DeviceObject,
IN CLOCKMASTER_OP Op
)
/*++
Routine Description:
modifies the USB SOF clock
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus;
PURB urb;
USHORT siz;
USHORT func;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: ClockMaster\n"));
switch(Op) {
case TakeControl:
func = URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL;
siz = sizeof(struct _URB_FRAME_LENGTH_CONTROL);
break;
case FreeControl:
func = URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL;
siz = sizeof(struct _URB_FRAME_LENGTH_CONTROL);
break;
case ChangeClock:
siz = sizeof(struct _URB_SET_FRAME_LENGTH);
func = URB_FUNCTION_SET_FRAME_LENGTH;
break;
case GetClock:
siz = sizeof(struct _URB_GET_FRAME_LENGTH);
func = URB_FUNCTION_GET_FRAME_LENGTH;
break;
}
urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST), USBP_TAG);
if (urb) {
switch(Op) {
case TakeControl:
case FreeControl:
case GetClock:
break;
case ChangeClock:
urb->UrbSetFrameLength.FrameLengthDelta = 1;
break;
}
urb->UrbHeader.Length = siz;
urb->UrbHeader.Function = func;
//
// Do we need a timeout here?
//
ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, NULL);
switch(Op) {
case TakeControl:
USBPRINT_KdPrint3 (("'USBPRINT.SYS: TakeControl\n"));
break;
case FreeControl:
USBPRINT_KdPrint3 (("'USBPRINT.SYS: FreeControl\n"));
break;
case GetClock:
USBPRINT_KdPrint3 (("'USBPRINT.SYS: GetClock %d\n", urb->UrbGetFrameLength.FrameLength));
break;
case ChangeClock:
USBPRINT_KdPrint3 (("'USBPRINT.SYS: ChangeClock\n"));
break;
}
USBPRINT_KdPrint3 (("'USBPRINT.SYS: clock op status = %x urb = %x\n", ntStatus,
urb->UrbHeader.Status));
ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
NTSTATUS
USBPRINT_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;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_GetPortStatus\n"));
deviceExtension = DeviceObject->DeviceExtension;
*PortStatus = 0;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_GET_PORT_STATUS,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, /* INTERNAL */
&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);
ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = PortStatus;
USBPRINT_KdPrint3 (("'USBPRINT.SYS: calling USBD port status api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: return from IoCallDriver USBD (in getportstatus)%x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
if (!NT_SUCCESS(ntStatus))
{
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Error! IoCallDriver failed\n"));
}
else
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success! IoCallDriver did not fail\n"));
}
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Port status = %x\n", *PortStatus));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
USBPRINT_KdPrint3 (("'USBPRINT.SYS: USBPRINT_GetPortStatus (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USBPRINT_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;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: enter USBPRINT_ResetPort\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 */
&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);
ASSERT(nextStack != NULL);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: calling USBD enable port api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: return from IoCallDriver USBD (in reset parent port)%x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
USBPRINT_KdPrint3 (("'USBPRINT.SYS: USBPRINT_ResetPort (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USBPRINT_ProcessIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this printer
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
PUCHAR pch;
USBPRINT_KdPrint2 (("'USBPRINT.SYS: IRP_MJ_DEVICE_CONTROL\n"));
USBPRINT_IncrementIoCount(DeviceObject);
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
deviceExtension = DeviceObject->DeviceExtension;
if (deviceExtension->AcceptingRequests == FALSE) {
ntStatus = STATUS_DEVICE_DATA_ERROR;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
USBPRINT_DecrementIoCount(DeviceObject);
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Information = 0;
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
//
// Handle Ioctls from User mode
//
switch (ioControlCode) {
case IOCTL_USBPRINT_SET_PIPE_PARAMETER:
ntStatus = STATUS_SUCCESS;
break;
case IOCTL_PAR_QUERY_DEVICE_ID:
{
int iReturn;
char * pTempBuffer;
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Enter in PAR_QUERY_DEVICE_ID\n"));
pTempBuffer=ExAllocatePool(NonPagedPool,outputBufferLength+3); //3 == 2 bytes for the size at the beginning, plus 1 for the null at the end
if(pTempBuffer==NULL)
{
Irp->IoStatus.Information=0;
ntStatus=STATUS_NO_MEMORY;
}
else
{
iReturn=USBPRINT_Get1284Id(DeviceObject,pTempBuffer,outputBufferLength+2);
if(iReturn>0)
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success in PAR_QUERY_DEVICE_ID\n"));
Irp->IoStatus.Information=iReturn-1;
*(pTempBuffer+iReturn)='\0';
RtlCopyBytes(ioBuffer,pTempBuffer+2,iReturn-1); //+2 to step past the size bytes at the beginning, -1 is +1 for null -2 for size bytes
ntStatus=STATUS_SUCCESS;
} /*if success*/
else
{
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Failure in PAR_QUERY_DEVICE_ID\n"));
Irp->IoStatus.Information=0;
ntStatus=STATUS_DEVICE_DATA_ERROR;
} /*else failure*/
ExFreePool(pTempBuffer);
} /*end else malloc OK*/
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Exit in PAR_QUERY_DEVICE_ID\n"));
}
break;
case IOCTL_USBPRINT_SOFT_RESET:
ntStatus=USBPRINT_SoftReset(DeviceObject);
Irp->IoStatus.Information=0;
break;
case IOCTL_USBPRINT_GET_1284_ID:
{
int iReturn;
pch = (PUCHAR) ioBuffer;
if(outputBufferLength<sizeof(UCHAR))
{
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Buffer to small in GET_1284_ID\n"));
Irp->IoStatus.Information=0;
ntStatus=STATUS_BUFFER_TOO_SMALL;
}
else
{
iReturn=USBPRINT_Get1284Id(DeviceObject,ioBuffer,outputBufferLength);
if(iReturn>=0)
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success in GET_1284_ID\n"));
*pch=(UCHAR)iReturn;
Irp->IoStatus.Information=iReturn;
ntStatus=STATUS_SUCCESS;
} /*if success*/
else
{
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Failure in GET_1284_ID\n"));
Irp->IoStatus.Information=0;
ntStatus=STATUS_DEVICE_DATA_ERROR;
} /*else failure*/
} /*end else buffer len OK*/
}
break; //end case GET_1284_ID
case IOCTL_USBPRINT_GET_LPT_STATUS:
{
int iReturn;
pch = (PUCHAR) ioBuffer;
if(outputBufferLength<sizeof(UCHAR))
{
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Buffer to small in GET_LPT_STATUS\n"));
Irp->IoStatus.Information=0;
ntStatus=STATUS_BUFFER_TOO_SMALL;
}
else
{
iReturn= USBPRINT_GetLptStatus(DeviceObject);
if(iReturn>=0)
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Success in GET_LPT_STATUS\n"));
*pch=(UCHAR)iReturn;
Irp->IoStatus.Information=1;
ntStatus=STATUS_SUCCESS;
} /*if success*/
else
{
USBPRINT_KdPrint1 (("'USBPRINT.SYS: Failure in GET_LPT_STATUS\n"));
Irp->IoStatus.Information=0;
ntStatus=STATUS_DEVICE_DATA_ERROR;
} /*else failure*/
} /*end else buffer OK*/
}
break;
case IOCTL_USBPRINT_VENDOR_SET_COMMAND:
ntStatus=HPUsbIOCTLVendorSetCommand(DeviceObject,Irp);
break;
case IOCTL_USBPRINT_VENDOR_GET_COMMAND:
ntStatus=HPUsbIOCTLVendorGetCommand(DeviceObject,Irp);
break;
case IOCTL_USBPRINT_RESET_DEVICE:
{
ULONG portStatus;
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Reset Device Test\n"));
TRAP(); // test this
//
// Check the port state, if it is disabled we will need
// to re-enable it
//
ntStatus = USBPRINT_GetPortStatus(DeviceObject, &portStatus);
if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&portStatus & USBD_PORT_CONNECTED)
{
//
// port is disabled, attempt reset
//
//USBPRINT_EnableParentPort(DeviceObject);
USBPRINT_KdPrint2 (("'USBPRINT.SYS: Resetting port\n"));
USBPRINT_ResetParentPort(DeviceObject);
}
}
break;
case IOCTL_USBPRINT_CLOCK_MASTER_TEST:
{
USBPRINT_KdPrint3 (("'USBPRINT.SYS: Clock Master Test\n"));
TRAP(); // test this
// get the clock
USBPRINT_ClockMaster(DeviceObject, GetClock);
// take control to change clock
//ntStatus = USBPRINT_ClockMaster(DeviceObject, TakeControl);
//if (NT_SUCCESS(ntStatus)) {
ntStatus = USBPRINT_ClockMaster(DeviceObject, ChangeClock);
//}
USBPRINT_ClockMaster(DeviceObject, FreeControl);
}
break;
default:
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
USBPRINT_DecrementIoCount(DeviceObject);
return ntStatus;
}
/****************STUFF FROM HP:*************************/
/*-------------------------------------------------------------------------------
* HPUsbIOCTLVendorSetCommand() - Send a vendor defined SET command
*-------------------------------------------------------------------------------
*/
NTSTATUS HPUsbIOCTLVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
// Local Variables
NTSTATUS ntStatus;
PIO_STACK_LOCATION currentIrpStack;
// Set up a local pointer to the Irp stack
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
// Send the SET command
ntStatus = HPUsbVendorSetCommand(DeviceObject,
(PUCHAR) Irp->AssociatedIrp.SystemBuffer,
currentIrpStack->Parameters.DeviceIoControl.InputBufferLength);
// Set the Irp information values
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
// Return
return ntStatus;
}
/*-------------------------------------------------------------------------------
* HPUsbIOCTLVendorGetCommand() - Send a vendor defined GET command
*-------------------------------------------------------------------------------
*/
NTSTATUS HPUsbIOCTLVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
// Local Variables
NTSTATUS ntStatus;
PIO_STACK_LOCATION currentIrpStack;
ULONG bytesRead = 0;
// Set up a local pointer to the Irp stack
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
// Get the port status
ntStatus = HPUsbVendorGetCommand(DeviceObject,
(PUCHAR) Irp->AssociatedIrp.SystemBuffer,
currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
&bytesRead);
// Set the Irp information values
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = bytesRead;
// Return
return ntStatus;
}
/*-------------------------------------------------------------------------------
* HPUsbVendorSetCommand() - Send a vendor specified SET command
*
* Inputs:
* buffer[0] - Vendor Request Code (bRequest function code)
* buffer[1] - Vendor Request Value Most Significant Byte (wValue MSB)
* buffer[2] - Vendor Request Value Least Significant Byte (wValue LSB)
* buffer[3...] - Any data to be sent as part of the command
*
*-------------------------------------------------------------------------------
*/
NTSTATUS HPUsbVendorSetCommand(IN PDEVICE_OBJECT DeviceObject,
IN PUCHAR buffer,
IN ULONG length)
{
// Local variables
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PUSBD_INTERFACE_INFORMATION interface;
PURB urb;
ULONG size;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
if ( buffer == NULL || length < 3 )
return STATUS_INVALID_PARAMETER;
// Set up a local pointer to the device extension
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
// Set up a local pointer to the interface
interface = deviceExtension->Interface;
// Determine the size of the URB
size = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
// Allocate memory for the USB Request Block (URB)
// urb = (PURB)
// ExAllocatePoolWithTag(NonPagedPool,size,HPUSB_ALLOC_TAG);
urb = ExAllocatePoolWithTag(NonPagedPool,size, USBP_TAG);
// Check for an error
if (urb == NULL)
return STATUS_NO_MEMORY;
// Store the vendor request code
bRequest = buffer[0];
// Store the vendor request parameter
wValue = (buffer[1] << 8) | buffer[2];
// Create the wIndex value (Interface:Alternate)
wIndex = (interface->InterfaceNumber << 8) |
(interface->AlternateSetting);
// Use a macro in the standard USB header files to build the URB
UsbBuildVendorRequest(urb,
URB_FUNCTION_VENDOR_INTERFACE,
(USHORT) size,
0,
0,
bRequest,
wValue,
wIndex,
buffer,
NULL,
length,
NULL);
//
// Timeout cancellation should happen from user mode
//
ntStatus = USBPRINT_CallUSBD(DeviceObject,urb, NULL);
// Free allocated memory
ExFreePool(urb);
// Return Success
return ntStatus;
}
/*-------------------------------------------------------------------------------
* HPUsbVendorGetCommand() - Send a vendor specified GET command
*
* Inputs:
* buffer[0] - Vendor Request Code (bRequest function code)
* buffer[1] - Vendor Request Value Most Significant Byte (wValue MSB)
* buffer[2] - Vendor Request Value Least Significant Byte (wValue LSB)
* Outputs:
* buffer[ ] - Response data
*
*-------------------------------------------------------------------------------
*/
NTSTATUS HPUsbVendorGetCommand(IN PDEVICE_OBJECT DeviceObject,
IN PUCHAR buffer,
IN ULONG length,
OUT PULONG pBytesRead)
{
// Local variables
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PUSBD_INTERFACE_INFORMATION interface;
PURB urb;
ULONG size;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
if ( buffer == NULL || length < 3 )
return STATUS_INVALID_PARAMETER;
// Initialize the pBytesRead return value
*pBytesRead = 0;
// Set up a local pointer to the device extension
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
// Set up a local pointer to the interface
interface = deviceExtension->Interface;
// Determine the size of the URB
size = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
// Allocate memory for the USB Request Block (URB)
// urb = (PURB)
// ExAllocatePoolWithTag(NonPagedPool,size,HPUSB_ALLOC_TAG);
urb = ExAllocatePoolWithTag(NonPagedPool,size, USBP_TAG);
// Check for an error
if (urb == NULL)
return STATUS_NO_MEMORY;
// Store the vendor request code
bRequest = buffer[0];
// Store the vendor request parameter
wValue = (buffer[1] << 8) | buffer[2];
// Create the wIndex value (Interface:Alternate)
wIndex = (interface->InterfaceNumber << 8) |
(interface->AlternateSetting);
// Use a macro in the standard USB header files to build the URB
UsbBuildVendorRequest(urb,
URB_FUNCTION_VENDOR_INTERFACE,
(USHORT) size,
USBD_TRANSFER_DIRECTION_IN |
USBD_SHORT_TRANSFER_OK,
0,
bRequest,
wValue,
wIndex,
buffer,
NULL,
length,
NULL);
//
// Timeout cancellation should happen from user mode
//
ntStatus = USBPRINT_CallUSBD(DeviceObject,urb, NULL);
// Retrieve the number of bytes read
if (NT_SUCCESS(ntStatus))
*pBytesRead = urb->UrbControlVendorClassRequest.TransferBufferLength;
// Free allocated memory
ExFreePool(urb);
// Return Success
return ntStatus;
}
/*
// -----------------------------------------------------------
// Kernel Mode Usage
// -----------------------------------------------------------
// Create the channel change request
Buffer[0] = HP_VENDOR_COMMAND_DO_SOMETHING;
Buffer[1] = HP_PARAMETER_UPPER_BYTE;
Buffer[2] = HP_PARAMETER_LOWER_BYTE;
// Send the request
status = CallDeviceIoControl(
m_pTargetDeviceObject, // the device to send the new irp to
IOCTL_HPUSB_VENDOR_GET_COMMAND, // the ioctl to send to the driver ,
Buffer, // the input buffer for the ioctl
3, // the length of the input buffer
Buffer, // the output buffer for the ioctl
1, // the length of the output buffer
FALSE, // create the irp with IRP_MJ_DEVICE_CONTROL
NULL); // use the provided completion routine
*/