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