In the Windows 7 Sensor platform, some properties and data fields contain arrays of information. For example, the SENSOR_PROPERTY_LIGHT_RESPONSE_CURVE property contains an array of 4-byte unsigned integers. However, when you receive such arrays through the Sensor API, they will always represented as type VT_VECTOR|UI1, an array of single-byte characters, regardless of the actual type of the data in the array. This requirement arises because the platform uses the WPD serializer when moving data from the sensor class extension to the API layer. The WPD serializer can serialize arrays of data only if the individual data type is UI1.

From the driver perspective, this means that PROPVARIANT for these array types should be created by using InitPropVariantFromBuffer. This function creates the PROPVARIANT as type VT_VECTOR|UI1. Here's some example code that creates a light response curve:

UINT responseCurve[10] = {0}; // Array to contain the response curve data.

// ****************************************************************************************

// The response curve consists of an array of integer pairs.

// The first integer contains the percentage brightness offset to be applied to the display.

// The second integer contains the corresponding ambient light value (in LUX).

// ****************************************************************************************

// (0, 10)

responseCurve[0] = 0; responseCurve[1] = 10;

// (10, 40)

responseCurve[2] = 10; responseCurve[3] = 40;

// (40, 80)

responseCurve[4] = 40; responseCurve[5] = 80;

// (68, 100)

responseCurve[6] = 68; responseCurve[7] = 100;

// (90, 150)

responseCurve[8] = 90; responseCurve[9] = 150;

 

// Create the buffer.

PROPVARIANT pvCurve = {0};

InitPropVariantFromBuffer(responseCurve, 10 * sizeof (UINT), &pvCurve);

 

// Add the values to the IPortableDeviceValues object.

hr = m_pSensorProperties->SetValue(SENSOR_PROPERTY_LIGHT_RESPONSE_CURVE, &pvCurve);

 

PropVariantClear(&pvCurve);

From the API perspective, you must be careful to cast arrays to the correct data type for the property or data field. Here's an example of how to "unpack" the light response curve data on the API side:

PROPVARIANT pvCurve;
PropVariantInit(&pvCurve);

// Retrieve the property value.
hr = pSensor->GetProperty(SENSOR_PROPERTY_LIGHT_RESPONSE_CURVE, &pvCurve);
if (SUCCEEDED(hr))
{
    if ((VT_UI1|VT_VECTOR) == V_VT(pvCurve)) // Note actual type of UI1
    {
        // Cast the array to UINT, a 4-byte unsigned integer.

        // Item count for the array.
        UINT  cElement = pvCurve.caub.cElems/sizeof(UINT);
        // Array pointer.
        UINT* pElement = (UINT*)(pvCurve.caub.pElems);

        // Use the array.
    }
}

// Remember to free the PROPVARIANT when done.
PropVariantClear(&pvCurve);

Earlier documentation for the Sensor API and WDK (or the header, sensors.h) did not call out this re-typing requirement. We've been updating the docs, but the header comments will continue to show the actual data type, without mention of the serialization issue.