ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
device_id.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file device_id.h
6 * @brief Stable device UUID derived from the chip MAC (PROTOCORE_ENABLE_DEVICE_ID).
7 *
8 * protocore_uuid_from_mac() computes a deterministic RFC 4122 version-5 UUID from a
9 * 6-byte MAC: namespace = the RFC 4122 DNS namespace, name = the lowercase MAC
10 * hex, hashed with the library's SHA-1. The same MAC always yields the same
11 * UUID, so it is a stable device identity (mDNS hostname, MQTT client ID, ...)
12 * that needs no storage. protocore_device_uuid() reads the part's factory MAC
13 * and formats it. Pure, host-testable core; no heap.
14 *
15 * @author Douglas Quigg (dstroy0)
16 * @date 2026
17 */
18
19#ifndef PROTOCORE_DEVICE_ID_H
20#define PROTOCORE_DEVICE_ID_H
21
22#include "protocore_config.h" // the entry point: protocore_types.h for the widths
23
24#if PROTOCORE_ENABLE_DEVICE_ID
25
27
28/** @brief Length of a formatted UUID string including the null terminator. */
29#define PROTOCORE_UUID_STR_LEN 37
30
31/**
32 * @brief Format a deterministic RFC 4122 v5 UUID from a 6-byte MAC.
33 *
34 * @param mac six MAC bytes.
35 * @param out buffer of at least PROTOCORE_UUID_STR_LEN bytes; receives
36 * "xxxxxxxx-xxxx-5xxx-yxxx-xxxxxxxxxxxx" (lowercase, null-terminated).
37 */
38/** @brief The address a UUID is derived from, and where the text lands. */
39typedef struct
40{
41 const uint8_t *mac; ///< the six address bytes a format reads, when the caller supplies them
42 char *out; ///< PROTOCORE_UUID_STR_LEN bytes the formatted UUID is written into
43} DeviceIdArgs;
44
45/**
46 * @brief The stable MAC-derived device identity.
47 *
48 * @var DeviceIdNs::args the address a UUID is derived from, and where the text lands
49 * @var DeviceIdNs::from_mac format a UUIDv5 from the caller's address
50 * @var DeviceIdNs::uuid format one from the part's own burned-in address
51 *
52 * No storage member: both calls write into the caller's buffer and hold nothing.
53 */
54typedef struct
55{
56 DeviceIdArgs args;
57} DeviceIdVars;
58
59/** @brief The operands and the outcome. */
60extern DeviceIdVars DeviceIdV;
61
62/** @brief The entries. */
63typedef struct
64{
65 void (*const from_mac)(uint8_t *work);
66 void (*const uuid)(uint8_t *work);
67} DeviceIdNs;
68
69// What the table binds, defined once in the .c and taking one parameter each: everything
70// else an entry needs is an operand in DeviceIdV or a region of the borrow at a fixed offset.
71void protocore_device_id_from_mac(uint8_t *work);
72void protocore_device_id_uuid(uint8_t *work);
73
74// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
75// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
76// `DeviceId.from_mac(work)` resolves to a named function and becomes a DIRECT call. An extern table
77// leaves the call indirect and the symbol live at every level, -O2 -flto included.
78static const DeviceIdNs DeviceId __attribute__((unused)) = {
79 .from_mac = protocore_device_id_from_mac,
80 .uuid = protocore_device_id_uuid,
81};
82
83#if PROTOCORE_HAS_VENDOR_MAC
84/**
85 * @brief Format this device's UUID from its burned-in factory station MAC.
86 * @param out buffer of at least PROTOCORE_UUID_STR_LEN bytes.
87 */
88
89#endif
90
92
93#endif // PROTOCORE_ENABLE_DEVICE_ID
94
95#endif // PROTOCORE_DEVICE_ID_H
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
#define PROTOCORE_END_DECLS
Definition types.h:97