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