Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1004 lines
32 KiB

/*++
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*/
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);
if(irp==NULL)
{
ioStatus.Status=STATUS_NO_MEMORY;
goto GetPortStatusDone;
}
//
// 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
//
GetPortStatusDone:
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.
//
if(irp==NULL)
{
ioStatus.Status=STATUS_NO_MEMORY;
goto ResetPortDone;
}
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
//
ResetPortDone:
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->IsChildDevice == TRUE)
{
ntStatus = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,IO_NO_INCREMENT);
USBPRINT_DecrementIoCount(DeviceObject);
return ntStatus;
}
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_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;
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
*/