void FOSVRHMD::UpdateHeadPose(FQuat& lastHmdOrientation, FVector& lastHmdPosition, FQuat& hmdOrientation, FVector& hmdPosition) { OSVR_Pose3 pose; OSVR_ReturnCode returnCode; auto entryPoint = IOSVR::Get().GetEntryPoint(); FScopeLock lock(entryPoint->GetClientContextMutex()); auto clientContext = entryPoint->GetClientContext(); returnCode = osvrClientUpdate(clientContext); check(returnCode == OSVR_RETURN_SUCCESS); returnCode = osvrClientGetViewerPose(DisplayConfig, 0, &pose); if (returnCode == OSVR_RETURN_SUCCESS) { LastHmdOrientation = CurHmdOrientation; LastHmdPosition = CurHmdPosition; CurHmdPosition = BaseOrientation.Inverse().RotateVector(OSVR2FVector(pose.translation, WorldToMetersScale) - BasePosition); CurHmdOrientation = BaseOrientation.Inverse() * OSVR2FQuat(pose.rotation); lastHmdOrientation = LastHmdOrientation; lastHmdPosition = LastHmdPosition; hmdOrientation = CurHmdOrientation; hmdPosition = CurHmdPosition; } else { lastHmdOrientation = hmdOrientation = FQuat::Identity; lastHmdPosition = hmdPosition = FVector(0.0f, 0.0f, 0.0f); } }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_CLOSE * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: identifies the resource context associated with a * previously opened resource. * * The driver should: * - Unlock the resource if necessary, and release any system and device resources associated with this WPD object resource. */ HRESULT WpdObjectResources::OnClose( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { // No results are expected to be returned UNREFERENCED_PARAMETER(pResults); HRESULT hr = S_OK; LPWSTR pszContext = NULL; ContextMap* pContextMap = NULL; ResourceContext* pContext = NULL; // Get the Object ID hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &pszContext); if (FAILED(hr)) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the context map which the driver stored in pParams for convenience if (SUCCEEDED(hr)) { hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); } // If this was a creation request, enable the resource for the content if (SUCCEEDED(hr)) { // Get the context for this transfer hr = GetClientContext(pParams, pszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Failed to get resource context"); } if (SUCCEEDED(hr)) { if (pContext->CreateRequest == TRUE) { hr = m_pFakeDevice->EnableResource(pContext->ObjectID, pContext->Key); CHECK_HR(hr, "Failed to enable resource on object [%ws]", pContext->ObjectID); } } //Free the context SAFE_RELEASE(pContext); if (SUCCEEDED(hr)) { hr = DestroyResourceContext(pContextMap, pszContext); CHECK_HR(hr, "Failed to remove resource context [%ws]", pszContext); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pszContext); SAFE_RELEASE(pContextMap); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_COMMIT_OBJECT * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT: identifies the object creation request (driver returned this in * WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT). * * The driver should: * - Commit the object to the device. * - Return the new/updated ObjectID in WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID. */ HRESULT WpdObjectManagement::OnCommit( IPortableDeviceValues* pParams, IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pszContext = NULL; ObjectManagementContext* pContext = NULL; ContextMap* pContextMap = NULL; CComPtr<IPortableDeviceValues> pEventParams; hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, &pszContext); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); // Get the object management context for this request if (hr == S_OK) { hr = GetClientContext(pParams, pszContext, (IUnknown**)&pContext); CHECK_HR(hr, "Failed to get Object Management Context"); } if (hr == S_OK) { hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); } if (hr == S_OK) { if (pContext->UpdateRequest) { // Update the object hr = UpdateObject(pContext, pParams, pResults); } else { // Save the new object hr = CommitNewObject(pContext, pszContext, pParams, pResults); } } // We're done with the context SAFE_RELEASE(pContext); // Destroy the context associated with this request, since it is no longer needed if (hr == S_OK) { hr = DestroyObjectManagementContext(pContextMap, pszContext); CHECK_HR(hr, "Failed to destroy object identified by context [%ws]", pszContext); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pszContext); SAFE_RELEASE(pContextMap); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_WRITE_OBJECT_DATA * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT: identifies the object creation request previsouly started with * WPD_PROPERTY_OBJECT_MANAGEMENT_CREATE_OBJECT. * - WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE: specifies the next number of bytes to write. * - WPD_PROPERTY_OBJECT_MANAGEMENT_DATA: specifies byte array where the data should be copied from. * * The driver should: * - Write the next WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE to the resource. * - Return the number of bytes actually written in WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_WRITTEN. * It is normally considered an error if this value does not match WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE. */ HRESULT WpdObjectManagement::OnWriteObjectData( IPortableDeviceValues* pParams, IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pszContext = NULL; DWORD dwNumBytesToWrite = 0; DWORD dwNumBytesWritten = 0; BYTE* pBuffer = NULL; DWORD cbBuffer = 0; ObjectManagementContext* pContext = NULL; // Get the Context string if (hr == S_OK) { hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, &pszContext); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT"); } // Get the number of bytes to write if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE, &dwNumBytesToWrite); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE"); } // Get the source buffer if (hr == S_OK) { hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_MANAGEMENT_DATA, &pBuffer, &cbBuffer); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_DATA"); } // Get the resource context for this object creation request if (hr == S_OK) { hr = GetClientContext(pParams, pszContext, (IUnknown**)&pContext); CHECK_HR(hr, "Failed to get Object Management Context"); } // Write the next band of data for this new object request if (hr == S_OK) { // TBD: Write bytes to object. This sample driver ignores the data content. dwNumBytesWritten = dwNumBytesToWrite; } if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_WRITTEN, dwNumBytesWritten); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_WRITTEN"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pszContext); // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pBuffer); SAFE_RELEASE(pContext); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_PROPERTIES_BULK_SET_VALUES_BY_OBJECT_LIST_NEXT * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT: the context the driver returned to * the client in OnGetValuesByObjectListStart. * * The driver should: * - Write the next set of property values, and return the write results in WPD_PROPERTY_OBJECT_PROPERTIES_BULK_WRITE_RESULTS. * If there are no more properties to be written, an empty collection should be returned. * - It is up to the driver to write as many object property values as it wants. If zero write results are returned * it is assumed the bulk operation is complete and the WPD_COMMAND_OBJECT_PROPERTIES_BULK_SET_VALUES_BY_OBJECT_LIST_END * will be called next. * * - S_OK should be returned if the collection can be returned successfully. * - Any error return indicates that the driver did not fill in any results, and the caller will * not attempt to unpack any property values. */ HRESULT WpdObjectPropertiesBulk::OnSetValuesByObjectListNext( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pwszContext = NULL; BulkPropertiesContext* pContext = NULL; DWORD cObjects = 0; CComPtr<IPortableDeviceValues> pEventParams; CComPtr<IPortableDeviceValuesCollection> pWriteResults; CComPtr<IPortableDeviceValuesCollection> pValuesCollection; hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT, &pwszContext); CHECK_HR(hr, "Failed to get WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT from IPortableDeviceValues"); // Get the bulk property operation context if (SUCCEEDED(hr)) { hr = GetClientContext(pParams, pwszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Failed to get bulk property context"); } // Make sure the the collection holds a ValuesCollection, then get the number of elements. if (SUCCEEDED(hr)) { if(pContext->ValuesCollection != NULL) { hr = pContext->ValuesCollection->GetCount(&cObjects); CHECK_HR(hr, "Failed to get number of objectIDs from bulk properties context"); } else { hr = E_INVALIDARG; CHECK_HR(hr, "Incorrect context specified - this context does not contain a values collection"); } } // Create the collection to hold the write results if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValuesCollection, (VOID**) &pWriteResults); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValuesCollection"); } // Create the collection to hold the event parameters if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pEventParams); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValues"); } if (SUCCEEDED(hr)) { for (DWORD dwIndex = pContext->NextObject; dwIndex < cObjects; dwIndex++) { CComPtr<IPortableDeviceValues> pValues; CComPtr<IPortableDeviceValues> pSetResults; bool bObjectChanged = false; hr = pContext->ValuesCollection->GetAt(dwIndex, &pValues); CHECK_HR(hr, "Failed to get next values from bulk properties context"); // CoCreate a collection to store the per object results. if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pSetResults); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValues"); } if (SUCCEEDED(hr)) { LPWSTR pszObjectID = NULL; // Get which object this is for hr = pValues->GetStringValue(WPD_OBJECT_ID, &pszObjectID); if (SUCCEEDED(hr)) { hr = m_pDevice->SetPropertyValues(pContext->Scope, pszObjectID, pValues, pSetResults, pEventParams, &bObjectChanged); CHECK_HR(hr, "Failed to get count of values"); } if (SUCCEEDED(hr)) { // Ensure the write results contain which ObjectID this was for hr = pSetResults->SetStringValue(WPD_OBJECT_ID, pszObjectID); CHECK_HR(hr, "Failed to set WPD_OBJECT_ID in write results"); if (SUCCEEDED(hr) && bObjectChanged) { // set property values is successful and object has changed, so we post an event. // This is best effort, so errors are ignored HRESULT hrEvent = PostWpdEvent(pParams, pEventParams); CHECK_HR(hrEvent, "Failed post event for updated object [%ws] (errors ignored)", pszObjectID); } pEventParams->Clear(); } CoTaskMemFree(pszObjectID); } if (SUCCEEDED(hr)) { hr = pWriteResults->Add(pSetResults); CHECK_HR(hr, "Failed to add IPortableDeviceValues to IPortableDeviceValuesCollection"); } pContext->NextObject++; } } if (SUCCEEDED(hr)) { hr = pResults->SetIUnknownValue(WPD_PROPERTY_OBJECT_PROPERTIES_BULK_WRITE_RESULTS, pWriteResults); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_PROPERTIES_BULK_WRITE_RESULTS"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pwszContext); SAFE_RELEASE(pContext); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_PROPERTIES_BULK_GET_VALUES_BY_OBJECT_FORMAT_NEXT * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT: the context the driver returned to * the client in OnGetValuesByObjectFormatStart. * * The driver should: * - Return the next set of property values in WPD_PROPERTY_OBJECT_PROPERTIES_BULK_VALUES. * If there are no more properties to be read an * empty collection should be returned. * - It is up to the driver to return as many object property values as it wants. If zero values are returned * it is assumed the bulk operation is complete and the WPD_COMMAND_OBJECT_PROPERTIES_BULK_GET_VALUES_BY_OBJECT_FORMAT_END * will be called next. * * - S_OK should be returned if the collection can be returned successfully. * - Any error return indicates that the driver did not fill in any results, and the caller will * not attempt to unpack any property values. */ HRESULT WpdObjectPropertiesBulk::OnGetValuesByObjectFormatNext( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pwszContext = NULL; BulkPropertiesContext* pContext = NULL; DWORD cObjects = 0; CComPtr<IPortableDeviceValuesCollection> pCollection; hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT, &pwszContext); CHECK_HR(hr, "Failed to get WPD_PROPERTY_OBJECT_PROPERTIES_BULK_CONTEXT from IPortableDeviceValues"); // Get the bulk property operation context if (SUCCEEDED(hr)) { hr = GetClientContext(pParams, pwszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Failed to get bulk property context"); } // Make sure the the collection holds VT_LPWSTR values. if (SUCCEEDED(hr)) { hr = pContext->ObjectIDs->ChangeType(VT_LPWSTR); CHECK_HR(hr, "Failed to change objectIDs collection to VT_LPWSTR"); } if (SUCCEEDED(hr)) { hr = pContext->ObjectIDs->GetCount(&cObjects); CHECK_HR(hr, "Failed to get number of objectIDs from bulk properties context"); } if (SUCCEEDED(hr)) { cObjects = cObjects - pContext->NextObject; if(cObjects > MAX_OBJECTS_TO_RETURN) { cObjects = MAX_OBJECTS_TO_RETURN; } } if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValuesCollection, (VOID**) &pCollection); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValuesCollection"); } if (SUCCEEDED(hr)) { for (DWORD dwIndex = pContext->NextObject, dwCount = 0; dwCount < cObjects; dwCount++, dwIndex++) { CComPtr<IPortableDeviceValues> pValues; PROPVARIANT pv = {0}; PropVariantInit(&pv); hr = pContext->ObjectIDs->GetAt(dwIndex, &pv); CHECK_HR(hr, "Failed to get next object ID from bulk properties context"); if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pValues); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceValuesCollection"); } if (SUCCEEDED(hr)) { // If a key list was supplied, get the specified object properties, other get all // properties. if(pContext->Properties != NULL) { hr = m_pDevice->GetPropertyValues(pContext->Scope, pv.pwszVal, pContext->Properties, pValues); CHECK_HR(hr, "Failed to get property values for [%ws]", pv.pwszVal); } else { hr = m_pDevice->GetAllPropertyValues(pContext->Scope,pv.pwszVal, pValues); CHECK_HR(hr, "Failed to get property values for [%ws]", pv.pwszVal); } } // Add the ObjectID to the returned results if (SUCCEEDED(hr)) { hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal); CHECK_HR(hr, "Failed to set WPD_OBJECT_ID for %ws", pv.pwszVal); } if (SUCCEEDED(hr)) { hr = pCollection->Add(pValues); CHECK_HR(hr, "Failed to add IPortableDeviceValues to IPortableDeviceValuesCollection"); } PropVariantClear(&pv); pContext->NextObject++; } } if (SUCCEEDED(hr)) { hr = pResults->SetIUnknownValue(WPD_PROPERTY_OBJECT_PROPERTIES_BULK_VALUES, pCollection); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_PROPERTIES_BULK_VALUES"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pwszContext); SAFE_RELEASE(pContext); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_SEEK * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: identifies the resource context associated with a * previously opened resource. * - WPD_PROPERTY_OBJECT_RESOURCES_SEEK_OFFSET: Displacement to be added to the location indicated by the WPD_PROPERTY_OBJECT_RESOURCES_SEEK_ORIGIN_FLAG parameter. * - WPD_PROPERTY_OBJECT_RESOURCES_SEEK_ORIGIN_FLAG: Specifies the origin of the displacement for the seek operation. Can be one of the following values: * STREAM_SEEK_SET - Offset is from the beginning of the stream * STREAM_SEEK_CUR - Offset is from the current position in the stream * STREAM_SEEK_END - Offset is from the end of the stream * * The driver should: * - Move the seek pointer for the resource to point to the specified position, so that * subsequent read / write operations occur from the new position. * - Return the new position as an offset relative to the start of the data stream in WPD_PROPERTY_OBJECT_RESOURCES_POSITION_FROM_START. */ HRESULT WpdObjectResources::OnSeek( IPortableDeviceValues* pParams, IPortableDeviceValues* pResults) { // No results are expected to be returned UNREFERENCED_PARAMETER(pResults); HRESULT hr = S_OK; LPWSTR pszContext = NULL; DWORD dwOrigin = 0; LONGLONG lOffset = 0; ResourceContext* pContext = NULL; // Get the Object ID hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &pszContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the offset if (hr == S_OK) { hr = pParams->GetSignedLargeIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_SEEK_OFFSET, &lOffset); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_SEEK_OFFSET"); } // Get the origin flags if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_SEEK_ORIGIN_FLAG, &dwOrigin); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_SEEK_ORIGIN_FLAG"); } // Get the context for this transfer if (hr == S_OK) { hr = GetClientContext(pParams, pszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Failed to get resource context"); } // Update the current seek pointer. For this driver, we update the NumBytesTransfered in the context so that subsequent reads/writes start // at the appropriate place. if (hr == S_OK) { ULONG ulSize = 0; ULONG ulOriginalNumBytesTransfered = pContext->NumBytesTransfered; CComPtr<IPortableDeviceValues> pResourceAttributes; // Get the total size of the resource hr = m_pFakeDevice->GetResourceAttributes(pContext->ObjectID, pContext->Key, &pResourceAttributes); CHECK_HR(hr, "Failed to get attributes on [%ws]", pContext->ObjectID); if (hr == S_OK) { hr = pResourceAttributes->GetUnsignedIntegerValue(WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE, &ulSize); CHECK_HR(hr, "Failed to get WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE"); } if(dwOrigin == STREAM_SEEK_CUR) { pContext->NumBytesTransfered += (LONG) lOffset; } else if(dwOrigin == STREAM_SEEK_SET) { pContext->NumBytesTransfered = (LONG) lOffset; } else { pContext->NumBytesTransfered = ulSize + (LONG) lOffset; } // Validate that this is in the correct range if (hr == S_OK) { if(pContext->NumBytesTransfered > ulSize) { hr = E_INVALIDARG; CHECK_HR(hr, "Attempting to seek beyond existing data"); // Restore the seek pointer to its original value pContext->NumBytesTransfered = ulOriginalNumBytesTransfered; } } } // Set the return value if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_POSITION_FROM_START, pContext->NumBytesTransfered); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_POSITION_FROM_START"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pszContext); SAFE_RELEASE(pContext); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_WRITE * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: identifies the previsouly opened resource we are going to write to. * - WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_WRITE: specifies the next number of bytes to write. * - WPD_PROPERTY_OBJECT_RESOURCES_DATA: specifies byte array where the data should be copied from. * * The driver should: * - Write the next WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_WRITE to the resource. * - Return the number of bytes actually written in WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_WRITTEN. * It is normally considered an error if this value does not match WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_WRITE. */ HRESULT WpdObjectResources::OnWrite( IPortableDeviceValues* pParams, IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pszContext = NULL; DWORD dwNumBytesToWrite = 0; DWORD dwNumBytesWritten = 0; BYTE* pBuffer = NULL; DWORD cbBuffer = 0; ResourceContext* pContext = NULL; // Get the Context string hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &pszContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the number of bytes to write if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_WRITE, &dwNumBytesToWrite); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_WRITE"); } // Get the source buffer if (hr == S_OK) { hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, &pBuffer, &cbBuffer); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } // Get the resource context for this transfer if (hr == S_OK) { hr = GetClientContext(pParams, pszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Faield to get resource context"); } // Write the next band of data for this transfer request if (hr == S_OK) { hr = m_pFakeDevice->WriteData(pContext->ObjectID, pContext->Key, pContext->NumBytesTransfered, pBuffer, dwNumBytesToWrite, &dwNumBytesWritten); CHECK_HR(hr, "Failed to write %d bytes to [%ws] on resource {%ws}.%d", dwNumBytesToWrite, pContext->ObjectID, CComBSTR(pContext->Key.fmtid), pContext->Key.pid); if (SUCCEEDED(hr)) { pContext->NumBytesTransfered += dwNumBytesWritten; } } if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_WRITTEN, dwNumBytesWritten); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_WRITTEN"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pszContext); // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pBuffer); SAFE_RELEASE(pContext); return hr; }
HRESULT WpdObjectEnumerator::OnFindNext( _In_ IPortableDeviceValues* pParams, _Inout_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszEnumContext = NULL; DWORD dwNumObjectsRequested = 0; DWORD dwNumObjectsEnumerated = 0; WpdObjectEnumeratorContext* pEnumeratorContext = NULL; CComPtr<IPortableDevicePropVariantCollection> pObjectIDCollection; // First get ALL parameters for this command. If we cannot get ALL parameters // then E_INVALIDARG should be returned and no further processing should occur. // Get the enumeration context identifier for this enumeration operation. // The enumeration context identifier is needed to lookup the specific // enumeration context in the client context map for this enumeration operation. // NOTE that more than one enumeration may be in progress. hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, &wszEnumContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT"); } // Get the number of objects requested for this enumeration call. // The driver should always attempt to meet this requested value. // If there are fewer children than requested, the driver should return the remaining // children and a return code of S_FALSE. hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, &dwNumObjectsRequested); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED"); } // Get the enumeration context for this enumeration operation. if (hr == S_OK) { hr = GetClientContext(pParams, wszEnumContext, (IUnknown**)&pEnumeratorContext); CHECK_HR(hr, "Failed to get the enumeration context"); } // CoCreate a collection to store the object identifiers being returned for this enumeration call. if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDevicePropVariantCollection, (VOID**) &pObjectIDCollection); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDevicePropVariantCollection"); } if ((hr == S_OK) && (pEnumeratorContext != NULL)) { hr = m_pDevice->FindNext(dwNumObjectsRequested, pEnumeratorContext, pObjectIDCollection, &dwNumObjectsEnumerated); CHECK_HR(hr, "Failed to get the next object"); } // Set the collection of object identifiers enumerated in the results if (hr == S_OK) { hr = pResults->SetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_ENUMERATION_OBJECT_IDS, pObjectIDCollection); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_ENUMERATION_OBJECT_IDS"); } // If the enumeration context reports that their are no more objects to return then return S_FALSE indicating to the // caller that we are finished. if (hr == S_OK) { if (pEnumeratorContext != NULL) { // Update the number of children we have enumerated and returned to the caller pEnumeratorContext->m_ChildrenEnumerated += dwNumObjectsEnumerated; // Check the number requested against the number enumerated and set the HRESULT // accordingly. if (dwNumObjectsEnumerated < dwNumObjectsRequested) { // We returned less than the number of objects requested to the caller hr = S_FALSE; } else { // We returned exactly the number of objects requested to the caller hr = S_OK; } } } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszEnumContext); SAFE_RELEASE(pEnumeratorContext); return hr; }
FOSVRHMD::FOSVRHMD() : LastHmdOrientation(FQuat::Identity), CurHmdOrientation(FQuat::Identity), DeltaControlRotation(FRotator::ZeroRotator), DeltaControlOrientation(FQuat::Identity), CurHmdPosition(FVector::ZeroVector), BaseOrientation(FQuat::Identity), BasePosition(FVector::ZeroVector), WorldToMetersScale(100.0f), bHmdPosTracking(false), bHaveVisionTracking(false), bStereoEnabled(true), bHmdEnabled(true), bHmdOverridesApplied(false), DisplayConfig(nullptr) { static const FName RendererModuleName("Renderer"); RendererModule = FModuleManager::GetModulePtr<IRendererModule>(RendererModuleName); auto entryPoint = IOSVR::Get().GetEntryPoint(); FScopeLock lock(entryPoint->GetClientContextMutex()); auto osvrClientContext = entryPoint->GetClientContext(); // Prevents debugger hangs that sometimes occur with only one monitor. #if OSVR_UNREAL_DEBUG_FORCED_WINDOWMODE FSystemResolution::RequestResolutionChange(1280, 720, EWindowMode::Windowed); // bStereo ? WindowedMirror : Windowed #endif EnablePositionalTracking(true); IConsoleVariable* CVScreenPercentage = IConsoleManager::Get().FindConsoleVariable(TEXT("r.screenpercentage")); if (CVScreenPercentage) { mScreenScale = float(CVScreenPercentage->GetInt()) / 100.0f; } StartCustomPresent(); // enable vsync IConsoleVariable* CVSyncVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync")); if (CVSyncVar) { CVSyncVar->Set(false); } // Uncap fps to enable FPS higher than 62 GEngine->bSmoothFrameRate = false; // check if the client context is ok. bool bClientContextOK = entryPoint->IsOSVRConnected(); // get the display context bool bDisplayConfigOK = false; if (bClientContextOK) { bool bFailure = false; auto rc = osvrClientGetDisplay(osvrClientContext, &DisplayConfig); if (rc == OSVR_RETURN_FAILURE) { UE_LOG(OSVRHMDLog, Warning, TEXT("Could not create DisplayConfig. Treating this as if the HMD is not connected.")); } else { auto begin = FDateTime::Now().GetSecond(); auto end = begin + 3; while (!bDisplayConfigOK && FDateTime::Now().GetSecond() < end) { bDisplayConfigOK = osvrClientCheckDisplayStartup(DisplayConfig) == OSVR_RETURN_SUCCESS; if (!bDisplayConfigOK) { bFailure = osvrClientUpdate(osvrClientContext) == OSVR_RETURN_FAILURE; if (bFailure) { UE_LOG(OSVRHMDLog, Warning, TEXT("osvrClientUpdate failed during startup. Treating this as \"HMD not connected\"")); break; } } FPlatformProcess::Sleep(0.2f); } bDisplayConfigOK = bDisplayConfigOK && !bFailure; if (!bDisplayConfigOK) { UE_LOG(OSVRHMDLog, Warning, TEXT("DisplayConfig failed to startup. This could mean that there is nothing mapped to /me/head. Treating this as if the HMD is not connected.")); } } } bool bDisplayConfigMatchesUnrealExpectations = false; if (bDisplayConfigOK) { bool bSuccess = HMDDescription.Init(osvrClientContext, DisplayConfig); if (bSuccess) { bDisplayConfigMatchesUnrealExpectations = HMDDescription.OSVRViewerFitsUnrealModel(DisplayConfig); if (!bDisplayConfigMatchesUnrealExpectations) { UE_LOG(OSVRHMDLog, Warning, TEXT("The OSVR display config does not match the expectations of Unreal. Possibly incompatible HMD configuration.")); } } else { UE_LOG(OSVRHMDLog, Warning, TEXT("Unable to initialize the HMDDescription. Possible failures during initialization.")); } } // our version of connected is that the client context is ok (server is running) // and the display config is ok (/me/head exists and received a pose) bHmdConnected = bClientContextOK && bDisplayConfigOK && bDisplayConfigMatchesUnrealExpectations; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_READ * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: identifies the previsouly opened resource we are going to read from. * - WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ: specifies the next number of bytes to read. * - WPD_PROPERTY_OBJECT_RESOURCES_DATA: specifies byte array where the data should be copied to. * * The driver should: * - Read up to the next WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ from the resource. * - Return the number of bytes actually read in WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ. */ HRESULT WpdObjectResources::OnRead( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR pszContext = NULL; DWORD dwNumBytesToRead = 0; DWORD dwNumBytesRead = 0; BYTE* pBuffer = NULL; DWORD cbBuffer = 0; ResourceContext* pContext = NULL; // Get the Context hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &pszContext); if (FAILED(hr)) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the number of bytes to read if (SUCCEEDED(hr)) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ, &dwNumBytesToRead); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ"); } // Get the destination buffer if (SUCCEEDED(hr)) { hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, &pBuffer, &cbBuffer); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } // Get the context for this transfer if (SUCCEEDED(hr)) { hr = GetClientContext(pParams, pszContext, (IUnknown**) &pContext); CHECK_HR(hr, "Failed to get resource context"); } // Read the next band of data for this transfer request if (SUCCEEDED(hr) && pBuffer != NULL) { hr = m_pFakeDevice->ReadData(pContext->ObjectID, pContext->Key, pContext->NumBytesTransfered, pBuffer, dwNumBytesToRead, &dwNumBytesRead); CHECK_HR(hr, "Failed to read %d bytes from [%ws] on resource {%ws}.%d", dwNumBytesToRead, pContext->ObjectID, CComBSTR(pContext->Key.fmtid), pContext->Key.pid); if (SUCCEEDED(hr)) { pContext->NumBytesTransfered += dwNumBytesRead; } } if (SUCCEEDED(hr) && pBuffer != NULL) { hr = pResults->SetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, pBuffer, dwNumBytesRead); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } if (SUCCEEDED(hr)) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ, dwNumBytesRead); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pszContext); // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pBuffer); SAFE_RELEASE(pContext); return hr; }