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