README.md
1# Context Hub Peripheral Protocol (CHPP)
2
3The Context Hub Runtime Environment (CHRE) is a feature built into Android which can run background applications on a lower power, always-on processor, with lower energy cost than what is possible when using the main applications processor (AP).
4
5CHPP is designed to run over a serial link (e.g. UART, SPI) and enables an Android Context Hub (CHRE) running on a dedicated low-power processor to connect to peripherals (e.g. GNSS, WiFi). Using CHPP, CHRE can pull together various sources of information, including sensors, location, and audio, to enable a new generation of context-aware applications.
6
7CHPP is a communication protocol that spans from the Transport to the Application layer. The CHPP Transport layer is responsible for correct handling of ARQ, fragmentation, and ordering of datagrams, while the CHPP Application Layer is responsible for the services, including client-service messaging and service discovery.
8
9CHPP is designed to be flexible and future-proof while meeting the memory and processing constraints of both the CHRE and the peripherals that are often even-lower-resourced.
10
11CHPP provides several basic services that are necessary for debugging and service discovery, defines a number of services for the most commonly used sensors and peripherals, and also allows vendor-specific services as necessary. CHPP allows these services to coexist on a single link with very small overhead.
12
13## Integration Quick-Start
14
15A quick-start guide for integration is provided in QUICKSTART.md
16
17## Overview
18
19Within the CHPP transport layer, each endpoint is considered a peer, meaning there are no role differences. However, within the application layer, one endpoint exposes a service to the other endpoint, which is considered to be a client of said service. CHPP is point-to-point, therefore multiple clients to the same service over the same link are not supported. In a typical configuration, the endpoint where CHRE runs will be a client of one or more peripherals that each provide one or more services. For example, CHRE may be running on a microcontroller which has a serial connection to a discrete GNSS (Global Navigation Satellite System) chip that exposes the GNSS CHPP service. However, the protocol is designed such that endpoints can both provide services and serve as clients of remote services simultaneously.
20
21## Error Detection and Correction
22
23CHPP supports checksum based ARQ. CHPP supports implicit NACKs, and optionally supports explicit NACKs. The timeout is implementation dependent with a recommended value of 50 msec.
24
25## Conventions
26
27- Unless otherwise specified, CHPP follows the Little Endian convention.
28- Bit-level diagrams are presented with the most-significant bit occupying the leftmost cell
29- Bits are numbered with 0 being the least significant bit and 7 being the most significant bit in a byte.
30
31# Transport Layer Packetization
32
33CHPP packets consist of a 2-byte preamble (packet start delimiter) and 8 bytes of header information. The header is followed by zero or more bytes of application-layer payload, typically starting with a 6-byte app header, and ends with a 4-byte packet footer. Defined as a structure (ChppTransportHeader in transport.h), the CHPP transport header is as follows:
34
35- Preamble
36
37 - uint16_t preamble;
38
39- Transport Header
40
41 - uint8_t flags;
42 - uint8_t packetCode;
43 - uint8_t ackSeq;
44 - uint8_t seq;
45 - uint16_t length;
46 - uint16_t reserved;
47
48## Preamble
49
50CHPP packets use a two-byte preamble as the packet start delimiter. If the receiving side is not actively within a packet, it assumes a packet starts whenever it sees the preamble. For the current version of CHPP, the preamble is 0x6843 (“Ch” in ASCII as a little endian 16-bit integer). For future versions, e.g. for a non-point-to-point version of CHPP, we expect only the LSB to change.
51
52## Packet Flags
53
54Up to 8 flags are supported as a bitmap as follows
55
56### 0x01: Fragmentation
57
58The fragmentation flag allows the transfer of data messages larger than the MTU. In such cases, the data message would be split into multiple fragments. A fragmentation flag of (0) indicates the last/only packet in a datagram. A fragmentation flag set to (1) indicates that the packet is part of an unfinished, fragmented datagram
59
60### 0x02 - 0x80: Reserved
61
62Reserved for future use
63
64## Packet Codes
65
66The packet code field consists of two nibbles. The lower nibble is used for optional error reporting. The higher nibble is used for transport layer configuration.
67
68### Error Reporting (lower nibble)
69
70Error reporting is a recommended feature and can help with debugging and potentially help improve performance. A non-zero explicit NACK code indicates an explicit NACK. The code provides the reason as follows:
71
72- 0x0: No explicit-NACK
73- 0x1: Checksum failure
74- 0x2: Out of memory
75- 0x3: Busy
76- 0x4: Invalid header
77- 0x5: Out of order packet
78
79### Attributes (higher nibble)
80
81- 0x0: Regular Packet
82- 0x1: Reset. The reset code is used at bootup to indicate that readiness, as well as to reset the state to post-bootup state in case of irrecoverable errors. If set, this indicates that the sending endpoint is requesting initialization of the CHPP protocol. The first packet sent after bootup always has this flag set, and endpoints may send a packet with this flag to attempt to recover from protocol failures. Upon receipt, the endpoint resets all its state, for example dropping any packets awaiting transmission, and resetting its service state. It then responds with a reset-ack.
83 A reset packet may optionally populate the Error Reporting entry with the reason behind the reset.
84 A reset packet has an optional configuration payload [TBD].
85- 0x2 Reset-ack. Similar to reset, but sent as a response to reset, as described above.
86
87## ACK Sequence Number
88
89The ack sequence number provides the next expected packets, effectively acknowledging all packets up to (n-1). The 1-byte ack allows for (optional, future) support of group ACKs (up to a window size of 127 packets). Note that fragmented messages have multiple sequence numbers, one for each fragment.
90The ack may be sent as part of a packet with or without a payload. In the latter case, the payload length would be set to zero.
91If an ACK is not received after a predetermined timeout, or an implicit NACK is received (through an ACK of a lower sequence number), the unacknowledged packet(s) shall be retransmitted.
92
93## Sequence Number
94
95Provides the 8-bit sequence number of this packet. Note that fragmented messages have multiple sequence numbers, one for each fragment.
96
97## Length
98
99Provides the payload length. Devices may have MTU sizes smaller than this limit. Data messages larger than the MTU size can be fragmented according to the Packet Flags: Fragmentation section above.
100A value of 0 indicates no payload, which is useful in cases where only transport layer data is relevant, for example when transmitting a bare acknowledgement message.
101
102## Payload
103
104The optional payload immediately follows a non-zero payload length. Its contents are described in the Application Layer section. It typically begins with an app layer header.
105
106## Checksum
107
108Provides an error detection code that is run over of the entire CHPP packet, i.e. anything between the preamble and the checksum fields.
109The checksum algorithm is [TBD].
110
111# CHPP Transport - Link Layer API
112
113To allow for a clean C implementation with clear separation of layers while supporting multiple CHPP instances per device, each CHPP layer state is stored in its own context struct.
114To tie corresponding transport and application layers together, each layer’s context struct includes a pointer to the context struct of the other corresponding layer (i.e. the transport layer’s context has a pointer to the corresponding app layer’s context struct and vice versa).
115Initializing CHPP involves:
116
1171. Allocating the structs for the application and transport layers (in any order).
1182. Calling the application and transport layers’ initialization functions (in any order)
1193. Initializing the platform-specific link layer parameters within the transport struct.
120
121## void chppTransportInit(\*transportContext, \*appContext)
122
123The CHPP Transport Layer state is stored in the ChppTransportState struct transportContext, and passed around between various functions. It is necessary to initialize the transport layer state for each transport layer instance on every platform.
124Each transport layer instance is associated with a single application layer instance. appContext points to the application layer status struct associated with this transport layer instance.
125After calling chppTransportInit, it is also necessary to separately initialize the platform-specific values of transportContext.linkParams.
126
127## void chppAppInit(\*transportContext, \*appContext)
128
129The CHPP Application Layer state is stored in the ChppAppState struct appContext, and passed around between various functions. It is necessary to initialize the application layer state for each application layer instance on every platform.
130Each application layer instance is associated with a single transport layer instance. transportContext points to the transport layer status struct associated with this application layer instance.
131
132## void chppAppInitWithClientServiceSet(\*transportContext, \*appContext, clientServiceSet)
133
134It is also possible to specify the client/service endpoints to be enabled at runtime.
135
136## bool chppRxDataCb(\*transportContext, \*buf, len)
137
138This function is the interface between the CHPP Transport layer and the communications link’s Rx path (e.g. from the UART driver). This function is called when any data is received at the serial interface. The data is provided through a pointer to *buf, with its length specified as len.
139The return value from chppRxData(*buf, len) can optionally be used at the communications link driver to improve performance. When the return value is true, the driver may stop sending all-zero payloads (e.g. as might happen when a serial link is idle).
140
141## bool chppRxPacketCompleteCb(\*transportContext)
142
143This is an optional function that enables the link layer to indicate the end of a packet. For packets with a corrupt length field, this function can enable the link layer to explicitly NACK the bad packet earlier.
144This function is designed exclusively for link layers that can identify the end of individual packets. The availability of this information depends on the link layer implementation.
145
146## enum ChppLinkErrorCode chppPlatformLinkSend(\*params, \*buf, len)
147
148This function is the interface between the CHPP Transport layer and the communications link’s Tx path (e.g. to the UART driver). This function is called when any data should be sent to the serial interface. The data is provided through a pointer to \*buf, with its length specified as len. The struct params is platform-specific and should include link details and parameters as initialized by the implementation.
149Both synchronous and asynchronous implementations of this function are supported. A synchronous implementation refers to one where chppPlatformLinkSend() is done with buf and len when it returns (i.e. the caller can free or reuse buf and len). An asynchronous implementation refers to one where chppPlatformLinkSend() returns before completely consuming buf and len (e.g. the send is completed at a later time). In this case, it is up to the platform implementation to call chppLinkSendDoneCb() after processing the contents of buf and len.
150This function returns CHPP_LINK_ERROR_NONE_SENT if the platform implementation for this function is synchronous and CHPP_LINK_ERROR_NONE_QUEUED if it is implemented asynchronously. It can also return an error code from enum ChppLinkErrorCode.
151
152## void chppLinkSendDoneCb(\*params)
153
154Notifies the transport layer that the link layer is done sending the previous payload (as provided to platformLinkSend() through buf and len) and can accept more data.
155On systems that implement the link layer Tx asynchronously, where platformLinkSend() returns False before consuming the payload provided to it, the platform implementation must call this function after platformLinkSend() is done with the payload (i.e. buf and len).
156
157## void chppWorkThreadStart(\*transportContext)
158
159Starts the main thread for CHPP's Transport Layer. This thread needs to be started after the Transport Layer is initialized through chppTransportInit() and provided with the transport layer context struct.
160
161## void chppWorkThreadStop(\*transportContext)
162
163Stops the main thread for CHPP's Transport Layer that has been started by calling chppWorkThreadStart(). Stopping this thread may be necessary for testing and debugging purposes. The parameter context provides the transport layer context struct.
164
165# Application Layer Messaging
166
167CHPP Application Layer datagrams typically have a 6-byte header. This is followed by zero or more bytes of application-layer payload. Both the header and payload are counted in the transport layer payload length. The transport layer 4-byte packet footer follows. Defined as a structure, the CHPP transport header looks like this:
168
169- uint8_t handle;
170- uint8_t type;
171- uint8_t transaction;
172- uint8_t reserved
173- uint16_t command;
174
175## Service Handle
176
177The Service Handle provides the capability of running multiple simultaneous clients / services over a single CHPP transport (physical) link. This allows differentiation between traffic destined for different services / applications / sensors on a single link. It also allows both sides to have clients and services simultaneously if necessary. Handles include reserved ones (0x00 - 0x0f) and assignable ones. Assigning a handle is through a handshaking phase on the reserved handle number 0x01. The handshake allows for a wide range of manufacturer IDs, devices, and protocol types/versions to be mapped into an 8-bit handle number to achieve efficiency as well as flexibility.
178
179### Handle
180
181- 0x00: Non-handle based P2P communication
182- 0x01: Loopback testing
183- 0x02 - 0x0e: reserved
184- 0x0f: CHPP service discovery handshake
185- 0x10 - 0xff: Handles for services negotiated through handshake
186
187## Message Type
188
189The message type clarifies the direction of the messages (client <-> service) and whether a response is expected
190
191- 0b00 (0): Request from client. Requires response with same command from service
192- 0b01 (1): Response from service (with the same command / transaction ID as the request)
193- 0b10 (2): Notification from client. Service shall not respond
194- 0b11 (3): Notification from service. Client shall not respond
195
196## Transaction ID
197
198CHPP has an 8-bit transaction ID for out-of-order responses which is optional for clients, and mandatory for services. The Transaction ID allows CHPP to have multiple requests outstanding for not just different commands, but for a single command. To allow multiple outstanding requests, the service shall relay back the Transaction ID of a request in its response. The client shall not issue the same command unless it has either received the response or has changed / incremented the Transaction ID.
199
200## Commands
201
202The CHPP messaging structure allocates 16 bits for commands. CHPP Service Discovery uses the same messaging structure. Note that each vendor and service (as indicated by the Vendor ID and Service ID) can define their own commands and therefore command codes for different services and vendors can overlap.
203
204# CHPP Basic Services
205
206CHPP’s built-in basic services take advantage of reserved handle numbers, ranging from 0x00 - 0x0f to support debugging and development as well as discovery of other services. These basic services currently are as follows.
207
208## Handleless Communication Service (0x00)
209
210The handle 0x00 is reserved for use cases that do not need the flexibility provided by handles and avoid the need for discovery.
211
212## Loopback Testing Service (0x01)
213
214Loopback testing is a mandatory service where the loopback service relays the entire received datagram back to the client.
215The client requesting the loopback must set the handle to 0x01, and the message type to 0 (i.e. request from client). The server responding with the loopback will respond on the same handle but with the message type to 1 (service response). Any (application layer) data following the handle and message type fields will be identically relayed back to the client.
216
217## Discovery Service (0x0f)
218
219Service Discovery is mapps a 8-bit handle to a number of coexisting services. In response to a discovery command, the discovery service responds with a list of available services (UUID + name + version) on the device. The first service in the list corresponds to handle 0x10, and so on.
220
221# CHPP Predefined Service Protocols
222
223CHPP supports the following services using the CHRE PAL. The standard UUIDs for these services are defined in common/standard_uuids.h.
224
225- WWAN
226- WiFi
227- GNSS
228