1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CHPP_TRANSPORT_H_
18 #define CHPP_TRANSPORT_H_
19 
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 
24 #include "chpp/condition_variable.h"
25 #include "chpp/link.h"
26 #include "chpp/macros.h"
27 #include "chpp/mutex.h"
28 #include "chpp/notifier.h"
29 #include "chpp/transport_signals.h"
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /************************************************
36  *  Public Definitions
37  ***********************************************/
38 
39 /**
40  * CHPP Transport layer reset timeout in ns. The transport layer will attempt
41  * another reset if the previous reset is not acked in time.
42  */
43 #ifndef CHPP_TRANSPORT_RESET_TIMEOUT_NS
44 #define CHPP_TRANSPORT_RESET_TIMEOUT_NS \
45   (UINT64_C(1500) * CHPP_NSEC_PER_MSEC)  // 1500 ms
46 #endif
47 
48 /**
49  * CHPP Transport layer timeout for tx packets.
50  */
51 #ifndef CHPP_TRANSPORT_TX_TIMEOUT_NS
52 #define CHPP_TRANSPORT_TX_TIMEOUT_NS \
53   (UINT64_C(100) * CHPP_NSEC_PER_MSEC)  // 100 ms
54 #endif
55 
56 /**
57  * CHPP Transport layer timeout for rx packets.
58  */
59 #ifndef CHPP_TRANSPORT_RX_TIMEOUT_NS
60 #define CHPP_TRANSPORT_RX_TIMEOUT_NS \
61   (UINT64_C(80) * CHPP_NSEC_PER_MSEC)  // 80 ms
62 #endif
63 
64 /**
65  * CHPP Transport layer maximum retransmission attempts, after which a reset is
66  * attempted. Setting this to zero disables retransmissions.
67  */
68 #ifndef CHPP_TRANSPORT_MAX_RETX
69 #define CHPP_TRANSPORT_MAX_RETX UINT16_C(4)
70 #endif
71 
72 /**
73  * CHPP Transport layer maximum reset attempts. Current functional values are 1
74  * or higher (setting to 0 currently functions identically to 1).
75  */
76 #ifndef CHPP_TRANSPORT_MAX_RESET
77 #define CHPP_TRANSPORT_MAX_RESET UINT16_C(3)
78 #endif
79 
80 /**
81  * CHPP Transport layer predefined timeout values.
82  */
83 #define CHPP_TRANSPORT_TIMEOUT_INFINITE UINT64_MAX
84 #define CHPP_TRANSPORT_TIMEOUT_IMMEDIATE 0
85 
86 /**
87  * CHPP Transport header flags bitmap
88  *
89  * @defgroup CHPP_TRANSPORT_FLAG
90  * @{
91  */
92 // This packet concludes a (fragmented or unfragmented) datagram
93 #define CHPP_TRANSPORT_FLAG_FINISHED_DATAGRAM 0x00
94 // Set if packet is part of a fragmented datagram, except for the last fragment
95 #define CHPP_TRANSPORT_FLAG_UNFINISHED_DATAGRAM 0x01
96 // Reserved for future use
97 #define CHPP_TRANSPORT_FLAG_RESERVED 0xfe
98 /** @} */
99 
100 /**
101  * Preamble (i.e. packet start delimiter) for this version of CHPP is "Ch".
102  * Any future backwards-incompatible versions of CHPP Transport will use a
103  * different preamble.
104  *
105  * @defgroup CHPP_PREAMBLE
106  * @{
107  */
108 #define CHPP_PREAMBLE_DATA 0x6843
109 #define CHPP_PREAMBLE_LEN_BYTES 2
110 /** @} */
111 
112 /**
113  * Macros for a specific byte in the CHPP_PREAMBLE.
114  * Using the CHPP_PREAMBLE_BYTE_... macros are preferred due to a reduced risk
115  * of mistakes.
116  */
117 #define chppPreambleByte(loc) \
118   ((CHPP_PREAMBLE_DATA >> (8 * (CHPP_PREAMBLE_LEN_BYTES - (loc)-1))) & 0xff)
119 #define CHPP_PREAMBLE_BYTE_FIRST chppPreambleByte(0)
120 #define CHPP_PREAMBLE_BYTE_SECOND chppPreambleByte(1)
121 
122 /**
123  * Maximum number of datagrams in the Tx queue.
124  * CHPP will return an error if it is provided with a new Tx datagram when this
125  * queue is full.
126  * To be safe, this should be less than half of the maximum uint8_t value.
127  * Otherwise, ChppTxDatagramQueue should be updated accordingly.
128  */
129 #define CHPP_TX_DATAGRAM_QUEUE_LEN ((uint8_t)16)
130 
131 /**
132  * Maximum payload of packets at the link layer.
133  * TODO: Negotiate or advertise MTU. In the mean time, set default as to achieve
134  * transport TX MTU of 1024.
135  */
136 #define CHPP_LINK_TX_MTU_BYTES                                               \
137   ((uint16_t)MIN(                                                            \
138       CHPP_PLATFORM_LINK_TX_MTU_BYTES,                                       \
139       (1024 + CHPP_PREAMBLE_LEN_BYTES + sizeof(struct ChppTransportHeader) + \
140        sizeof(struct ChppTransportFooter))))
141 
142 /**
143  * Maximum payload of packets at the transport layer.
144  */
145 #define CHPP_TRANSPORT_TX_MTU_BYTES                              \
146   ((uint16_t)(CHPP_LINK_TX_MTU_BYTES - CHPP_PREAMBLE_LEN_BYTES - \
147               sizeof(struct ChppTransportHeader) -               \
148               sizeof(struct ChppTransportFooter)))
149 
150 /**
151  * Maximum payload of packets at the transport layer.
152  */
153 #define CHPP_TRANSPORT_RX_MTU_BYTES                                       \
154   ((uint16_t)(CHPP_PLATFORM_LINK_RX_MTU_BYTES - CHPP_PREAMBLE_LEN_BYTES - \
155               sizeof(struct ChppTransportHeader) -                        \
156               sizeof(struct ChppTransportFooter)))
157 
158 /************************************************
159  *  Status variables to store context in lieu of global variables (this)
160  ***********************************************/
161 
162 /**
163  * Error codes optionally reported in ChppTransportHeader (Least significant
164  * nibble of int8_t packetCode).
165  */
166 #define CHPP_TRANSPORT_ERROR_MASK LEAST_SIGNIFICANT_NIBBLE
167 #define CHPP_TRANSPORT_GET_ERROR(value) \
168   ((enum ChppTransportErrorCode)(       \
169       (value)&CHPP_TRANSPORT_ERROR_MASK))  // TODO: Consider checking if this
170                                            // maps into a valid enum
171 enum ChppTransportErrorCode {
172   //! No error reported (either ACK or implicit NACK)
173   CHPP_TRANSPORT_ERROR_NONE = 0,
174   //! Checksum failure
175   CHPP_TRANSPORT_ERROR_CHECKSUM = 1,
176   //! Out of memory
177   CHPP_TRANSPORT_ERROR_OOM = 2,
178   //! Busy
179   CHPP_TRANSPORT_ERROR_BUSY = 3,
180   //! Invalid header
181   CHPP_TRANSPORT_ERROR_HEADER = 4,
182   //! Out of order
183   CHPP_TRANSPORT_ERROR_ORDER = 5,
184   //! Timeout
185   CHPP_TRANSPORT_ERROR_TIMEOUT = 6,
186   //! Too many retries
187   CHPP_TRANSPORT_ERROR_MAX_RETRIES = 7,
188   //! Message incomprehensible at App Layer
189   CHPP_TRANSPORT_ERROR_APPLAYER = 0xF,
190 };
191 
192 /**
193  * Packet attributes in ChppTransportHeader (Most significant nibble (MSN) of
194  * int8_t packetCode).
195  */
196 #define CHPP_TRANSPORT_ATTR_VALUE(value) (((value)&0x0f) << 4)
197 #define CHPP_TRANSPORT_ATTR_MASK MOST_SIGNIFICANT_NIBBLE
198 #define CHPP_TRANSPORT_GET_ATTR(value)   \
199   ((enum ChppTransportPacketAttributes)( \
200       (value)&CHPP_TRANSPORT_ATTR_MASK))  // TODO: Consider checking if this
201                                           // maps into a valid enum
202 
203 enum ChppTransportPacketAttributes {
204   //! None
205   CHPP_TRANSPORT_ATTR_NONE = CHPP_TRANSPORT_ATTR_VALUE(0),
206   //! Reset
207   CHPP_TRANSPORT_ATTR_RESET = CHPP_TRANSPORT_ATTR_VALUE(1),
208   //! Reset Ack
209   CHPP_TRANSPORT_ATTR_RESET_ACK = CHPP_TRANSPORT_ATTR_VALUE(2),
210   //! Transport-Layer Loopback Request
211   CHPP_TRANSPORT_ATTR_LOOPBACK_REQUEST = CHPP_TRANSPORT_ATTR_VALUE(3),
212   //! Transport-Layer Loopback Response
213   CHPP_TRANSPORT_ATTR_LOOPBACK_RESPONSE = CHPP_TRANSPORT_ATTR_VALUE(4),
214 };
215 
216 #define CHPP_ATTR_AND_ERROR_TO_PACKET_CODE(attr, error) \
217   ((uint8_t)(attr & CHPP_TRANSPORT_ATTR_MASK) |         \
218    (uint8_t)(error & CHPP_TRANSPORT_ERROR_MASK))
219 
220 /**
221  * CHPP Transport Layer header (not including the preamble)
222  */
223 CHPP_PACKED_START
224 struct ChppTransportHeader {
225   //! Flags bitmap, defined as CHPP_TRANSPORT_FLAG_...
226   uint8_t flags;
227 
228   //! LS Nibble: Defined in enum ChppTransportErrorCode
229   //! MS Nibble: Defined in enum ChppTransportPacketAttributes
230   uint8_t packetCode;
231 
232   //! Next expected sequence number for a payload-bearing packet
233   uint8_t ackSeq;
234 
235   //! Sequence number
236   uint8_t seq;
237 
238   //! Payload length in bytes (not including header / footer)
239   uint16_t length;
240 
241   //! Reserved
242   uint16_t reserved;
243 } CHPP_PACKED_ATTR;
244 CHPP_PACKED_END
245 
246 /**
247  * CHPP Transport Layer footer (containing the checksum)
248  */
249 CHPP_PACKED_START
250 struct ChppTransportFooter {
251   uint32_t checksum;  // IEEE CRC-32 initialized to 0xFFFFFFFF
252 } CHPP_PACKED_ATTR;
253 CHPP_PACKED_END
254 
255 enum ChppRxState {
256   //! Waiting for, or processing, the preamble (i.e. packet start delimiter)
257   //! Moves to CHPP_STATE_HEADER as soon as it has seen a complete preamble.
258   CHPP_STATE_PREAMBLE = 0,
259 
260   //! Processing the packet header. Moves to CHPP_STATE_PAYLOAD after processing
261   //! the expected length of the header.
262   CHPP_STATE_HEADER = 1,
263 
264   //! Copying the packet payload. The payload length is determined by the
265   //! header.
266   //! Moves to CHPP_STATE_FOOTER afterwards.
267   CHPP_STATE_PAYLOAD = 2,
268 
269   //! Processing the packet footer (checksum) and responding accordingly. Moves
270   //! to CHPP_STATE_PREAMBLE afterwards.
271   CHPP_STATE_FOOTER = 3,
272 };
273 
274 enum ChppResetState {
275   CHPP_RESET_STATE_RESETTING = 0,          //! Reset in progress
276   CHPP_RESET_STATE_NONE = 1,               //! Not in the middle of a reset
277   CHPP_RESET_STATE_PERMANENT_FAILURE = 2,  //! Failed, will not retry
278 };
279 
280 /**
281  * Semantic Versioning system of CHRE.
282  */
283 CHPP_PACKED_START
284 struct ChppVersion {
285   //! Major version of (breaking changes).
286   uint8_t major;
287 
288   //! Minor version (backwards compatible changes).
289   uint8_t minor;
290 
291   //! Patch version (bug fixes).
292   uint16_t patch;
293 } CHPP_PACKED_ATTR;
294 CHPP_PACKED_END
295 
296 /**
297  * Payload that is sent along reset and reset-ack packets. This may be used to
298  * advertise the configuration parameters of this CHPP instance, and/or set the
299  * configuration parameters of the remote side (TODO).
300  */
301 CHPP_PACKED_START
302 struct ChppTransportConfiguration {
303   //! CHPP transport version.
304   struct ChppVersion version;
305 
306   //! Receive MTU size.
307   uint16_t rxMtu;
308 
309   //! Max outstanding packet window size (1 for current implementation).
310   uint16_t windowSize;
311 
312   //! Transport layer timeout in milliseconds (i.e. to receive ACK).
313   uint16_t timeoutInMs;
314 } CHPP_PACKED_ATTR;
315 CHPP_PACKED_END
316 
317 struct ChppRxStatus {
318   //! Current receiving state, as described in ChppRxState.
319   enum ChppRxState state;
320 
321   //! Location counter in bytes within each state. Must always be reinitialized
322   //! to 0 when switching states.
323   size_t locInState;
324 
325   //! Next expected sequence number (for a payload-bearing packet)
326   uint8_t expectedSeq;
327 
328   //! Packet (error) code, if any, of the last received packet
329   uint8_t receivedPacketCode;
330 
331   //! Last received ACK sequence number (i.e. next expected sequence number for
332   //! an outgoing payload-bearing packet)
333   uint8_t receivedAckSeq;
334 
335   //! Time when starting to receive the current packet (i.e. after preamble).
336   uint64_t packetStartTimeNs;
337 
338   //! Location counter in bytes within the current Rx datagram.
339   size_t locInDatagram;
340 
341   //! The total number of data received in chppRxDataCb.
342   size_t numTotalDataBytes;
343 
344   //! The timestamp when the transport received any data through chppRxDataCb.
345   uint32_t lastDataTimeMs;
346 
347   //! The timestamp when the transport received a good RX packet.
348   uint32_t lastGoodPacketTimeMs;
349 };
350 
351 struct ChppTxStatus {
352   //! Last sent ACK sequence number (i.e. next expected sequence number for
353   //! an incoming payload-bearing packet)
354   uint8_t sentAckSeq;
355 
356   //! Last sent sequence number (irrespective of whether it has been received /
357   //! ACKed or not)
358   uint8_t sentSeq;
359 
360   //! Does the transport layer have any packets (with or without payload) it
361   //! needs to send out?
362   bool hasPacketsToSend;
363 
364   //! Error code, if any, of the next packet the transport layer will send out.
365   uint8_t packetCodeToSend;
366 
367   //! How many times the last sent sequence number has been (re-)sent.
368   size_t txAttempts;
369 
370   //! Time when the last packet was sent to the link layer.
371   uint64_t lastTxTimeNs;
372 
373   //! How many bytes of the front-of-queue datagram has been sent out
374   size_t sentLocInDatagram;
375 
376   //! Note: For a future ACK window >1, sentLocInDatagram doesn't always apply
377   //! to the front-of-queue datagram. Instead, we need to track the queue
378   //! position the datagram being sent as well (relative to the front-of-queue).
379   //! e.g. uint8_t datagramBeingSent
380 
381   //! How many bytes of the front-of-queue datagram has been acked
382   size_t ackedLocInDatagram;
383 
384   //! Whether the link layer is still processing pendingTxPacket
385   bool linkBusy;
386 };
387 
388 struct PendingTxPacket {
389   //! Length of outgoing packet to the Link Layer
390   size_t length;
391 
392   //! Payload of outgoing packet to the Link Layer
393   uint8_t payload[CHPP_LINK_TX_MTU_BYTES];
394 };
395 
396 struct ChppDatagram {
397   //! Length of datagram payload in bytes (A datagram can be constituted from
398   //! one or more packets)
399   size_t length;
400 
401   // Datagram payload
402   uint8_t *payload;
403 };
404 
405 struct ChppTxDatagramQueue {
406   //! Number of pending datagrams in the queue.
407   uint8_t pending;
408 
409   //! Index of the datagram at the front of the queue.
410   uint8_t front;
411 
412   //! Location counter within the front datagram (i.e. the datagram at the front
413   //! of the queue), showing how many bytes of this datagram have already been
414   //! packetized and processed.
415   size_t loc;
416 
417   //! Array of datagrams
418   struct ChppDatagram datagram[CHPP_TX_DATAGRAM_QUEUE_LEN];
419 };
420 
421 struct ChppTransportState {
422   struct ChppAppState *appContext;  // Pointer to app layer context
423 
424   struct ChppRxStatus rxStatus;         // Rx state and location within
425   struct ChppTransportHeader rxHeader;  // Rx packet header
426   struct ChppTransportFooter rxFooter;  // Rx packet footer (checksum)
427   struct ChppDatagram rxDatagram;       // Rx datagram
428   uint8_t loopbackResult;  // Last transport-layer loopback test result as an
429                            // enum ChppAppErrorCode
430 
431   struct ChppTxStatus txStatus;                // Tx state
432   struct ChppTxDatagramQueue txDatagramQueue;  // Queue of datagrams to be Tx
433   struct PendingTxPacket pendingTxPacket;      // Outgoing packet to Link Layer
434   struct ChppDatagram transportLoopbackData;   // Transport-layer loopback
435                                                // request data, if any
436 
437   struct ChppMutex mutex;          // Lock for transport state (i.e. context)
438   struct ChppNotifier notifier;    // Notifier for main thread
439   bool initialized;                // Has been initialized
440   enum ChppResetState resetState;  // Maintains state of a reset
441   uint16_t resetCount;             // (Unsuccessful) reset attempts
442   uint64_t resetTimeNs;            // Time of last reset
443 
444   struct ChppConditionVariable
445       resetCondVar;  // Condvar specifically to wait for resetState
446 
447   //! This MUST be the last field in the ChppTransportState structure, otherwise
448   //! chppResetTransportContext() will not work properly.
449   struct ChppPlatformLinkParameters linkParams;  // For corresponding link layer
450 
451   // !!! DO NOT ADD ANY NEW FIELDS HERE - ADD THEM BEFORE linkParams !!!
452 };
453 
454 /************************************************
455  *  Public functions
456  ***********************************************/
457 
458 /**
459  * Initializes the CHPP transport layer state stored in the parameter
460  * transportContext.
461  * It is necessary to initialize state for each transport layer instance on
462  * every platform.
463  * Each transport layer instance is associated with a single application layer
464  * instance. appContext points to the application layer status struct associated
465  * with this transport layer instance.
466  *
467  * Note: It is necessary to initialize the platform-specific values of
468  * transportContext.linkParams (prior to the call, if needed in the link layer
469  * APIs, such as chppPlatformLinkInit()).
470  *
471  * @param transportContext Maintains status for each transport layer instance.
472  * @param appContext The app layer status struct associated with this transport
473  * layer instance.
474  */
475 void chppTransportInit(struct ChppTransportState *transportContext,
476                        struct ChppAppState *appContext);
477 
478 /**
479  * Deinitializes the CHPP transport layer and does necessary clean-ups for
480  * e.g. clean shutdown.
481  *
482  * @param transportContext A non-null pointer to ChppTransportState
483  * initialized previously in chppTransportInit().
484  */
485 void chppTransportDeinit(struct ChppTransportState *transportContext);
486 
487 /**
488  * Blocking call until CHPP has finished resetting.
489  *
490  * @param transportContext, A non-null pointer to ChppTransportState
491  * initialized previously in chppTransportDeinit().
492  * @param timeoutMs The timeout in milliseconds.
493  *
494  * @return False if timed out.
495  */
496 bool chppTransportWaitForResetComplete(
497     struct ChppTransportState *transportContext, uint64_t timeoutMs);
498 
499 /**
500  * Processes all incoming data on the serial port based on the Rx state.
501  * stream. Checks checksum, triggering the correct response (ACK / NACK).
502  * Moves the state to CHPP_STATE_PREAMBLE afterwards.
503  *
504  * TODO: Add requirements, e.g. context must not be modified unless locked via
505  * mutex.
506  *
507  * TODO: Add sufficient outward facing documentation
508  *
509  * @param context Maintains status for each transport layer instance.
510  * @param buf Input data. Cannot be null.
511  * @param len Length of input data in bytes.
512  *
513  * @return true informs the serial port driver that we are waiting for a
514  * preamble. This allows the driver to (optionally) filter incoming zeros and
515  * save processing
516  */
517 bool chppRxDataCb(struct ChppTransportState *context, const uint8_t *buf,
518                   size_t len);
519 
520 /**
521  * Optional callback function for the link layer to indicate the end of a
522  * packet. The availability of this information depends on the link layer
523  * implementation.
524  *
525  * @param context Maintains status for each transport layer instance.
526  */
527 void chppRxPacketCompleteCb(struct ChppTransportState *context);
528 
529 /**
530  * Enqueues an outgoing datagram of a specified length and frees the payload
531  * asynchronously after it is sent. The payload must have been allocated by the
532  * caller using chppMalloc.
533  *
534  * If enqueueing a datagram is unsuccessful, the payload is freed (discarded)
535  * and an error message printed.
536  *
537  * Note that the ownership of buf is taken from the caller when this method is
538  * invoked.
539  *
540  * @param context Maintains status for each transport layer instance.
541  * @param buf Datagram payload allocated through chppMalloc. Cannot be null.
542  * @param len Datagram length in bytes.
543  *
544  * @return True informs the sender that the datagram was successfully enqueued.
545  * False informs the sender that the queue was full and the payload discarded.
546  */
547 bool chppEnqueueTxDatagramOrFail(struct ChppTransportState *context, void *buf,
548                                  size_t len);
549 
550 /**
551  * Enables the App Layer to enqueue an outgoing error datagram, for example for
552  * an OOM situation over the wire.
553  *
554  * @param context Maintains status for each transport layer instance.
555  * @param errorCode Error code to be sent.
556  */
557 void chppEnqueueTxErrorDatagram(struct ChppTransportState *context,
558                                 enum ChppTransportErrorCode errorCode);
559 
560 /**
561  * Provides systems that do not use chppWorkThreadStart() and its associated
562  * timeout mechanisms (that relies on chppNotifierTimedWait()) how long they
563  * should wait until they run chppTransportDoWork() again, in nanoseconds.
564  *
565  * For these implementations, chppTransportDoWork() should be run at or slightly
566  * after the wait time returned by this function.
567  *
568  * A return value of CHPP_TRANSPORT_TIMEOUT_INFINITE indicates that there is no
569  * need to run chppTransportDoWork() based on a timeout (i.e. CHPP is not
570  * waiting on an ACK).
571  *
572  * A return value of CHPP_TRANSPORT_TIMEOUT_IMMEDIATE indicates that
573  * chppTransportDoWork() should be run immediately.
574  *
575  * @param context Maintains status for each transport layer instance.
576  *
577  * @return Time until chppTransportDoWork() must be called in nanoseconds.
578  */
579 uint64_t chppTransportGetTimeUntilNextDoWorkNs(
580     struct ChppTransportState *context);
581 
582 /**
583  * Starts the main thread for CHPP's Transport Layer. This thread needs to be
584  * started after the Transport Layer is initialized through chppTransportInit().
585  * Note that a platform may implement this as a new thread or as part of an
586  * existing thread.
587  *
588  * If needed (e.g. for testing and debugging), this thread can be stopped by
589  * calling chppWorkThreadStop().
590  *
591  * If a system does not support multi-threading, the system MUST replicate the
592  * high-level behavior of chppWorkThreadStart(). More details in the
593  * documentation of chppWorkThreadHandleSignal(). For such systems,
594  * chppTransportGetTimeUntilNextDoWorkNs() can be used to replicate the
595  * functionality of chppNotifierTimedWait().
596  *
597  * @param context Maintains status for each transport layer instance.
598  */
599 void chppWorkThreadStart(struct ChppTransportState *context);
600 
601 /**
602  * Handles signals set for the CHPP transport instance. This method should be
603  * invoked externally if chppWorkThreadStart() cannot be directly used, for
604  * example if the system does not support thread signaling and needs explicit
605  * control of the CHPP work thread from an outer control loop. By "outer control
606  * loop," we mean the code path triggering work on the CHPP transport layer.
607  *
608  * Note that if a platform uses this method, the outer control loop MUST
609  * replicate the behavior in the chppWorkThreadStart() method exactly. All
610  * pending signals MUST be handled prior to the suspension of the outer control
611  * loop, and any initialization sequence MUST be replicated.
612  *
613  * @param context Maintains status for each transport layer instance.
614  * @param signals The signals to process. Should be obtained via
615  * chppNotifierTimedWait() for the given transport context's notifier.
616  *
617  * @return true if the CHPP work thread should exit.
618  */
619 bool chppWorkThreadHandleSignal(struct ChppTransportState *context,
620                                 uint32_t signals);
621 
622 /**
623  * Signals the main thread for CHPP's Transport Layer to perform some work. This
624  * method should only be called from the link layer.
625  *
626  * Note that this method must be safe to call from an interrupt context, as the
627  * platform link layer implementation may send a signal from one (e.g. handling
628  * an interrupt from the physical layer or inputs from the remote endpoint).
629  *
630  * @param params Platform-specific struct with link details / parameters.
631  * @param signal The signal that describes the work to be performed. Only bits
632  * specified by CHPP_TRANSPORT_SIGNAL_PLATFORM_MASK can be set.
633  */
chppWorkThreadSignalFromLink(struct ChppPlatformLinkParameters * params,uint32_t signal)634 static inline void chppWorkThreadSignalFromLink(
635     struct ChppPlatformLinkParameters *params, uint32_t signal) {
636   struct ChppTransportState *context =
637       container_of(params, struct ChppTransportState, linkParams);
638 
639   CHPP_ASSERT((signal & ~(CHPP_TRANSPORT_SIGNAL_PLATFORM_MASK)) == 0);
640   chppNotifierSignal(&context->notifier,
641                      signal & CHPP_TRANSPORT_SIGNAL_PLATFORM_MASK);
642 }
643 
644 /**
645  * Stops the main thread for CHPP's Transport Layer that has been started by
646  * calling chppWorkThreadStart(). Stopping this thread may be necessary for
647  * testing and debugging purposes.
648  *
649  * @param context Maintains status for each transport layer instance.
650  */
651 void chppWorkThreadStop(struct ChppTransportState *context);
652 
653 /**
654  * Notifies the transport layer that the link layer is done sending the previous
655  * payload (as provided to platformLinkSend() through buf and len) and can
656  * accept more data.
657  *
658  * On systems that implement the link layer Tx asynchronously, where
659  * platformLinkSend() returns False before consuming the payload provided to it
660  * (i.e. buf and len), the platform implementation must call this function after
661  * platformLinkSend() is done with the payload (i.e. buf and len).
662  *
663  * @param params Platform-specific struct with link details / parameters.
664  * @param error Indicates success or failure type.
665  */
666 void chppLinkSendDoneCb(struct ChppPlatformLinkParameters *params,
667                         enum ChppLinkErrorCode error);
668 
669 /**
670  * Notifies the transport layer that the app layer is done with the previous
671  * payload (as provided to chppAppProcessRxDatagram() through buf and len), so
672  * it is freed appropriately etc.
673  *
674  * TODO: Look into automatically doing this when a response is sent back by a
675  * service.
676  *
677  * @param context Maintains status for each transport layer instance.
678  * @param buf Pointer to the buf given to chppAppProcessRxDatagram. Cannot be
679  * null.
680  */
681 void chppDatagramProcessDoneCb(struct ChppTransportState *context,
682                                uint8_t *buf);
683 
684 /**
685  * Sends out transport-layer loopback data. Note that in most situations, an
686  * application-layer loopback test is pprefrable as it is more thorough and
687  * provides statistics regarding the correctness of the loopbacked data.
688  *
689  * The result will be available later, asynchronously, as a ChppAppErrorCode
690  * enum in context->loopbackResult.
691  *
692  * @param context Maintains status for each transport layer instance.
693  * @param buf Pointer to the loopback data to be sent. Cannot be null.
694  * @param len Length of the loopback data.
695  *
696  * @return A ChppLinkErrorCode enum indicating if the transport-layer-loopback
697  * request was accepted. Note that the actual test result will be available
698  * later, asynchronously, in context->loopbackResult.
699  */
700 uint8_t chppRunTransportLoopback(struct ChppTransportState *context,
701                                  uint8_t *buf, size_t len);
702 
703 /**
704  * Sends a reset or reset-ack packet over the link in order to reset the remote
705  * side or inform the counterpart of a reset, respectively. The transport
706  * layer's configuration is sent as the payload of the reset packet.
707  *
708  * This function is typically used only internally, either immediately after
709  * initialization via chppWorkThreadStart() or for subsequent resets or
710  * reset-acks via chppReset(). However, implementations that do not rely on
711  * chppWorkThreadStart() would require to call this function after initializing
712  * CHPP.
713  *
714  * @param transportContext Maintains status for each transport layer instance.
715  * @param resetType Distinguishes a reset from a reset-ack, as defined in the
716  * ChppTransportPacketAttributes struct.
717  * @param error Provides the error that led to the reset.
718  */
719 void chppTransportSendReset(struct ChppTransportState *context,
720                             enum ChppTransportPacketAttributes resetType,
721                             enum ChppTransportErrorCode error);
722 
723 #ifdef __cplusplus
724 }
725 #endif
726 
727 #endif  // CHPP_TRANSPORT_H_
728