# Messages

The Qualcomm® sensing hub (QSH) framework uses a unified communication model based on protocol buffer-encoded messages, data streams, and sensor unique identifiers (SUIDs). This model is the shared contract used by both client applications on the application processor and sensor drivers and algorithms on the low-power processor.

Note

The `.proto` files define the message schemas used by both sides. Client applications use them to encode requests sent by means of `sendRequest()`. Driver and algorithm authors use them to define what their sensor accepts and emits.

## Communication among sensors

Within the QSH framework, every sensor driver and algorithm is treated as a sensor. This means that inter-sensor communication, such as a step-counter algorithm consuming accelerometer data or a tilt-to-wake algorithm consuming gyroscope data, uses the same request and event message model as client applications on the application processor.

All communication to, from, and among sensors is performed through request and event messages over data streams. Message payloads are encoded in the protocol buffer format using the nanopb generator, encoder, and decoder. The QSH framework manages the payload length, message ID, and timestamp metadata for every message.

The following figure shows the communication between a data client and a data source over a data stream:

<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 812 256" aria-label="Figure : Sensor communication between data client and data source" svgdefaultwidth="80%">
  <!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8)  -->
  <defs>
    <style>.svg-1 .st0,.svg-1 .st1 { fill: #fff }
.svg-1 .st0,.svg-1 .st2,.svg-1 .st3,.svg-1 .st4 { isolation: isolate }
.svg-1 .st0,.svg-1 .st2,.svg-1 .st4 { font-family: Roboto-Regular, Roboto; font-size: 15.7px }
.svg-1 .st1,.svg-1 .st5,.svg-1 .st6,.svg-1 .st7 { stroke-miterlimit: 10 }
.svg-1 .st1,.svg-1 .st5,.svg-1 .st7 { stroke: #d2d7e1 }
.svg-1 .st1,.svg-1 .st7 { stroke-width: 1.5px }
.svg-1 .st5,.svg-1 .st6 { stroke-width: 2px }
.svg-1 .st5,.svg-1 .st7 { fill: #fafafa }
.svg-1 .st6 { fill: none; stroke: #000 }
.svg-1 .st4 { letter-spacing: 0em }
.svg-1 .st8 { fill: #040a40 }</style>
  </defs>
  <rect class="st5" x="1" y="1" width="810" height="254" rx="4" ry="4"></rect>
  <rect class="st8" x="689.8" y="216.4" width="19.6" height="19.6" rx="1.4" ry="1.4"></rect>
  <rect class="st1" x="18" y="17.5" width="776" height="182" rx="4" ry="4"></rect>
  <rect class="st7" x="30.2" y="83.7" width="281.7" height="104.4" rx="4" ry="4"></rect>
  <g>
    <rect class="st8" x="137.4" y="99.3" width="154.6" height="73.2" rx="4" ry="4"></rect>
    <g class="st3">
      <text class="st0" transform="translate(204.8 131.1)"><tspan x="0" y="0">PB</tspan></text>
      <text class="st0" transform="translate(159.1 149.9)"><tspan x="0" y="0">Encode/Decode</tspan></text>
    </g>
  </g>
  <g class="st3">
    <text class="st2" transform="translate(66.6 131.1)"><tspan x="0" y="0">Data</tspan></text>
    <text class="st2" transform="translate(62.9 149.9)"><tspan x="0" y="0">client</tspan></text>
  </g>
  <g>
    <g>
      <g>
        <line class="st6" x1="440.4" y1="109.5" x2="492.1" y2="109.5"></line>
        <polygon points="490.5 115 500 109.5 490.5 104 490.5 115"></polygon>
      </g>
      <line class="st6" x1="313.1" y1="109.5" x2="371.6" y2="109.5"></line>
      <g class="st3">
        <text class="st2" transform="translate(377.5 114.1)"><tspan x="0" y="0">Request</tspan></text>
      </g>
    </g>
    <g>
      <line class="st6" x1="430.4" y1="162.3" x2="500" y2="162.3"></line>
      <g>
        <line class="st6" x1="319.9" y1="162.3" x2="381.6" y2="162.3"></line>
        <polygon points="321.5 167.8 312 162.3 321.5 156.8 321.5 167.8"></polygon>
      </g>
      <g class="st3">
        <text class="st4" transform="translate(386.9 166.9)"><tspan x="0" y="0">E</tspan></text>
        <text class="st2" transform="translate(395.6 166.9)"><tspan x="0" y="0">vent</tspan></text>
      </g>
    </g>
  </g>
  <g class="st3">
    <text class="st2" transform="translate(362.8 40.2)"><tspan x="0" y="0">Data stream</tspan></text>
    <text></text>
  </g>
  <rect class="st7" x="500" y="83.7" width="281.7" height="104.4" rx="4" ry="4"></rect>
  <g>
    <rect class="st8" x="515.6" y="99.3" width="154.6" height="73.2" rx="4" ry="4"></rect>
    <g class="st3">
      <text class="st0" transform="translate(583.1 131.1)"><tspan x="0" y="0">PB</tspan></text>
      <text class="st0" transform="translate(537.3 149.9)"><tspan x="0" y="0">Encode/Decode</tspan></text>
    </g>
  </g>
  <g class="st3">
    <text class="st2" transform="translate(714.1 131.1)"><tspan x="0" y="0">Data</tspan></text>
    <text class="st2" transform="translate(706 149.9)"><tspan x="0" y="0">source</tspan></text>
  </g>
  <text class="st2" transform="translate(717.3 230.7)"><tspan x="0" y="0">Third-party</tspan></text>
  <g>
    <polyline class="st6" points="171.1 75.1 171.1 48.8 640.9 48.8 640.9 75.1"></polyline>
    <polygon points="177.1 73.4 171.1 83.7 165.1 73.4 177.1 73.4"></polygon>
    <polygon points="634.9 73.4 640.9 83.7 646.9 73.4 634.9 73.4"></polygon>
  </g>
</svg>

**Figure: Sensor communication between data client and data source**

As shown in the figure:

- Client to Sensor (request): The client sends request messages to enable, disable, or reconfigure a sensor. Every request targets a specific SUID. The client manager validates the request and routes it to the target sensor, which passes it to the appropriate sensor instance for handling.
- Sensor to Client (event): Sensor instances send event messages asynchronously back to their registered clients. Clients can be application-processor apps or other sensors and algorithms running on the low-power processor. Events are triggered by new sensor data, configuration changes, flush completions, or errors.

The following sequence diagram shows the full message lifecycle between a client application, the client manager, and a sensor or driver:

![%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', 'primaryBorderColor': '#000000', 'lineColor': '#000000', 'textColor': '#000000', 'noteBkgColor': '#f5f5f5', 'activationBkgColor': '#f5f5f5'}}}%%
sequenceDiagram
    participant App as Client Application
    participant CM as Client Manager
    participant S as Sensor / Driver
    App-&gt;&gt;CM: sns_client_request_msg(SUID, msg_id, payload)
    CM--&gt;&gt;App: sns_client_resp_msg (ack)
    CM-&gt;&gt;S: Client request
    S--&gt;&gt;CM: sensor event data
    CM--&gt;&gt;App: sns_client_event_msg(SUID, timestamp, payload)](data:image/png;base64,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)

QSH message lifecycle

The following sections describe the message types exchanged between the client application, the client manager, and the sensor.

### Client messages

The client application interacts with the QSH framework through three message types:

1. Sends a `sns_client_request_msg` request message through the `sendRequest()` API. The payload field of this message carries a protocol buffer-encoded, sensor-specific request.
2. Receives a `sns_client_resp_msg` response message. The client manager sends this acknowledgment immediately after receiving the request. It confirms that the request was correctly encoded and that the destination SUID is reachable. Minimal processing is performed at this stage.
3. Receives one or more `sns_client_event_msg` event messages using the callback registered with `setCallback()`. Each event message belongs to a single SUID. If a client has active requests on multiple SUIDs, events for each SUID are delivered in separate messages. A single event message can carry one or more sensor samples.

## Request message fields

All requests to the client manager use `sns_client_request_msg` as the outermost protocol buffer message. This message has the following fields:

- SUID: The destination address of the request. The client manager rejects any request sent to an invalid or unavailable SUID.
- msg\_id: A numeric identifier that tells the destination sensor how to interpret the encoded payload. Message IDs are unique within a sensor, but two different sensors may use the same ID for different message types. For example:

    - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG`: Standard streaming request from a client to a sensor.
    - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT`: Standard sensor event from a data source sensor.
- Request (`sns_std_request`): The information package sent to the sensor. The `sns_std_request::payload` field carries the sensor-specific configuration, encoded as a protocol buffer message corresponding to the `msg_id`. For details, see the sensor-specific `.proto` file.
- Resampler configuration (optional): Controls the rate at which the client receives sensor data. Use one of the following options:

    - `SNS_RESAMPLER_RATE_FIXED`: Deliver data at an exact rate. For example, if the client requests 200 Hz but the sensor runs at 240 Hz, samples are interpolated down to 200 Hz.
    - `SNS_RESAMPLER_RATE_MINIMUM`: Deliver data at no less than the requested rate. For example, if the client requests 200 Hz but the sensor runs at 240 Hz, samples are delivered at 240 Hz.
- Threshold configuration (optional): Filters events so the client only receives data when a condition is met. The following threshold types are supported:

    - `SNS_THRESHOLD_TYPE_RELATIVE_VALUE`: Triggers when the delta between the current value and the last reported value exceeds the configured threshold.
    - `SNS_THRESHOLD_TYPE_RELATIVE_PERCENT`: Triggers when the difference between the current and last reported value exceeds a percentage of the last reported value.
    - `SNS_THRESHOLD_TYPE_ABSOLUTE`: Triggers when the current value crosses a fixed threshold.
    - `SNS_THRESHOLD_TYPE_ANGLE`: Triggers when the angle between the current and last reported quaternion exceeds the configured threshold, in radians. Applies to quaternion sensors only.
- Suspend configuration (optional): Controls system behavior when the client processor suspends. It has the following sub-fields:

    - `client_proc_type`: Identifies the processor where the client runs. A flush request from any client on this processor causes all clients on that processor to receive a flush.
    - `delivery_type`: Specifies whether events are delivered while the processor is suspended:

        - `SNS_STD_DELIVERY_WAKEUP`: Delivers events as they become available, regardless of processor state. If the requested `batch_period` exceeds system capacity, data is sent when the buffer is full. The `flush_period` is effectively ignored with this option.
        - `SNS_STD_DELIVERY_NO_WAKEUP`: Holds events while the processor is suspended and delivers all pending events when the processor resumes.
    - `nowakeup_msg_ids`: A list of message IDs that must not wake the client processor. These messages are only delivered if other wake-up-capable events are already being sent.

    For the full field reference, see `<workspace>/build-qcom-wayland/workspace/sources/sensinghub/sensing-hub/apis/proto/sns_client.proto`, where `<workspace>` is your working directory.

## Batching

Within `sns_client_request_msg::sns_std_request`, the client can control how and when data is delivered using the following batching fields:

- `batching::batch_period`: Maximum time in microseconds between data deliveries. All events generated since the last delivery are held until this timer fires. In concurrency scenarios, events may be delivered sooner. A flush request overrides this timer immediately. Batching is disabled by default (`batch_period = 0`).
- `batching::flush_period`: A hint to the client manager and physical sensor about how much historical data to retain, in microseconds. Data older than this value may be dropped. If not set, defaults to `batch_period`, meaning only one batch is retained. When set, `flush_period` must be greater than or equal to `batch_period`.
- `batching::flush_only`: If `True`, the client manager delivers events only when the client explicitly sends a flush request. Otherwise, batching continues until `flush_period` is reached, at which point the oldest data is dropped.
- `batching::max_batch`: If `True`, directs the sensor to use its maximum hardware batching capacity. If both `flush_only` and `max_batch` are `True`, `flush_only` takes precedence.

## Event message fields

All events delivered to the client use `sns_client_event_msg` as the outermost protocol buffer message. This message is carried inside the payload field of `sns_client_report_ind_msg`, which is the transport-level indication wrapper. The `sns_client_event_msg` message has the following fields:

- SUID: Identifies the data source that generated the event. If a client has active requests on multiple SUIDs, each SUID’s events are delivered in a separate `sns_client_event_msg` message.
- `events::msg_id`: Identifies the type of event and uses the same numeric ID space as requests — it tells the client which proto message to use when decoding the payload.
- `events::timestamp`: The time the event occurred, in QTimer clock ticks. For sensor data events, this is the time the physical sample was captured in hardware. For framework-generated events (configuration updates, errors, flush completions), this is the time the event was created.
- `events::payload`: The encoded event data. Decode this field using the sensor-specific proto buffer corresponding to the `msg_id`.

Events are generated in the following situations:

- New sensor data is available at the configured sample rate or batch period.
- A sensor configuration change is processed (`SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_PHYSICAL_CONFIG_EVENT`).
- A flush request completes (`SNS_STD_MSGID_SNS_STD_FLUSH_EVENT`).
- An error occurs in the sensor, sensor instance, or framework (`SNS_STD_MSGID_SNS_STD_ERROR_EVENT`).

## Message payloads

The sensor-specific content of a request or event is carried in the `payload` field of `sns_std_request` and `sns_client_event`, respectively. These fields contain a protocol buffer-encoded message whose structure is defined by the `msg_id`. The field may also be empty if the message type carries no additional data.

Clients use the `.proto` file for the sensor they’re communicating with. Each sensor type has a corresponding `.proto` file. For example, `sns_accel.proto` describes how to enable an accelerometer stream. Every sensor publishes its list of `.proto` files as part of its attributes.

- Data types: Each sensor advertises a data type attribute. A data type maps to a unique set of `.proto` files that define the sensor-specific API. All sensors of the same type must support a minimum set of request and event messages, and may define additional optional messages specific to their implementation.
- Standardized messages: The following Qualcomm-defined messages can be sent to any sensor. They’re defined in the `sns_std.proto` file.

    - `SNS_STD_MSGID_SNS_STD_ATTR_REQ`: Queries a sensor for its published attributes. The sensor responds with an `SNS_STD_MSGID_SNS_STD_ATTR_EVENT` containing all attributes.

        - `sns_std_attr_req::register_updates`: If `True`, the client receives an `sns_std_attr_event` notification whenever the sensor’s attributes change.
        - `sns_std_attr_event::attributes`: The list of all attributes published by the sensor, returned in response to `sns_std_attr_req` or on an attribute change.
    - `SNS_STD_MSGID_SNS_STD_FLUSH_REQ`: Forces all batched data from this sensor to be immediately delivered to the client. This flushes both hardware buffers (for example, the physical FIFO on an accelerometer) and any data held by the client manager. For algorithm sensors such as game rotation vector (GRV), this also flushes the FIFOs of all underlying physical sensors (accelerometer, gyroscope).
    - `SNS_CLIENT_MSGID_SNS_CLIENT_DISABLE_REQ`: Cancels the active request for this sensor. For example, if the client previously sent `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG` to enable accelerometer streaming, sending `DISABLE_REQ` stops the stream for this client.
    - `SNS_STD_MSGID_SNS_STD_FLUSH_EVENT`: Sent by the sensor in response to a flush request. Indicates that all data corresponding to the flush has been delivered and no further flush events follow.
    - `SNS_STD_MSGID_SNS_STD_ERROR_EVENT`: An error event generated by a sensor, sensor instance, or the framework.

    For the full message reference, see `<workspace>/build-qcom-wayland/workspace/sources/sensinghub/sensing-hub/apis/proto/sns_client.proto`.
- Standardized sensor messages: In addition to the messages above, the following Qualcomm-recommended messages apply to standard sensors. These are optional; you can define your own request and event messages instead. They’re defined in `sns_std_sensor.proto`:

    - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG`: Enables streaming for physical sensors (accelerometer, gyroscope, magnetometer) and some algorithm sensors (rotation vector, gravity, linear acceleration).
    - `SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG`: Enables streaming for on-change sensors such as proximity, ambient light, and step detect.
    - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_PHYSICAL_CONFIG_EVENT`: Sent by physical sensors after processing a client request. Indicates the actual operating parameters, such as the sample rate the sensor produces.
    - `SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT`: A data sample produced by the sensor in response to an active streaming request.
- SUID lookup: Before sending any request, a client must know the SUID of the target sensor. The SUID lookup sensor provides this. A client sends an `sns_suid_req` message specifying a data type string (for example, `accel`), and receives back all matching SUIDs. An empty data type string returns all SUIDs on the system.

    The SUID lookup sensor has a fixed, well-known SUID published in `sns_suid.proto`.

    If the client wants to be notified when new sensors of a given type become available, it sets the `register_updates` field to `True`. After receiving SUIDs, the client can send an `sns_std_attr_req` to each SUID to inspect attributes and select the most appropriate sensor.

    The `sns_suid_req` message has the following fields. For more information, see the `sns_suid.proto` file and example code.

Table : SUID request

    | Field | Mandatory or optional | Data type | Description |
    | --- | --- | --- | --- |
    | `data_type` | Mandatory | String | Data type of the sensor to query, for example `accel` or `gyro`. |
    | `register_updates` | Optional | Boolean | If `True`, the client receives a new SUID event whenever a sensor advertising this data type becomes available or unavailable. |
    | `default_only` | Optional | Boolean | Controls which SUIDs are returned:<br><ul class="simple"><br><li><p>If <code class="docutils literal notranslate"><span class="pre">True</span></code> and a default sensor is explicitly configured for the data type, only that sensor’s SUID is returned. If no default is configured, the SUID of the first matching sensor is returned.</p></li><br><li><p>If <code class="docutils literal notranslate"><span class="pre">False</span></code>, all SUIDs matching the data type are returned as they become available.</p></li><br></ul> |

## Sensor attributes

Every sensor publishes a list of attributes identified by a numeric ID. Attributes describe the sensor’s capabilities, operating parameters, and the range of values it accepts. A client queries attributes using `SNS_STD_MSGID_SNS_STD_ATTR_REQ` and receives them in an `SNS_STD_MSGID_SNS_STD_ATTR_EVENT` response.

The following table lists the standard sensor attributes:

Table : Sensor attribute

| Attribute ID | Attribute name | Required? | Data type | Description |
| --- | --- | --- | --- | --- |
| 0 | `SNS_STD_SENSOR_ATTRID_NAME` | Yes | String | Human-readable sensor name. |
| 1 | `SNS_STD_SENSOR_ATTRID_VENDOR` | Yes | String | Human-readable vendor name. |
| 2 | `SNS_STD_SENSOR_ATTRID_TYPE` | Yes | String | The data type used by this sensor, as defined in the sensor proto file. |
| 3 | `SNS_STD_SENSOR_ATTRID_AVAILABLE` | Yes | Boolean | Indicates whether this sensor is currently available to clients. |
| 4 | `SNS_STD_SENSOR_ATTRID_VERSION` | Yes | Integer | 64-bit integer representing the sensor driver version as `major[31:16].minor[15:8].revision[7:0]`. For example: major `0x0002`, minor `0x00`, revision `0x36` gives `DRIVER_VERSION 0x00020036`. |
| 5 | `SNS_STD_SENSOR_ATTRID_API` | Yes | String | List of `.proto` filenames used by this sensor. Additional proto dependencies are specified as imports within those files. Used primarily for test automation. |
| 6 | `SNS_STD_SENSOR_ATTRID_RATES` | No | Float | List of sample rates supported by the sensor, in Hz. |
| 7 | `SNS_STD_SENSOR_ATTRID_RESOLUTIONS` | No | Float | List of sample resolutions supported by the sensor. |
| 8 | `SNS_STD_SENSOR_ATTRID_FIFO_SIZE` | No | Integer | Supported FIFO depth, in number of samples. |
| 9 | `SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT` | No | Integer | Array of active current draw values, in µA. |
| 10 | `SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT` | No | Integer | Inactive (sleep) current draw, in µA. |
| 11 | `SNS_STD_SENSOR_ATTRID_RANGES` | No | Float | Supported operating measurement ranges. |
| 12 | `SNS_STD_SENSOR_ATTRID_OP_MODES` | No | String | Operating modes supported by the sensor, for example `[LPM, HIGH_PERF, NORMAL, OFF]`. |
| 13 | `SNS_STD_SENSOR_ATTRID_DRI` | No | Boolean | Interrupt type supported: `True` = data ready interrupt (DRI); `False` = in-band interrupt (IBI). |
| 14 | `SNS_STD_SENSOR_ATTRID_STREAM_SYNC` | No | Boolean | Indicates whether the sensor supports synchronized streaming. |
| 15 | `SNS_STD_SENSOR_ATTRID_EVENT_SIZE` | No | Integer | Size in bytes of the protocol-buffer-encoded data event produced by this sensor. Used by the HAL to determine maximum batching capacity. |
| 16 | `SNS_STD_SENSOR_ATTRID_STREAM_TYPE` | Yes | Integer | Streaming type: `0` = continuous periodic, `1` = on-change, `2` = one-shot. |
| 17 | `SNS_STD_SENSOR_ATTRID_DYNAMIC` | No | Boolean | `True` if the sensor can connect or disconnect at runtime. |
| 18 | `SNS_STD_SENSOR_ATTRID_HW_ID` | No | Integer | Hardware identifier used to distinguish multiple sensors of the same type. |
| 19 | `SNS_STD_SENSOR_ATTRID_RIGID_BODY` | No | Integer | Physical location of the sensor: `0` = display side, `1` = keyboard side, `2` = external device. |
| 21 | `SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR` | No | Boolean | `True` if this is a physical sensor; `False` if it is a virtual (algorithm) sensor. |
| 22 | `SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR_TESTS` | No | Integer | List of supported physical sensor self-tests, using enum values from `sns_physical_sensor_test_type`. |
| 23 | `SNS_STD_SENSOR_ATTRID_SELECTED_RESOLUTION` | No | Float | Active measurement resolution for each configured dynamic range value. |
| 24 | `SNS_STD_SENSOR_ATTRID_SELECTED_RANGE` | No | Float[2] | Active dynamic range. For the default value, see the sensor hardware requirement specification from the vendor. |
| 25 | `SNS_STD_SENSOR_ATTRID_ADDITIONAL_LOW_LATENCY_RATES` | No | Float | Additional sample rates available for low-latency dedicated clients, in Hz. These extend the rates in `SNS_STD_SENSOR_ATTRID_RATES` and may impact system performance if used by non-dedicated clients. |
| 26 | `SNS_STD_SENSOR_ATTRID_PASSIVE_REQUEST` | No | Boolean | `True` if the sensor supports passive requests. If `False`, all requests are treated as active. |
| 29 | `SNS_STD_SENSOR_ATTRID_TRANSPORT_MTU_SIZE` | No | Integer | Maximum transmission unit (MTU) size for a transport sensor, in bytes. |
| 30 | `SNS_STD_SENSOR_ATTRID_HLOS_INCOMPATIBLE` | No | Boolean | `True` if the sensor is not compatible with the HLOS specification for its data type. |
| 31 | `SNS_STD_SENSOR_ATTRID_SERIAL_NUM` | No | String | Sensor serial number. |
| 32 | `SNS_STD_SENSOR_ATTRID_TECH_USED` | No | Integer array | Technologies used by this sensor. For the list of values, see `sns_tech` in `sns_std_type.proto`. |

Note

Attribute ID 20 is reserved and not currently assigned.

For more information, see the `sns_std_sensor.proto` file and example code. Proto files are located in the `/etc/sensors/proto/` directory on the device.

### Protocol buffers

The QSH client request and event messages are opaque memory buffers containing protocol buffer-encoded payloads. Clients can generate these messages in any language supported by the nanopb library, encode them into a byte stream, and copy that stream into the `sns_client_request_msg` payload field. Similarly, clients extract the payload from `sns_client_report_ind_msg` and decode it using the appropriate `.proto` definition.

For more information, see [Protocol Buffers](https://developers.google.com/protocol-buffers/) and [nanopb](https://github.com/nanopb/nanopb).

**Next steps**

- [Features](https://docs.qualcomm.com/doc/80-80022-7/topic/supported_features.html#features)

Last Published: May 07, 2026

[Previous Topic
Architecture](https://docs.qualcomm.com/bundle/publicresource/80-80022-7/topics/architecture.md) [Next Topic
Features](https://docs.qualcomm.com/bundle/publicresource/80-80022-7/topics/supported_features.md)