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