/*++
Module Name:
ReadWriteRequest.cpp
Abstract:
This module contains the implementation of the HID Read/Write request
completion callback object.
--*/
#include "internal.h"
#include "Defines.h"
#include "SensorDDI.h"
#include "ReadWriteRequest.h"
#include "ReadWriteRequest.tmh"
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::CReadWriteRequest
//
// Object constructor function
//
/////////////////////////////////////////////////////////////////////////
CReadWriteRequest::CReadWriteRequest() :
m_pHidWdfIoRequest(NULL),
m_pHidWdfDevice(NULL),
m_pHidWdfDriver(NULL),
m_pHidWdfFile(NULL),
m_pHidWdfIoTarget(NULL),
m_pParentCallback(NULL),
m_bytesRead(0),
m_fResend(FALSE)
{
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::~CReadWriteRequest
//
// Object destructor function
//
/////////////////////////////////////////////////////////////////////////
CReadWriteRequest::~CReadWriteRequest()
{
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::InitializeRequest
//
//
//
/////////////////////////////////////////////////////////////////////////
HRESULT CReadWriteRequest::InitializeRequest(IWDFDevice* pWdfDevice,
CAsyncCallback* pCallback)
{
HRESULT hr = (NULL != pWdfDevice) ? S_OK : E_UNEXPECTED;
// Store the callback
m_pParentCallback = pCallback;
if(SUCCEEDED(hr))
{
m_fResend = TRUE;
// Store the IWDFDevice pointer
m_pHidWdfDevice = pWdfDevice;
// Step 1: Try CreateWdfFile here (target to next driver in the driver stack)
hr = m_pHidWdfDevice->CreateWdfFile( NULL, &m_pHidWdfFile );
if(SUCCEEDED(hr) && (NULL != m_pHidWdfFile))
{
// Step 2: Get the parent driver object
m_pHidWdfDevice->GetDriver( &m_pHidWdfDriver );
// Step 3: Get the IO target i.e. default Target
if (NULL != m_pHidWdfDriver)
{
m_pHidWdfDevice->GetDefaultIoTarget( &m_pHidWdfIoTarget );
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::UninitializeRequest
//
//
//
/////////////////////////////////////////////////////////////////////////
HRESULT CReadWriteRequest::UninitializeRequest()
{
m_bytesRead = 0;
ZeroMemory(m_buffer, READ_BUFFER_SIZE);
if (NULL != m_pHidWdfFile)
{
m_pHidWdfFile->Close();
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::OnCompletion
//
// This method is called by Framework when read request is completed
// The result is saved in the m_buffer
//
/////////////////////////////////////////////////////////////////////////
void CReadWriteRequest::OnCompletion(
__in IWDFIoRequest* pRequest,
__in IWDFIoTarget* pIoTarget,
__in IWDFRequestCompletionParams* CompletionParams,
__in PVOID Context
)
{
UNREFERENCED_PARAMETER(pRequest);
UNREFERENCED_PARAMETER(pIoTarget);
UNREFERENCED_PARAMETER(Context);
HRESULT hr = CompletionParams->GetCompletionStatus();
WDF_REQUEST_TYPE reqType = CompletionParams->GetCompletedRequestType();
//Delete the previous request object
m_pHidWdfIoRequest->DeleteWdfObject();
m_pHidWdfIoRequest = NULL;
//Process the read buffer
if ( SUCCEEDED( hr ) && (WdfRequestRead == reqType) )
{
m_bytesRead = (ULONG) CompletionParams->GetInformation();
// Call back object process the buffer first
if ( m_pParentCallback != NULL )
{
//
// retrieve the context form this request if any
//
//void *context = NULL;
//pRequest->RetrieveContext(&context);
m_pParentCallback->OnAsyncReadCallback(m_buffer, m_bytesRead, Context);
}
// Queue up another pending Read request
if ( TRUE == m_fResend )
{
CreateAndSendReadRequest();
}
}
else if( SUCCEEDED( hr ) && (WdfRequestWrite == reqType) )
{
Trace(TRACE_LEVEL_INFORMATION, "WdfRequestWrite");
}
return;
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::CreateAndSendReadRequest
//
// This helper method creates and sends the read request down the stack
//
// Remarks:
// In this routine we:
// 1. Create a request and format it for read
// 2. Asynchronously send the request without any timeout
//
// In case of failure this routine deletes the request*/
//
/////////////////////////////////////////////////////////////////////////
HRESULT CReadWriteRequest::CreateAndSendReadRequest(void *context)
{
HRESULT hr = S_OK;
CComPtr<IWDFMemory> pOutputMemory = NULL;
CComPtr<IRequestCallbackRequestCompletion> pICallback = NULL;
//Reset internal buffer
m_bytesRead = 0;
ZeroMemory(m_buffer, READ_BUFFER_SIZE);
//Creates a new request
hr = m_pHidWdfDevice->CreateRequest(NULL, m_pHidWdfDevice, &m_pHidWdfIoRequest);
//Get callback interface
if ( SUCCEEDED( hr ) )
{
hr = this->QueryInterface( __uuidof(IRequestCallbackRequestCompletion) , (PVOID*)&pICallback );
//Set completion callback
if ( SUCCEEDED( hr ) )
{
m_pHidWdfIoRequest->SetCompletionCallback(pICallback, context);
}
// set the context for the request
//m_pHidWdfIoRequest->AssignContext(NULL, context);
//Create output memory
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfDriver->CreatePreallocatedWdfMemory( (BYTE*)m_buffer,
READ_BUFFER_SIZE,
NULL, // no object event callback
m_pHidWdfIoRequest, // request object as parent
&pOutputMemory);
}
//Format request
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfIoTarget->FormatRequestForRead( m_pHidWdfIoRequest,
m_pHidWdfFile,
pOutputMemory,
NULL,
NULL );
}
//Send down the request
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfIoRequest->Send( m_pHidWdfIoTarget,
0, //No flag
0 //No timeout
);
}
if( FAILED( hr ) )
{
m_pHidWdfIoRequest->DeleteWdfObject();
m_pHidWdfIoRequest = NULL;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::CreateAndSendWriteRequest
//
// This helper method creates and sends the write request down the stack
//
// Remarks:
//
// In this routine we:
// 1. Create a request and format it for write
// 2. Asynchronously send the request without any timeout
//
// In case of failure this routine deletes the request*/
//
/////////////////////////////////////////////////////////////////////////
HRESULT CReadWriteRequest::CreateAndSendWriteRequest(
BYTE* buffer,
ULONG bufferSize,
void *context
)
{
HRESULT hr = S_OK;
CComPtr<IWDFMemory> pInputMemory = NULL;
CComPtr<IRequestCallbackRequestCompletion> pICallback = NULL;
//Create a new request
hr = m_pHidWdfDevice->CreateRequest(NULL, m_pHidWdfDevice, &m_pHidWdfIoRequest);
if ( SUCCEEDED( hr ) )
{
hr = this->QueryInterface( __uuidof(IRequestCallbackRequestCompletion) , (PVOID*)&pICallback );
//Set completion callback
if ( SUCCEEDED( hr ) )
{
m_pHidWdfIoRequest->SetCompletionCallback(pICallback, context);
}
// set the context for the request
//m_pHidWdfIoRequest->AssignContext(NULL, context);
//Create input memory
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfDriver->CreatePreallocatedWdfMemory(buffer,
bufferSize,
NULL, // no object event callback
m_pHidWdfIoRequest, // request object as parent
&pInputMemory);
}
//Format request
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfIoTarget->FormatRequestForWrite( m_pHidWdfIoRequest,
m_pHidWdfFile,
pInputMemory,
NULL,
NULL );
}
//
//Send down the request
//
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfIoRequest->Send(
m_pHidWdfIoTarget,
WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
0 //No timeout
);
}
if( FAILED( hr ) )
{
m_pHidWdfIoRequest->DeleteWdfObject();
m_pHidWdfIoRequest = NULL;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::CreateAndSendIOCTLRequest
//
// This helper method creates and sends the IOCTL request down the stack
//
// Remarks:
//
// In this routine we:
// 1. Create a request and format it for IOCTL
// 2. Asynchronously send the request without any timeout
//
// In case of failure this routine deletes the request*/
//
/////////////////////////////////////////////////////////////////////////
HRESULT CReadWriteRequest::CreateAndSendIOCTLRequest(
ULONG ulCode,
BYTE* buffer,
ULONG bufferSize,
void *context
)
{
HRESULT hr = S_OK;
CComPtr<IWDFMemory> pInputMemory = NULL;
CComPtr<IRequestCallbackRequestCompletion> pICallback = NULL;
//Create a new request
hr = m_pHidWdfDevice->CreateRequest(NULL, m_pHidWdfDevice, &m_pHidWdfIoRequest);
if ( SUCCEEDED( hr ) )
{
hr = this->QueryInterface( __uuidof(IRequestCallbackRequestCompletion) , (PVOID*)&pICallback );
//Set completion callback
if ( SUCCEEDED( hr ) )
{
m_pHidWdfIoRequest->SetCompletionCallback(pICallback, context);
}
// set the context for the request
//m_pHidWdfIoRequest->AssignContext(NULL, context);
//Create input memory
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfDriver->CreatePreallocatedWdfMemory(buffer,
bufferSize,
NULL, // no object event callback
m_pHidWdfIoRequest, // request object as parent
&pInputMemory);
}
//Format request
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfIoTarget->FormatRequestForIoctl( m_pHidWdfIoRequest,
ulCode,
m_pHidWdfFile,
pInputMemory,
NULL,
NULL,
NULL);
}
//
//Send down the request
//
if ( SUCCEEDED( hr ) )
{
hr = m_pHidWdfIoRequest->Send(
m_pHidWdfIoTarget,
WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
0 //No timeout
);
}
if( FAILED( hr ) )
{
m_pHidWdfIoRequest->DeleteWdfObject();
m_pHidWdfIoRequest = NULL;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CReadWriteRequest::CancelAndStopPendingRequest
//
//
//
/////////////////////////////////////////////////////////////////////////
HRESULT CReadWriteRequest::CancelAndStopPendingRequest()
{
HRESULT hr = S_OK;
if ( NULL != m_pHidWdfIoRequest )
{
m_pHidWdfIoRequest->CancelSentRequest();
}
return hr;
}