Exemple #1
0
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);
    }
}
Exemple #2
0
/**
 *  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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
/**
 *  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;
}