Morse Micro IoT SDK  2.11.2
mmpkt.h
1/*
2 * Copyright 2022-2024 Morse Micro
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
15#pragma once
16
17#include <stdbool.h>
18#include <stddef.h>
19#include <stdint.h>
20
21#include "mmosal.h"
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27
33#ifndef MM_FAST_ROUND_UP
34#define MM_FAST_ROUND_UP(x, m) ((((x)-1) | ((m)-1)) + 1)
35#endif
36
37#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
39#define MMPKT_DEBUG_MAGIC_OPENED (0x08254759)
41#define MMPKT_DEBUG_MAGIC_CLOSED (0xdeaddead)
43#define MMPKT_DEBUG_MAGIC_RELEASED (0x0bad0bad)
44#endif
45
46struct mmdrv_cmd_metadata;
47struct mmdrv_tx_metadata;
48struct mmdrv_rx_metadata;
49struct mmpkt_ops;
50
59 void *opaque;
61 struct mmdrv_tx_metadata *tx;
63 struct mmdrv_rx_metadata *rx;
65 struct mmdrv_cmd_metadata *cmd;
66};
67
87struct mmpkt
88{
90 uint8_t *buf;
92 uint32_t buf_len;
94 uint32_t start_offset;
96 uint32_t data_len;
100 const struct mmpkt_ops *ops;
102 struct mmpkt *volatile next;
103#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
104 uint32_t debug_magic;
105#endif
106};
107
110{
112 void (*free_mmpkt)(void *mmpkt);
113};
114
126struct mmpktview;
127
137static inline void mmpkt_init(struct mmpkt *mmpkt, uint8_t *buf, uint32_t buf_len,
138 uint32_t data_start_offset, const struct mmpkt_ops *ops)
139{
140 memset(mmpkt, 0, sizeof(*mmpkt));
141 mmpkt->buf = buf;
142 mmpkt->buf_len = buf_len;
143 mmpkt->start_offset = data_start_offset;
144 mmpkt->ops = ops;
145#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
146 mmpkt->debug_magic = MMPKT_DEBUG_MAGIC_CLOSED;
147#endif
148}
149
167static inline struct mmpkt *mmpkt_init_buf(uint8_t *buf, uint32_t buf_len,
168 uint32_t space_at_start, uint32_t space_at_end,
169 uint32_t metadata_size, const struct mmpkt_ops *ops)
170{
171 struct mmpkt *mmpkt = (struct mmpkt *)buf;
172
173 uint8_t *data_start;
174 uint32_t header_size = MM_FAST_ROUND_UP(sizeof(*mmpkt), 4);
175 uint32_t data_len;
176 metadata_size = MM_FAST_ROUND_UP(metadata_size, 4);
177
178 if (space_at_end != UINT32_MAX)
179 {
180 data_len = MM_FAST_ROUND_UP(space_at_start + space_at_end, 4);
181 }
182 else
183 {
184 /* Special case: if space_at_end is UINT32_MAX then use the entire buffer.
185 * Note that we round down to ensure that the metadata is word aligned. */
186 data_len = (buf_len - header_size - metadata_size) & ~0x03ul;
187 /* Signed comparison in case buf_len was less than (header_size + metadata_size).
188 * Note that we do not expect to allocate an mmpkt with length > INT32_MAX, so we
189 * can safely treat these as signed integers. */
190 if ((int32_t)data_len < (int32_t)space_at_start)
191 {
192 return NULL;
193 }
194 }
195
196 if (header_size + data_len + metadata_size > buf_len)
197 {
198 return NULL;
199 }
200
201 data_start = ((uint8_t *)mmpkt) + header_size;
202
203 mmpkt_init(mmpkt, data_start, data_len, space_at_start, ops);
204
205 if (metadata_size != 0)
206 {
207 mmpkt->metadata.opaque = data_start + data_len;
208 memset(mmpkt->metadata.opaque, 0, metadata_size);
209 }
210
211 return mmpkt;
212}
213
214
227struct mmpkt *mmpkt_alloc_on_heap(uint32_t space_at_start, uint32_t space_at_end,
228 uint32_t metadata_size);
229
237
251static inline struct mmpktview *mmpkt_open(struct mmpkt *mmpkt)
252{
253#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
254 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_CLOSED);
255 mmpkt->debug_magic = MMPKT_DEBUG_MAGIC_OPENED;
256#endif
257 return (struct mmpktview *)mmpkt;
258}
259
266static inline void mmpkt_close(struct mmpktview **view)
267{
268 MMOSAL_ASSERT(view != NULL);
269#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
270 struct mmpkt *mmpkt = (struct mmpkt *)(*view);
271 if (mmpkt != NULL)
272 {
273 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
274 mmpkt->debug_magic = MMPKT_DEBUG_MAGIC_CLOSED;
275 }
276#endif
277 *view = NULL;
278}
279
287static inline struct mmpkt *mmpkt_from_view(struct mmpktview *view)
288{
289 return (struct mmpkt *)view;
290}
291
299static inline uint8_t *mmpkt_get_data_start(struct mmpktview *view)
300{
301 struct mmpkt *mmpkt = (struct mmpkt *)view;
302#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
303 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
304#endif
305 return mmpkt->buf + mmpkt->start_offset;
306}
307
315static inline uint8_t *mmpkt_get_data_end(struct mmpktview *view)
316{
317 struct mmpkt *mmpkt = (struct mmpkt *)view;
318#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
319 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
320#endif
322}
323
332static inline uint32_t mmpkt_peek_data_length(const struct mmpkt *mmpkt)
333{
334 return mmpkt->data_len;
335}
336
345static inline uint32_t mmpkt_get_data_length(struct mmpktview *view)
346{
347 struct mmpkt *mmpkt = (struct mmpkt *)view;
348#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
349 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
350#endif
351 return mmpkt->data_len;
352}
353
361static inline uint32_t mmpkt_available_space_at_start(struct mmpktview *view)
362{
363 struct mmpkt *mmpkt = (struct mmpkt *)view;
364#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
365 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
366#endif
367 return mmpkt->start_offset;
368}
369
377static inline uint32_t mmpkt_available_space_at_end(struct mmpktview *view)
378{
379 struct mmpkt *mmpkt = (struct mmpkt *)view;
380#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
381 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
382#endif
384}
385
399static inline uint8_t *mmpkt_prepend(struct mmpktview *view, uint32_t len)
400{
401 struct mmpkt *mmpkt = (struct mmpkt *)view;
402#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
403 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
404#endif
406 mmpkt->start_offset -= len;
407 mmpkt->data_len += len;
408 return mmpkt->buf + mmpkt->start_offset;
409}
410
422static inline void mmpkt_prepend_data(struct mmpktview *view, const uint8_t * data, uint32_t len)
423{
424 uint8_t *dest = mmpkt_prepend(view, len);
425 memcpy(dest, data, len);
426}
427
441static inline uint8_t *mmpkt_append(struct mmpktview *view, uint32_t len)
442{
443 struct mmpkt *mmpkt = (struct mmpkt *)view;
444#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
445 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
446#endif
447 uint8_t *ret = mmpkt_get_data_end(view);
449 mmpkt->data_len += len;
450 return ret;
451}
452
462static inline void mmpkt_append_data(struct mmpktview *view, const uint8_t *data, uint32_t len)
463{
464 uint8_t *dest = mmpkt_append(view, len);
465 memcpy(dest, data, len);
466}
467
476{
477 return mmpkt->metadata;
478}
479
488static inline void mmpkt_adjust_start_offset(struct mmpkt *mmpkt, int32_t delta)
489{
491 mmpkt->start_offset += delta;
493}
494
503static inline uint8_t *mmpkt_remove_from_start(struct mmpktview *view, uint32_t len)
504{
505 struct mmpkt *mmpkt = (struct mmpkt *)view;
506#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
507 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
508#endif
509 uint8_t *ret;
510
511 if (mmpkt_get_data_length(view) < len)
512 {
513 return NULL;
514 }
515
516 ret = mmpkt_get_data_start(view);
517
518 mmpkt->start_offset += len;
519 mmpkt->data_len -= len;
520
521 return ret;
522}
523
532static inline uint8_t *mmpkt_remove_from_end(struct mmpktview *view, uint32_t len)
533{
534 struct mmpkt *mmpkt = (struct mmpkt *)view;
535#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
536 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
537#endif
538
539 if (mmpkt_get_data_length(view) < len)
540 {
541 return NULL;
542 }
543
544 uint8_t *ret = mmpkt_get_data_end(view) - len;
545
546 mmpkt->data_len -= len;
547
548 return ret;
549}
550
558static inline void mmpkt_truncate(struct mmpkt *mmpkt, uint32_t len)
559{
560 MMOSAL_ASSERT(len <= mmpkt->data_len);
561 mmpkt->data_len = len;
562}
563
573static inline struct mmpkt *mmpkt_get_next(struct mmpkt *mmpkt)
574{
575 return mmpkt->next;
576}
577
586static inline void mmpkt_set_next(struct mmpkt *mmpkt, struct mmpkt *next)
587{
588 mmpkt->next = next;
589}
590
602static inline bool mmpkt_contains_ptr(struct mmpktview *view, const void *ptr)
603{
604 struct mmpkt *mmpkt = (struct mmpkt *)view;
605#if defined(MMPKT_DEBUG) && MMPKT_DEBUG
606 MMOSAL_ASSERT(mmpkt->debug_magic == MMPKT_DEBUG_MAGIC_OPENED);
607#endif
608 return ((const uint8_t *)ptr >= &mmpkt->buf[0]
609 && (const uint8_t *)ptr < &mmpkt->buf[mmpkt->buf_len]);
610}
611
612#ifdef __cplusplus
613}
614#endif
615
#define MMOSAL_ASSERT(expr)
Assert that the given expression evaluates to true and abort execution if not.
Definition: mmosal.h:1006
struct mmpkt * mmpkt_alloc_on_heap(uint32_t space_at_start, uint32_t space_at_end, uint32_t metadata_size)
Allocate a new mmpkt on the heap (using mmosal_malloc()).
static void mmpkt_append_data(struct mmpktview *view, const uint8_t *data, uint32_t len)
Appends the given data to the data already in the mmpkt.
Definition: mmpkt.h:462
static struct mmpkt * mmpkt_init_buf(uint8_t *buf, uint32_t buf_len, uint32_t space_at_start, uint32_t space_at_end, uint32_t metadata_size, const struct mmpkt_ops *ops)
Initialize an mmpkt in a single buffer using the given values.
Definition: mmpkt.h:167
static struct mmpkt * mmpkt_from_view(struct mmpktview *view)
Get the underlying mmpkt from an opened view.
Definition: mmpkt.h:287
static void mmpkt_close(struct mmpktview **view)
Close the given view.
Definition: mmpkt.h:266
void mmpkt_release(struct mmpkt *mmpkt)
Release a reference to the given mmpkt.
static void mmpkt_init(struct mmpkt *mmpkt, uint8_t *buf, uint32_t buf_len, uint32_t data_start_offset, const struct mmpkt_ops *ops)
Initialize an mmpkt header with the given values.
Definition: mmpkt.h:137
static union mmpkt_metadata_ptr mmpkt_get_metadata(struct mmpkt *mmpkt)
Retrieve a reference to the metadata associated with the given mmpkt.
Definition: mmpkt.h:475
static struct mmpkt * mmpkt_get_next(struct mmpkt *mmpkt)
Get the next pointer embedded in the mmpkt.
Definition: mmpkt.h:573
static void mmpkt_adjust_start_offset(struct mmpkt *mmpkt, int32_t delta)
Adjust the start offset of an mmpkt.
Definition: mmpkt.h:488
static uint32_t mmpkt_available_space_at_start(struct mmpktview *view)
Returns the amount of space available for prepending to the data in the buffer.
Definition: mmpkt.h:361
static uint32_t mmpkt_peek_data_length(const struct mmpkt *mmpkt)
Peek the length of the data currently from an unopened mmpkt.
Definition: mmpkt.h:332
#define MM_FAST_ROUND_UP(x, m)
Round x up to the next multiple of m (where m is a power of 2).
Definition: mmpkt.h:34
static uint8_t * mmpkt_get_data_end(struct mmpktview *view)
Gets a pointer to the end of the data in the mmpkt.
Definition: mmpkt.h:315
static uint8_t * mmpkt_prepend(struct mmpktview *view, uint32_t len)
Reserves space immediately before the data currently in the given mmpkt and returns a pointer to this...
Definition: mmpkt.h:399
static void mmpkt_truncate(struct mmpkt *mmpkt, uint32_t len)
Truncate the mmpkt data to the given length.
Definition: mmpkt.h:558
static uint32_t mmpkt_get_data_length(struct mmpktview *view)
Gets the length of the data currently in the mmpkt.
Definition: mmpkt.h:345
static uint32_t mmpkt_available_space_at_end(struct mmpktview *view)
Returns the amount of space available for appending to the data in the buffer.
Definition: mmpkt.h:377
static void mmpkt_prepend_data(struct mmpktview *view, const uint8_t *data, uint32_t len)
Prepends the given data to the data already in the mmpkt.
Definition: mmpkt.h:422
static uint8_t * mmpkt_remove_from_end(struct mmpktview *view, uint32_t len)
Remove data from the end of the mmpkt.
Definition: mmpkt.h:532
static struct mmpktview * mmpkt_open(struct mmpkt *mmpkt)
Open a view of the given mmpkt.
Definition: mmpkt.h:251
static uint8_t * mmpkt_append(struct mmpktview *view, uint32_t len)
Reserves space immediately after the data currently in the given mmpkt and returns a pointer to this ...
Definition: mmpkt.h:441
static uint8_t * mmpkt_get_data_start(struct mmpktview *view)
Gets a pointer to the start of the data in the mmpkt.
Definition: mmpkt.h:299
static bool mmpkt_contains_ptr(struct mmpktview *view, const void *ptr)
Check whether the given pointer is pointing inside the mmpkt's buffer.
Definition: mmpkt.h:602
static uint8_t * mmpkt_remove_from_start(struct mmpktview *view, uint32_t len)
Remove data from the start of the mmpkt.
Definition: mmpkt.h:503
static void mmpkt_set_next(struct mmpkt *mmpkt, struct mmpkt *next)
Set the next pointer embedded in the mmpkt.
Definition: mmpkt.h:586
static unsigned char buf[1024]
Statically allocated buffer for MQTT.
Definition: mqttdemo.c:153
Operations data structure for mmpkt.
Definition: mmpkt.h:110
void(* free_mmpkt)(void *mmpkt)
Free the given mmpkt.
Definition: mmpkt.h:112
Core mmpkt data structure.
Definition: mmpkt.h:88
uint32_t buf_len
Length of the buffer.
Definition: mmpkt.h:92
uint32_t data_len
Length of actual data in the buffer.
Definition: mmpkt.h:96
uint32_t start_offset
Offset where actual data starts in the buffer.
Definition: mmpkt.h:94
const struct mmpkt_ops * ops
Reference to operations data structure for this mmpkt.
Definition: mmpkt.h:100
uint8_t * buf
The buffer where data is stored.
Definition: mmpkt.h:90
union mmpkt_metadata_ptr metadata
Packet metadata used by driver (context dependent).
Definition: mmpkt.h:98
struct mmpkt *volatile next
Pointer that can be used to construct linked lists.
Definition: mmpkt.h:102
Union of pointer types for mmpkt metadata.
Definition: mmpkt.h:57
struct mmdrv_rx_metadata * rx
Metadata for a packet which is being received.
Definition: mmpkt.h:63
struct mmdrv_tx_metadata * tx
Metadata for a packet which is being transmitted.
Definition: mmpkt.h:61
void * opaque
Opaque pointer for contexts which are unaware of the specific metadata structure.
Definition: mmpkt.h:59
struct mmdrv_cmd_metadata * cmd
Control block for a command response sent to the host.
Definition: mmpkt.h:65