5.2.6. Driver Data and Events management

5.2.6.1. Introduction

Part of a driver functions is to provide data or to generate events. Access and formats of data, and events configuration or notification are standardized in egos. This to make use of events and data in modules more generic, and also to avoid multiple definitions of the same data in different drivers or modules of the software. This generecity is also a way to make applications more independent from hardware.

Data and Events handling are standardized with the use of generic APIs.

Data and Events formats are standardized with the definition of Data and Events libraries in egos. (See ?????? data & event libraries description) These libraries should only contain abstracted information, not specific to a chip / manufacturer / software...

5.2.6.2. Data management

5.2.6.2.1. Data Ids definitions

When developing a driver, developper must list all data objects which should be provided by the driver to the user of the driver (objects can be either readable, writable or both). And check if these objects are already defined in the libraries or if they should be added.

If already defined in the libraries, developer must ensure that data format in the driver complies with the format defined in the library.

If not defined, data must be added in the library, and its format must be chosen with all its uses in perspective, not only the specific use in the current driver. For example, let's say we must add the speed object in the library, for a driver of a module which provides speed information from 0 to 100 km/h, by increments of 1 km/h. You can define a U8 type for this information, and define the speed object in the library with this type. But this type may not be enough for other modules, which may have a better precision, or/and a bigger range of measures. So the speed object format should probably be defined differently, allowing more possibilities.

5.2.6.2.2. Data access

Two operations possibles on data: GET and/or SET.

5.2.6.2.2.1. Data get

A get operation of a data Id of the driver is done through data get or set messages: - mOSS_MSG__ID( cDATA__API, eDATA__API__GET) + data Id (nData_Id) + optional data

Format of optional data is defined in the library, and depends on the data Id requested.

Driver must answer to this message request with a message: - mOSS_MSG__ID( cDATA__MSG, eDATA__MSG__GET_RESPONSE) + sData_GetSetAnswer + optional data

sData_GetSetAnswer has two fields: - nId (nData_Id): Id of the data read - uResult (uErr_Code): Result of the read operation

Optional data contains the data read (in the format defined in the library) in case of a successful read.

data_GetOKAnswer function from data module can be used to ease answer in case of successful get request:

uErr_Code (data_GetOKAnswer) ( hHandle i_hDest // Dest of answer , nData_Id i_nId // Id of data read , pnU8 i_pData // Pointer to data , nU16 i_nSize // Size of data )

data_GetErrorAnswer function from data module can be used to ease answer in case of unsuccessful get request:

uErr_Code (data_GetErrorAnswer) ( hHandle i_hDest // Dest of answer , nData_Id i_nId // Id of data read , uErr_Code i_uError // Error code )

5.2.6.2.2.1.1. Data get code sample

Below a code example of data get handling in an accelerometer driver. This management should be placed in the main message loop of the driver process.

    mOSS_MSG__RECEIVE()
    {
            // Other cases of the driver (APIs, internal messages...)
            // case ...

            case mOSS_MSG__ID( cDATA__API, eDATA__API__GET):
            {
                    switch (mDATA__ID_FROM_API_MSG())
                    {
                            // All data Ids accessible in this driver should be handled below

                            case mDATA__ID(cDATA_TYPE__IMU, eDATA_IMU__ATTRIBUTE__ACCELERATION):
                            {
                                    // The handling of data retrieve is not the purpose of this document. Let's asssume a function retrieves the data requested and stores it in the chest
                                    // Check of optional data in the message can be necessary for some data Id with parameters (not in this example)
                                    l_uResult
                                    =       drv_imu_acc__AccRead
                                            ( &(mpDRV_IMU_ACC__CHEST()->sAccData)
                                            );

                                    if (cERR__CODE__OK._ == l_uResult._)
                                    {
                                            (data_GetOKAnswer)
                                            ( mOSS_MSG__SENDER()
                                            , mDATA__ID_FROM_API_MSG()
                                            , (pnU8)&(mpDRV_IMU_ACC__CHEST()->sAccXYZout)
                                            , sizeof(sDataImu_Acceleration)
                                            );
                                    }
                                    else
                                    {
                                            // Read failed
                                            (data_GetErrorAnswer)
                                            ( mOSS_MSG__SENDER()
                                            , mDATA__ID_FROM_API_MSG()
                                            , cERR__CODE__DATA_GET_ERROR
                                            );
                                    }
                            }
                            break;

                            default:
                            {
                                    // In case the Data ID is not handled in this driver, answer with a Get Error message (cERR__CODE__DATA_GET_UNHANDLED)

                                    (data_GetErrorAnswer)
                                    ( mOSS_MSG__SENDER()
                                    , mDATA__ID_FROM_API_MSG()
                                    , cERR__CODE__DATA_GET_UNHANDLED
                                    );
                            }       break;
                    }
            }       break;
    }
    mOSS_MSG__LOOP()

5.2.6.2.2.2. Data set

A get operation of a data Id of the driver is done through data get or set messages: - mOSS_MSG__ID( cDATA__API, eDATA__API__SET) + data Id (nData_Id) + data

Format of data is defined in the library, and depends on the data Id to be set.

Driver must answer to this message request with a message: - mOSS_MSG__ID( cDATA__MSG, eDATA__MSG__SET_RESPONSE) + sData_GetSetAnswer

sData_GetSetAnswer has two fields: - nId (nData_Id): Id of the data read - uResult (uErr_Code): Result of the set operation

data_SetAnswer function from data module can be used to ease answer for set request:

uErr_Code (data_SetAnswer) ( hHandle i_hDest // Dest of answer , nData_Id i_nId // Id of data set , uErr_Code i_uError // Result of set )

5.2.6.2.2.2.1. Data set code sample

Below a code example of data set handling. This management should be placed in the main message loop of the driver process.

    mOSS_MSG__RECEIVE()
    {
            // Other cases of the driver (APIs, internal messages...)
            // case ...

            case mOSS_MSG__ID( cDATA__API, eDATA__API__SET):
            {
                    switch (mDATA__ID_FROM_API_MSG())
                    {
                            // All data Ids which can be set in this driver should be handled below

                            case mDATA__ID(cDATA_TYPE__AAA, eDATA_AAA__ATTRIBUTE__BBB):
                            {
                                    // The handling of data set in the driver is not the purpose of this document. Let's asssume a function sets the concerned data.
                                    l_uResult
                                    =       drv_XXX__SetBBB
                                            ( mpDATA__DATA_FROM_MSG()       // These macro points on the data to be set
                                            );

                                    if (cERR__CODE__OK._ == l_uResult._)
                                    {
                                            // Set successful
                                            (data_SetAnswer)
                                            ( mOSS_MSG__SENDER()
                                            , mDATA__ID_FROM_API_MSG()
                                            , cERR__CODE__DATA_SET_OK
                                            );
                                    }
                                    else
                                    {
                                            // Set failed
                                            (data_SetAnswer)
                                            ( mOSS_MSG__SENDER()
                                            , mDATA__ID_FROM_API_MSG()
                                            , cERR__CODE__DATA_SET_ERROR
                                            );
                                    }
                            }
                            break;

                            default:
                            {
                                    // In case the Data ID is not handled in this driver, answer with a Set Error message (cERR__CODE__DATA_SET_UNHANDLED)

                                    (data_SetAnswer)
                                    ( mOSS_MSG__SENDER()
                                    , mDATA__ID_FROM_API_MSG()
                                    , cERR__CODE__DATA_SET_UNHANDLED
                                    );
                            }       break;
                    }
            }       break;
    }
    mOSS_MSG__LOOP()

5.2.6.3. Events management

5.2.6.3.1. Events Ids definitions

As for data, developper must list all events which should be provided by the driver to the user of the driver , and check if these events are already defined in the libraries or if they should be added.

Same attention to genericity of events should be paid when adding them in the library.

All the events available in the driver must be listed in a constant table. Example:

cnEvt_Id    g__acnDrvXxx_Events[]
=   { mEVT__ID(cEVT_TYPE__AAA, eEVT_AAA__ATTRIBUTE__ATTR1)
    , mEVT__ID(cEVT_TYPE__AAA, eEVT_AAA__ATTRIBUTE__ATTR5)
    , mEVT__ID(cEVT_TYPE__CCC, eEVT_CCC__ATTRIBUTE__ATTR2)
    };
As you see, you can integrate events from different categories (types) of the library, and only some attributes of each categories.

And a constant EventsList structure (sEvt_Eventslist) must be defined with its information. Example:

csEvt_Eventslist    g__csDrvXxx_EventsList
=   { g__acnDrvXxx_Events
    , __DIM(g__acnDrvXxx_Events)
    };

5.2.6.3.2. Events subscription

To manage events subscriptions, driver must store a subscribers list. An element of type psEvt_Suscriber must be available in the driver, preferably in the chest.

Example in the chest:

DECL_TYPEDEF(struct, sDrvXxx_Chest)
{
// (...)

// Events management
;   psEvt_Suscriber         psSuscribersList                                                = NULL                                                          // Suscribers list
;}  DECL_INSTANCE(struct, sDrvXxx_Chest);

To enable subscriptions to its events, a driver must handle subscription message: - mOSS_MSG__ID(cEVT__API, eEVT__API__SUBSCRIBE) + event Id (nEvt_Id) + optional data

The subscription is automatically managed by calling evt_SubscribeAdd macro, with these parameters: - .hSub: Handle of the subscriber - .nId: Event Id - .pcsEventsList: Pointer to the EventsList structure - .ppsSubscriberList: Pointer to the subscribers list

This macro will automatically find the subscriber information in its subscribers list (and create it if this subscriber is not yet in the list), and add the EventId (if supported by this driver) in the events subscribed for this subscriber.

The driver must answer with this message: - mOSS_MSG__ID(cEVT__MSG, eEVT__MSG__SUBSCRIBE_RESPONSE) + subscribe result (uErr_Code)

5.2.6.3.2.1. Events subscription code sample

Below a code example of events subscription. This management should be placed in the main message loop of the driver process.

    mOSS_MSG__RECEIVE()
    {
            // Other cases of the driver (APIs, internal messages...)
            // case ...

            case mOSS_MSG__ID(cEVT__API, eEVT__API__SUBSCRIBE):
            {
                    l_uResult
                    =       evt_SubscribeAdd
                            ( .hSub                                 = mOSS_MSG__SENDER()
                            , .nId                                  = mEVT__EVT_ID_FROM_MSG()
                            , .pcsEventsList                = &g__csDrvXxx_EventsList
                            , .ppsSubscriberList    = &mpDRV_XXX__CHEST()->psSuscribersList
                            );

                    (void)mOSS_MSG__REPLY_DATA
                    ( mOSS_MSG__ID(cEVT__MSG, eEVT__MSG__SUBSCRIBE_RESPONSE)
                    , (pnU8)&l_uResult
                    , sizeof(uErr_Code)
                    );
            }       break;
    }
    mOSS_MSG__LOOP()

5.2.6.3.3. Events unsubscription

Subscribers can unsubscribe to events with this message: - mOSS_MSG__ID(cEVT__API, eEVT__API__UNSUBSCRIBE) + event Id (nEvt_Id) + optional data

The unsubscription is automatically managed by calling evt_SubscribeRemove macro, with these parameters: - .hSub: Handle of the subscriber - .nId: Event Id - .pcsEventsList: Pointer to the EventsList structure - .ppsSubscriberList: Pointer to the subscribers list

This macro will automatically find the subscriber information in its subscribers list, and remove the EventId in the events subscribed for this subscriber.

The driver must answer with this message: - mOSS_MSG__ID(cEVT__MSG, eEVT__MSG__UNSUBSCRIBE_RESPONSE) + unsubscribe result (uErr_Code)

5.2.6.3.3.1. Events unsubscription code sample

Below a code example of events unsubscription. This management should be placed in the main message loop of the driver process.

    mOSS_MSG__RECEIVE()
    {
            // Other cases of the driver (APIs, internal messages...)
            // case ...

            case mOSS_MSG__ID(cEVT__API, eEVT__API__UNSUBSCRIBE):
            {
                    l_uResult
                    =       evt_SubscribeRemove
                            ( .hSub                                 = mOSS_MSG__SENDER()
                            , .nId                                  = mEVT__EVT_ID_FROM_MSG()
                            , .pcsEventsList                = &g__csDrvXxx_EventsList
                            , .ppsSubscriberList    = &mpDRV_XXX__CHEST()->psSuscribersList
                            );

                    (void)mOSS_MSG__REPLY_DATA
                    ( mOSS_MSG__ID(cEVT__MSG, eEVT__MSG__UNSUBSCRIBE_RESPONSE)
                    , (pnU8)&l_uResult
                    , sizeof(uErr_Code)
                    );
            }       break;
    }
    mOSS_MSG__LOOP()

5.2.6.3.4. Events notification

When an event managed by the driver occurs, the driver must notify all subscribers which have subscribed to this message with a message.

The message to send to subscribers is: - - mOSS_MSG__ID(cEVT__MSG, eEVT__MSG__NOTIFICATION) + optional data

But the notification can be handled automatically by calling evt_ListNotify macro, with these parameters: - .nId: Event Id to be notified - .pcsEventsList: Pointer to the EventsList structure - .ppsSubscriberList: Pointer to the subscribers list

This macro will automatically browse the list of subscribers and send them notification message if they subscribed to the event Id.

    evt_ListNotify
    ( .nId                                  = mEVT__ID(cEVT_TYPE__AAA, eEVT_AAA__ATTRIBUTE__ATTR5)
    , .pcsEventsList                = &g__csDrvXxx_EventsList
    , .ppsSubscriberList    = &mpDRV_XXX__CHEST()->psSuscribersList
    );