Developing Your First Sensor Driver – Part 2

In the last blog post we investigated the fundamental characteristics of a sensor driver (properties and data fields) and how the Sensor Class Extension interacts with them. Here we will expand the basic driver template to include raising events and managing clients. A client is an application that has requested a connection to the driver through the class extension.

This blog post will focus on the Time Sensor Sample from the Windows Driver Kit. In general this driver creates a thread that periodically requests data from the ‘device’ (just the system time), and posts it to the class extension. This differs from the skeleton sample examined previously, which merely responds to synchronous data requests. Let’s look at the following code snippet from _EventThreadProc in CSampleEvents to illustrate this additional functionality. Note some comments have been modified.

    1: // 
    2: // Fetching data and posting an event, 
    3: // from _EventThreadProc, lines 193 - 225 
    4: // 
    5:  
    6: CComPtr<IPortableDeviceValues> spEventParams;
    7: CComPtr<IPortableDeviceKeyCollection> spKeys;
    8:             
    9: if(SUCCEEDED(hr))
   10: {            
   11:     // Use the Ddi class to create the key collection.
   12:     hr = pThis->m_pDdi->OnGetSupportedDataFields(
   13:         g_wszSensorID, &spKeys);
   14: }
   15:  
   16: if(SUCCEEDED(hr))
   17: {
   18:     CComPtr<IWDFFile> spTemp;
   19:  
   20:     // Get the data fields.
   21:     hr = pThis->m_pDdi->OnGetDataFields(
   22:         spTemp, g_wszSensorID, spKeys, &spEventParams);
   23: }
   24:  
   25: if(SUCCEEDED(hr))
   26: {
   27:     // Add the data event property key.
   28:     hr = spEventParams->SetGuidValue(
   29:         SENSOR_EVENT_PARAMETER_EVENT_ID, 
   30:         SENSOR_EVENT_DATA_UPDATED);
   31:             
   32: if(SUCCEEDED(hr))
   33: {
   34:     // Post the event.
   35:     hr = pThis->PostDataEvent(spEventParams);                

In the first two blocks of code, we get a list of supported data fields and populate an IPortableDeviceValues collection with their current values. OnGetDataFields is the same method the class extension would call into if a client requested data on demand. Next we set the event type using the event property key. Setting the correct type is important because clients can register to be notified of specific types of events. For example an application may care about a new data event but not a state change event. The sensor and location platform defines several event property keys and types, which can be seen at MSDN. Finally we call into the PostDataEvent helper method to signal the class extension. Here is this method in its entirety.

    1: // Post a data updated event, lines 148 - 170
    2: HRESULT CSampleEvents::PostDataEvent(IPortableDeviceValues* pValues)
    3: {
    4:     HRESULT hr = (NULL == m_spSensorCXT) ? E_UNEXPECTED : S_OK ;
    5:  
    6:     if (SUCCEEDED(hr))
    7:     {
    8:               CComPtr<IPortableDeviceValuesCollection> 
    9:                   spValuesCollection;
   10:         hr = spValuesCollection.CoCreateInstance(
   11:             CLSID_PortableDeviceValuesCollection);
   12:  
   13:         if (SUCCEEDED(hr))
   14:         {
   15:             hr = spValuesCollection->Add(pValues);
   16:  
   17:             if (SUCCEEDED(hr))
   18:             {
   19:                 hr = m_spSensorCXT->PostEvent(
   20:                     g_wszSensorID, spValuesCollection);
   21:             }
   22:         }
   23:     }
   24:  
   25:     return hr;
   26: }

PostDataEvent simply takes the data field values, adds them to an IPortableDeviceValeus collection, and posts the collection to the Sensor Class Extension. The extension will notify appropriate clients of new data.

The Sensor Class Extension also informs a sensor driver of client connection and subscription changes through several methods: OnClientConnect, OnClientDisconnect, On ClientSubscribeToEvents, and OnClientUnsubscribeFromEvents. These enable a driver to adjust its activity accordingly (such as disabling device sampling when no client is connected or adjusting event frequency). For instance, the Time Sensor Sample keeps track of client applications in a Clients list, which it uses to update the driver’s report interval.

To wrap up, these simple additions allow a sensor driver can take advantage of events in the sensor and location platform. This event-driven model can improve performance in both the driver and client applications. For more information about sensor driver events, take a look here. Best of luck!

-- Sensor & Location Platform Team

This posting is provided "AS IS" with no warranties and confers no rights.