///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnD0Exit // // This method is called when a device leaves the system // // Parameters: // pWdfDevice - pointer to a device object // // // ///////////////////////////////////////////////////////////////////////// HRESULT CMyDevice::OnD0Exit( _In_ IWDFDevice* pWdfDevice, _In_ WDF_POWER_DEVICE_STATE newState ) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); UNREFERENCED_PARAMETER(pWdfDevice); UNREFERENCED_PARAMETER(newState); HRESULT hr = S_OK; hr = EnterProcessing(PROCESSING_IPNPCALLBACK); if (SUCCEEDED(hr)) { if( SUCCEEDED(hr) && NULL != m_pSensorManager) { hr = m_pSensorManager->Stop(newState); } } // processing in progress ExitProcessing(PROCESSING_IPNPCALLBACK); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit, hr = %!HRESULT!", hr); return hr; }
///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnD0Entry // // This method is called after a new device enters the system // // Parameters: // pWdfDevice - pointer to a device object // // ///////////////////////////////////////////////////////////////////////// HRESULT CMyDevice::OnD0Entry( _In_ IWDFDevice* pWdfDevice, _In_ WDF_POWER_DEVICE_STATE previousState ) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); UNREFERENCED_PARAMETER(pWdfDevice); UNREFERENCED_PARAMETER(previousState); HRESULT hr = S_OK; hr = EnterProcessing(PROCESSING_IPNPCALLBACK); if (SUCCEEDED(hr) && (previousState == WdfPowerDeviceD3 || previousState == WdfPowerDeviceD3Final)) { if( NULL != m_pSensorManager && NULL != m_pSensorManager->m_pSensorDDI) { if (TRUE == m_pSensorManager->m_pSensorDDI->m_fDeviceIdle) { hr = m_pSensorManager->m_pSensorDDI->InitSensorDevice(m_pSensorManager->m_spWdfDevice); } if (!SUCCEEDED(hr)) { hr = E_UNEXPECTED; Trace(TRACE_LEVEL_ERROR, "Unable to re-initialize sensor device, hr = %!HRESULT!", hr); } else { m_pSensorManager->m_pSensorDDI->OnDeviceReconnect(); } } } // processing in progress ExitProcessing(PROCESSING_IPNPCALLBACK); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit, hr = %!HRESULT!", hr); return hr; }
///////////////////////////////////////////////////////////////////////// // // CMyQueue::OnDeviceIoControl // // This method is called when an IOCTL is sent to the device // // Parameters: // pQueue - pointer to an IO queue // pRequest - pointer to an IO request // ControlCode - The IOCTL to process // InputBufferSizeInBytes - the size of the input buffer // OutputBufferSizeInBytes - the size of the output buffer // ///////////////////////////////////////////////////////////////////////// STDMETHODIMP_ (void) CMyQueue::OnDeviceIoControl( _In_ IWDFIoQueue* pQueue, _In_ IWDFIoRequest* pRequest, _In_ ULONG ControlCode, SIZE_T InputBufferSizeInBytes, SIZE_T OutputBufferSizeInBytes ) { UNREFERENCED_PARAMETER(pQueue); UNREFERENCED_PARAMETER(InputBufferSizeInBytes); UNREFERENCED_PARAMETER(OutputBufferSizeInBytes); //Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); DWORD dwWritten = 0; if( IS_WPD_IOCTL( ControlCode ) ) { if (FAILED(EnterProcessing(PROCESSING_IQUEUECALLBACKDEVICEIOCONTROL))) { // Unsupported request pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0); } else { m_pParentDevice->ProcessIoControl( pQueue, pRequest, ControlCode, InputBufferSizeInBytes, OutputBufferSizeInBytes, &dwWritten); } // processing in progress ExitProcessing(PROCESSING_IQUEUECALLBACKDEVICEIOCONTROL); } else { // Unsupported request pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0); } }
///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnSelfManagedIoFlush // // Called by UMDF to flush the device for a device's self-managed // I/O operations. // // Parameters: // pWdfDevice - pointer to an IWDFDevice object representing the // device // // Return Values: // ///////////////////////////////////////////////////////////////////////// VOID CMyDevice::OnSelfManagedIoFlush( _In_ IWDFDevice* pWdfDevice ) { UNREFERENCED_PARAMETER(pWdfDevice); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); HRESULT hr = EnterProcessing(PROCESSING_IPNPCALLBACKSELFMANAGEDIO); if (SUCCEEDED(hr)) { if (nullptr != m_spQueue) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Purging queue"); m_spQueue->PurgeSynchronously(); } } ExitProcessing(PROCESSING_IPNPCALLBACKSELFMANAGEDIO); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit, hr = %!HRESULT!", hr); }
///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnCleanupFile // // This method is called when the file handle to the device is closed // // Parameters: // pWdfFile - pointer to a file object // ///////////////////////////////////////////////////////////////////////// VOID CMyDevice::OnCleanupFile( _In_ IWDFFile* pWdfFile ) { //Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); HRESULT hr = S_OK; hr = EnterProcessing(PROCESSING_IFILECALLBACKCLEANUP); if (SUCCEEDED(hr)) { if (NULL != m_pSensorManager) { m_pSensorManager->CleanupFile(pWdfFile); } } // processing in progress ExitProcessing(PROCESSING_IFILECALLBACKCLEANUP); return; }
///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnSelfManagedIoSuspend // // Called by UMDF to suspend a device's self-managed I/O operations. // // All outstanding I/O must be completed. The queue is stopped // to flush out in progress requests. The queue is restarted and // the driver continues to get I/O, but the m_fDeviceActive flag is // set to false so that the hardware will not be accessed. // // Parameters: // pWdfDevice - pointer to an IWDFDevice object representing the // device // // Return Values: // S_OK: success // ///////////////////////////////////////////////////////////////////////// HRESULT CMyDevice::OnSelfManagedIoSuspend( _In_ IWDFDevice* pWdfDevice ) { UNREFERENCED_PARAMETER(pWdfDevice); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); HRESULT hr = EnterProcessing(PROCESSING_IPNPCALLBACKSELFMANAGEDIO); if (SUCCEEDED(hr)) { if (nullptr != m_pSensorManager) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Hardware is now not available"); m_pSensorManager->m_fDeviceActive = false; } if (nullptr != m_spQueue) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Flushing queue of running requests"); // TODO If all hardware requests are not guaranteed to complete within 1 second then // the queue should be stopped and all pending hardweare requests canceled //m_spQueue->Stop(nullptr); // Uncomment this line if the hardware requests need to be canceled // As noted above, cancel all pending hardware requests here to allow all ISensorDriver:: callbacks to complete m_spQueue->StopSynchronously(); // NOTE Any asynchronous work that accesses the hardware should be stopped m_spQueue->Start(); } } ExitProcessing(PROCESSING_IPNPCALLBACKSELFMANAGEDIO); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit, hr = %!HRESULT!", hr); return hr; }
///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnSelfManagedIoRestart // // Called by UMDF to restart a device's self-managed I/O operations. // // Parameters: // pWdfDevice - pointer to an IWDFDevice object representing the // device // // Return Values: // S_OK: success // ///////////////////////////////////////////////////////////////////////// HRESULT CMyDevice::OnSelfManagedIoRestart( _In_ IWDFDevice* pWdfDevice ) { UNREFERENCED_PARAMETER(pWdfDevice); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); HRESULT hr = EnterProcessing(PROCESSING_IPNPCALLBACKSELFMANAGEDIO); if (SUCCEEDED(hr)) { if (nullptr != m_pSensorManager) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Hardware is now available"); m_pSensorManager->m_fDeviceActive = true; } } ExitProcessing(PROCESSING_IPNPCALLBACKSELFMANAGEDIO); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit, hr = %!HRESULT!", hr); return hr; }
///////////////////////////////////////////////////////////////////////// // // CMyDevice::OnPrepareHardware // // Called by UMDF to prepare the hardware for use. In our case // we create the SensorDDI object and initialize the Sensor Class Extension // // Parameters: // pWdfDevice - pointer to an IWDFDevice object representing the // device // // Return Values: // S_OK: success // ///////////////////////////////////////////////////////////////////////// HRESULT CMyDevice::OnPrepareHardware( _In_ IWDFDevice* pWdfDevice ) { Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); HRESULT hr = (NULL != pWdfDevice) ? S_OK : E_UNEXPECTED; if (SUCCEEDED(hr)) { hr = EnterProcessing(PROCESSING_IPNPCALLBACKHARDWARE); if (SUCCEEDED(hr)) { if( NULL != pWdfDevice ) { // Store the IWDFDevice pointer m_spWdfDevice = pWdfDevice; } // Create & Configure the default IO Queue if (SUCCEEDED(hr)) { hr = ConfigureQueue(); } // Create the sensor manager object if (SUCCEEDED(hr)) { hr = CComObject<CSensorManager>::CreateInstance(&m_pSensorManager); if (nullptr != m_pSensorManager) { if ((SUCCEEDED(hr)) && (NULL != m_pSensorManager)) { m_pSensorManager->AddRef(); } // Initialize the sensor manager object if(SUCCEEDED(hr)) { hr = m_pSensorManager->Initialize(m_spWdfDevice, this); } } else { hr = E_POINTER; } } if (SUCCEEDED(hr)) { hr = StringCchCopy(m_pSensorManager->m_wszDeviceName, MAX_PATH, DEFAULT_DEVICE_MODEL_VALUE); if (SUCCEEDED(hr)) { ULONG ulCchInstanceId = 0; BOOL fResult = FALSE; WCHAR* wszInstanceId = nullptr; WCHAR* tempStr = nullptr; try { wszInstanceId = new WCHAR[MAX_PATH]; } catch(...) { hr = E_UNEXPECTED; Trace(TRACE_LEVEL_ERROR, "Failed to allocate memory for instance ID string, hr = %!HRESULT!", hr); if (nullptr != wszInstanceId) { delete[] wszInstanceId; } } try { tempStr = new WCHAR[MAX_PATH]; } catch(...) { hr = E_UNEXPECTED; Trace(TRACE_LEVEL_ERROR, "Failed to allocate memory for instance ID temp string, hr = %!HRESULT!", hr); if (nullptr != tempStr) { delete[] tempStr; } } if (SUCCEEDED(pWdfDevice->RetrieveDeviceInstanceId(NULL, &ulCchInstanceId))) { if (SUCCEEDED(pWdfDevice->RetrieveDeviceInstanceId(wszInstanceId, &ulCchInstanceId))) { HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; if (INVALID_HANDLE_VALUE != (hDeviceInfo = ::SetupDiCreateDeviceInfoList(NULL, NULL))) { SP_DEVINFO_DATA deviceInfo = {sizeof(SP_DEVINFO_DATA)}; if (TRUE == ::SetupDiOpenDeviceInfo(hDeviceInfo, wszInstanceId, NULL, 0, &deviceInfo)) { DEVPROPTYPE propType; ULONG ulSize; fResult = ::SetupDiGetDeviceProperty(hDeviceInfo, &deviceInfo, &DEVPKEY_Device_DeviceDesc, &propType, (PBYTE)tempStr, MAX_PATH*sizeof(WCHAR), &ulSize, 0); if (FALSE == fResult) { hr = HRESULT_FROM_WIN32(GetLastError()); } #pragma warning(suppress: 26035) //possible failure to null terminate string if (SUCCEEDED(hr) && (wcscmp(tempStr, L"") != 0)) { wcscpy_s(m_pSensorManager->m_wszDeviceName, MAX_PATH, tempStr); } ::SetupDiDestroyDeviceInfoList(hDeviceInfo); } } } } #pragma warning(suppress: 6001) //using unitialized memory if (nullptr != wszInstanceId) { delete[] wszInstanceId; } #pragma warning(suppress: 6001) //using unitialized memory if (nullptr != tempStr) { delete[] tempStr; } } } } // processing in progress ExitProcessing(PROCESSING_IPNPCALLBACKHARDWARE); } if (FAILED(hr)) { Trace(TRACE_LEVEL_CRITICAL, "Abnormal results during hardware initialization, hr = %!HRESULT!", hr); } Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit, hr = %!HRESULT!", hr); return hr; }
///////////////////////////////////////////////////////////////////////// // // CMyQueue::OnDeviceIoControl // // This method is called when an IOCTL is sent to the device // // Parameters: // pQueue - pointer to an IO queue // pRequest - pointer to an IO request // ControlCode - The IOCTL to process // InputBufferSizeInBytes - the size of the input buffer // OutputBufferSizeInBytes - the size of the output buffer // ///////////////////////////////////////////////////////////////////////// STDMETHODIMP_ (void) CMyQueue::OnDeviceIoControl( _In_ IWDFIoQueue* pQueue, _In_ IWDFIoRequest* pRequest, _In_ ULONG ControlCode, SIZE_T InputBufferSizeInBytes, SIZE_T OutputBufferSizeInBytes ) { UNREFERENCED_PARAMETER(pQueue); UNREFERENCED_PARAMETER(InputBufferSizeInBytes); UNREFERENCED_PARAMETER(OutputBufferSizeInBytes); //Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry"); DWORD dwWritten = 0; if (IOCTL_GPS_RADIO_MANAGEMENT_GET_RADIO_STATE == ControlCode || IOCTL_GPS_RADIO_MANAGEMENT_GET_PREVIOUS_RADIO_STATE == ControlCode || IOCTL_GPS_RADIO_MANAGEMENT_SET_RADIO_STATE == ControlCode || IOCTL_GPS_RADIO_MANAGEMENT_SET_PREVIOUS_RADIO_STATE == ControlCode ) { #if (NTDDI_VERSION >= NTDDI_WIN8) if (FAILED(EnterProcessing(PROCESSING_IQUEUECALLBACKDEVICEIOCONTROL))) { // Unsupported request pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0); } else { HRESULT hr = m_pParentDevice->ProcessIoControlRadioManagement(pRequest, ControlCode); pRequest->CompleteWithInformation(hr, sizeof(DEVICE_RADIO_STATE)); } // processing in progress ExitProcessing(PROCESSING_IQUEUECALLBACKDEVICEIOCONTROL); #endif } else if( IS_WPD_IOCTL( ControlCode ) ) { if (FAILED(EnterProcessing(PROCESSING_IQUEUECALLBACKDEVICEIOCONTROL))) { // Unsupported request pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0); } else { m_pParentDevice->ProcessIoControl( pQueue, pRequest, ControlCode, InputBufferSizeInBytes, OutputBufferSizeInBytes, &dwWritten); } // processing in progress ExitProcessing(PROCESSING_IQUEUECALLBACKDEVICEIOCONTROL); } else { // Unsupported request pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0); } }