You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A lot of things have changed in LibOSDP in preparation for a major release. The following things have to be documented. This issue will track all those topics as a todo list before making the major release.
App-owned queue data (b5823c0) OPT_OSDP_APP_OWNED_QUEUE_DATA is gone — always-on. Apps that submit queued payloads must now register osdp_cp_set_command_completion_callback / osdp_pd_set_event_completion_callback.
Single channel per OSDP context (04a0851) osdp_cp_setup() / osdp_pd_setup() take a struct osdp_channel * argument. channel removed from osdp_pd_info_t; id removed from struct osdp_channel. Multi-bus deployments must create one osdp_t per channel.
Retire inline MFGREP support (34cda90) Positive return from pd_command_callback_t for OSDP_CMD_MFG is no longer honored as an inline MFGREP. pd_command_callback_t contract is now 0 = ACK, -ve = NAK, +ve reserved. MFGREP must be emitted asynchronously via osdp_pd_submit_event().
File-transfer completion is notification-driven (f0990cd) Querying file-transfer status now advances the FSM to idle on terminal states. Callers must consume the new OSDP_NOTIFICATION_FILE_TX_DONE (payload enum osdp_file_tx_outcome) to learn the outcome.
osdp_event_notification renamed to osdp_notification (dfbf978) — the struct is shared by CP events and PD commands, so the event_ prefix was misleading. Enum type and enumerators were also renamed: enum osdp_event_notification_type → enum osdp_notification_type, and OSDP_EVENT_NOTIFICATION_* → OSDP_NOTIFICATION_* (the EVENT_ infix is dropped).
PD-mode notifications now fire the command callback (c07d953) — OSDP_FLAG_ENABLE_NOTIFICATION was previously a PD no-op. It now delivers link / SC transitions via pd_command_callback_t wrapped in osdp_cmd with id OSDP_CMD_NOTIFICATION. PD apps that set the flag must handle or ignore the new command id.
OSDP_NOTIFICATION_COMMAND.arg1 semantics (c01cc92) Changed from 1 = success, 0 = failure (bool-as-int) to the documented 0 = success, -1 = failure. Consumers comparing against the old values read every success as a failure (caught the pytest suite).
Log callback signature changed (e506db6) — osdp_log_callback_fn_t gained a leading int pd argument: (int pd, int log_level, ...). Every osdp_set_log_callback() consumer must update its callback signature. Silent break (compiles with a warning at best); rides in the same commit as minimal-logger mode.
PD online/offline tracking + OSDP_NOTIFICATION_PD_STATUS (dfbf978 enum, 756046a behavior) — PD now derives online/offline from CP link activity and emits a third notification type, OSDP_NOTIFICATION_PD_STATUS (governed by OSDP_PD_ONLINE_TOUT_MS). Extends the c07d953 item beyond link/SC transitions.
Adaptive CRC/Checksum handling along with strict capabilities based check-character gating
Fixed-width types in osdp_pd_info_t (0203552, 865cc46) — baud_rate and flags change from int to uint32_t. flags is the load-bearing one: every OSDP_FLAG_* value lives at bit 16 or above (0x00010000–0x00200000), so on a 16-bit-int target none of them could be represented at all. Quiet break — existing code keeps compiling; what changes is %d formatting (needs PRIu32) and signed comparisons. ABI break for anyone linking a prebuilt lib.
File-transfer callbacks take unsigned size/offset (c0212a1) — the wire format and the internal struct osdp_file were always uint32_t; the callbacks were int and the decode path bridged them with an explicit (int) cast, truncating any file over INT_MAX. - [ ] osdp_event_cardread.length is now uint16_t (08bccb3) — matches the 16-bit wire field. ABI break; %d consumers need PRIu16. The bits→bytes conversion is now BITS_TO_BYTES() and computes in uint32_t: a uint16_t promotes to int, and 0xFFFF + 7 overflows a 16-bit int.
Build, packaging & platform
Public headers install under include/libosdp/ (03e159b; cmake 5436dd3, 6c9344a, 6c8b0c5) — installed consumers must switch #include <osdp.h> → #include <libosdp/osdp.h>. pkg-config Cflags and find_package(libosdp) were updated to match; README documents find_package consumption (CMake ≥ 3.14).
Crypto backend selection (7f4eea5, 3cbe8e0, 6c8b0c5) — --crypto / OPT_OSDP_CRYPTO_BACKEND now takes auto|openssl|mbedtls|tinyaes, default auto (probes openssl → mbedtls → tinyaes). TinyAES is now bundled in-tree. Behavior change: a build that specifies no backend now auto-selects a system lib instead of falling back to TinyAES-with-warning.
Bare-metal now requires an app-supplied clock and entropy source on unrecognised targets (0e9d44c, 1a80a06) — bare-metal is split into platforms utils can identify (Arduino incl. ESP32/ESP8266, Zephyr, Mynewt) and those it cannot. Identifiable platforms are served natively and need no hooks. On an unidentifiable target, rand_u32() and osdp_millis_now() are left undefined and declared strongly, so a missing implementation is a link error — previously it was a clock frozen at zero (every timeout silently never fired) and a constant RNG. Both declarations had to drop __weak: a weak undefined reference resolves to NULL and gets called.
Arduino / PlatformIO is a first-class platform (0e9d44c) — esp_random() (ESP32) and RANDOM_REG32 (ESP8266) hardware TRNGs are selected automatically. Cores without a TRNG (AVR, SAMD) fall back to a micros()-seeded PRNG, which is still not a CSPRNG — Secure Channel deployments there must override rand_u32(). osdp_fill_random() stays a strong symbol: rand_u32() is the single override seam.
CI: bare-metal ARM compile check (72e1ec7) — arm-none-eabi-gcc -Wformat=2 -Werror over src/. Under newlib uint32_t is unsigned long, so wrong format specifiers and int-width mismatches are diagnosable there while staying silent on x86-64 glibc.
New features that need explicit documentation or callouts
Zero-copy RX (772ba9e) OPT_OSDP_RX_ZERO_COPY is a compile-time switch, no fallback. The old buffered osdp_read_fn_t path is removed in zero-copy builds. Python bindings do not support zero-copy builds.
Static CP builds (19596c9) --static-pd / OPT_OSDP_STATIC_PD renamed to --static / OPT_OSDP_STATIC (old names kept as deprecated aliases). Static builds now include CP, not just PD. Downstream build systems referencing the old preprocessor symbol must update.
tick_t and its width (c23e05e) Internal timestamps and osdp_millis_now() / osdp_millis_since() switched from int64_t to tick_t. New build flags --bare-metal and --use-32bit-tick-t (requires --bare-metal) let embedded targets opt into a 32-bit tick. Bare-metal apps that override the __weak osdp_millis_now() must change their return type to tick_t. UPDATE: As of 1a80a06, overriding osdp_millis_now() is no longer merely recommended on bare metal: on a target utils cannot identify it is mandatory, and its absence is a link error rather than a silent stall.
Minimal logger mode (e506db6) Opt-in mode where libosdp skips filtering/formatting and hands logs to the app as-is, with a static logger context (lower RAM). Useful for apps that already have a host logging subsystem.
Link/protocol metrics API (61fbe31) — new exported int osdp_get_metrics(osdp_t *ctx, int pd_idx, struct osdp_metrics *out) plus public struct osdp_metrics. The only net-new exported function in this release.
Security: secure-channel keys zeroized at function exit (b281fee) — hardening; worth a dedicated security line in the changelog.
Security: bare-metal/Arduino builds no longer draw Secure Channel nonces from a fixed-seed PRNG (0e9d44c). Users should override rand_u32() with a hardware entropy source in production.
Minor / housekeeping
C++ header sync + constness fixes (52abc71, e600d30) — may affect strict C++ consumers of osdp.hpp.
Static pools overlaid when role is exclusive (8d7a243) — memory refinement under OPT_OSDP_STATIC; sub-note to the static-build item.
CHANGELOG migrated to split per-file format (3fd5b15) — maintenance/process note.
A lot of things have changed in LibOSDP in preparation for a major release. The following things have to be documented. This issue will track all those topics as a todo list before making the major release.
v4.0 breaking / behavior-changing items (API & protocol)
OPT_OSDP_APP_OWNED_QUEUE_DATAis gone — always-on. Apps that submit queued payloads must now registerosdp_cp_set_command_completion_callback/osdp_pd_set_event_completion_callback.osdp_cp_setup()/osdp_pd_setup()take astruct osdp_channel *argument.channelremoved fromosdp_pd_info_t;idremoved fromstruct osdp_channel. Multi-bus deployments must create oneosdp_tper channel.pd_command_callback_tforOSDP_CMD_MFGis no longer honored as an inline MFGREP.pd_command_callback_tcontract is now0 = ACK,-ve = NAK,+ve reserved. MFGREP must be emitted asynchronously viaosdp_pd_submit_event().OSDP_NOTIFICATION_FILE_TX_DONE(payloadenum osdp_file_tx_outcome) to learn the outcome.osdp_event_notificationrenamed toosdp_notification(dfbf978) — the struct is shared by CP events and PD commands, so theevent_prefix was misleading. Enum type and enumerators were also renamed:enum osdp_event_notification_type→enum osdp_notification_type, andOSDP_EVENT_NOTIFICATION_*→OSDP_NOTIFICATION_*(theEVENT_infix is dropped).OSDP_FLAG_ENABLE_NOTIFICATIONwas previously a PD no-op. It now delivers link / SC transitions viapd_command_callback_twrapped inosdp_cmdwith idOSDP_CMD_NOTIFICATION. PD apps that set the flag must handle or ignore the new command id.OSDP_NOTIFICATION_COMMAND.arg1semantics (c01cc92) Changed from1 = success, 0 = failure(bool-as-int) to the documented0 = success, -1 = failure. Consumers comparing against the old values read every success as a failure (caught the pytest suite).osdp_log_callback_fn_tgained a leadingint pdargument:(int pd, int log_level, ...). Everyosdp_set_log_callback()consumer must update its callback signature. Silent break (compiles with a warning at best); rides in the same commit as minimal-logger mode.OSDP_NOTIFICATION_PD_STATUS(dfbf978 enum, 756046a behavior) — PD now derives online/offline from CP link activity and emits a third notification type,OSDP_NOTIFICATION_PD_STATUS(governed byOSDP_PD_ONLINE_TOUT_MS). Extends the c07d953 item beyond link/SC transitions.osdp_pd_info_t(0203552, 865cc46) —baud_rateandflagschange frominttouint32_t.flagsis the load-bearing one: everyOSDP_FLAG_*value lives at bit 16 or above (0x00010000–0x00200000), so on a 16-bit-inttarget none of them could be represented at all. Quiet break — existing code keeps compiling; what changes is%dformatting (needsPRIu32) and signed comparisons. ABI break for anyone linking a prebuilt lib.struct osdp_filewere alwaysuint32_t; the callbacks wereintand the decode path bridged them with an explicit(int)cast, truncating any file overINT_MAX. - [ ] osdp_event_cardread.length is now uint16_t (08bccb3) — matches the 16-bit wire field. ABI break; %d consumers need PRIu16. The bits→bytes conversion is now BITS_TO_BYTES() and computes in uint32_t: a uint16_t promotes to int, and 0xFFFF + 7 overflows a 16-bit int.Build, packaging & platform
include/libosdp/(03e159b; cmake 5436dd3, 6c9344a, 6c8b0c5) — installed consumers must switch#include <osdp.h>→#include <libosdp/osdp.h>. pkg-configCflagsandfind_package(libosdp)were updated to match; README documentsfind_packageconsumption (CMake ≥ 3.14).--crypto/OPT_OSDP_CRYPTO_BACKENDnow takesauto|openssl|mbedtls|tinyaes, defaultauto(probes openssl → mbedtls → tinyaes). TinyAES is now bundled in-tree. Behavior change: a build that specifies no backend now auto-selects a system lib instead of falling back to TinyAES-with-warning.--lib-onlyflag for that path.rand_u32()andosdp_millis_now()are left undefined and declared strongly, so a missing implementation is a link error — previously it was a clock frozen at zero (every timeout silently never fired) and a constant RNG. Both declarations had to drop__weak: a weak undefined reference resolves to NULL and gets called.esp_random()(ESP32) andRANDOM_REG32(ESP8266) hardware TRNGs are selected automatically. Cores without a TRNG (AVR, SAMD) fall back to amicros()-seeded PRNG, which is still not a CSPRNG — Secure Channel deployments there must overriderand_u32().osdp_fill_random()stays a strong symbol:rand_u32()is the single override seam.arm-none-eabi-gcc -Wformat=2 -Werroroversrc/. Under newlibuint32_tisunsigned long, so wrong format specifiers and int-width mismatches are diagnosable there while staying silent on x86-64 glibc.New features that need explicit documentation or callouts
OPT_OSDP_RX_ZERO_COPYis a compile-time switch, no fallback. The old bufferedosdp_read_fn_tpath is removed in zero-copy builds. Python bindings do not support zero-copy builds.--static-pd/OPT_OSDP_STATIC_PDrenamed to--static/OPT_OSDP_STATIC(old names kept as deprecated aliases). Static builds now include CP, not just PD. Downstream build systems referencing the old preprocessor symbol must update.osdp_millis_now()/osdp_millis_since()switched fromint64_ttotick_t. New build flags--bare-metaland--use-32bit-tick-t(requires--bare-metal) let embedded targets opt into a 32-bit tick. Bare-metal apps that override the__weak osdp_millis_now()must change their return type totick_t. UPDATE: As of 1a80a06, overridingosdp_millis_now()is no longer merely recommended on bare metal: on a target utils cannot identify it is mandatory, and its absence is a link error rather than a silent stall.int osdp_get_metrics(osdp_t *ctx, int pd_idx, struct osdp_metrics *out)plus publicstruct osdp_metrics. The only net-new exported function in this release.rand_u32()with a hardware entropy source in production.Minor / housekeeping
osdp.hpp.OPT_OSDP_STATIC; sub-note to the static-build item.