Skip to content

Loading builds...

Changes

#22502 (Jul 29, 2026, 1:06:38 PM)

libosmo-trx/trxc: add SETSLOT parameter parser/builder

Add struct osmo_trxc_setslot plus osmo_trxc_setslot_parse()/_build()
for the "<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]" SETSLOT parameters,
including VAMOS combinations (VFF/VHH/VFH/HVHH) with per-sub-channel
TSC overrides.

Change-Id: I17a1176b1418edd0caf750d50acda0482d4ad04a
Vadim Yanitskiy at

#22501 (Jul 29, 2026, 1:06:38 PM)

libosmo-trx/ep: add TRX endpoint module

Add the osmo_trx_ep module, encapsulating the clock/ctrl/data UDP
socket management of the TRX protocol on top of osmo_io.  One endpoint
serves an (optional) clock socket plus N channels, each channel being
a ctrl + data socket pair.

The module is role-neutral: struct osmo_trx_ep_cfg carries a mode
(OSMO_TRX_EP_MODE_{L1,TRX}) selecting which side of the protocol the
endpoint implements.  The mode is needed to parse datagrams received
on the data sockets, as the wire format alone does not identify the
direction (BURST.ind vs BURST.req).  All local and remote ports are
derived from a single base port (default: 5700).

To avoid indirect calls on the hot path, the decoded Rx handlers
(osmo_trx_ep_rx_*) are plain function prototypes bound at link-time,
not function pointers.  The library provides weak default stubs to
stay link-complete (-no-undefined), so applications only implement
the handlers for the directions they consume, overriding the stubs.

The Tx path implements TRXDv2 PDU batching for burst requests:
osmo_trx_ep_send_burst_req() accumulates PDUs until it is called
with br == NULL (the batching breaker), like in osmo-bts-trx.

osmo-trx itself will not adopt this module: its per-channel/thread
socket ownership model (dedicated blocking-read threads per socket)
is incompatible with osmo_io's single-select-loop dispatch. It is
meant for osmo-bts, osmocom-bb/trxcon, and the upcoming C rewrite
of fake_trx.

Change-Id: I767fa43a9ca88be40c385f6dcb9de22891a6afc3
Vadim Yanitskiy at

#22500 (Jul 29, 2026, 1:03:38 PM)

libosmo-trx: add TRXC/TRXD message codec

Introduce libosmo-trx: a shared implementation of the TRXC/TRXD
(OpenBTS-style TRX) protocol, to be used by osmo-trx, osmo-bts,
trxcon, and the upcoming C rewrite of fake_trx.

This initial version provides two I/O-free codec modules:

* trxd: TRXD PDU codec for BURST.ind and BURST.req
* trxc: verb-agnostic TRXC message codec (CMD/RSP/IND)

The codec logic is based on the existing implementations in
osmo-bts (f0ee51997470e1c3020ddb85082385ed43ba0c68).

Change-Id: I933fc417a67d0043f74b04626b7643c79e381492
Vadim Yanitskiy at

#22499 (Jul 29, 2026, 1:03:23 PM)

debian: add packaging for libosmo-trx

Add the usual Debian packaging files, closely following the ones in
libosmocore.git: the shared library package libosmo-trx0, as well as
the -dev, -doc, and -dbg packages.

Change-Id: I56f0074ad121ecacb076b508d1adfdd71cce99ec
Vadim Yanitskiy at

#22498 (Jul 29, 2026, 1:03:23 PM)

libosmo-trx/client: add optional limit for retransmissions

The client used to retransmit an unacknowledged command forever, like
osmo-bts-trx does.  trxcon, however, gives up after 3 retransmission
attempts, concluding that the transceiver is offline.  Add a new API
function osmo_trxc_client_set_max_retrans() enabling this behavior:
once a command has been retransmitted the given number of times
without a response, the client escalates to the fatal_error call-back
(with rsp == NULL) and freezes the command queue.  The default (0)
retains the old behavior (no limit).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Ib90a032b38c69ae26023e726992d3f5f7e502fcf
Vadim Yanitskiy at

#22497 (Jul 29, 2026, 1:03:09 PM)

Transceiver52M: implement TRXDv2 support

TRXDv2 was proposed and implemented in osmo-bts a while ago, but
osmo-trx was still stuck at TRXDv1.  This patch implements TRXDv2
and UL/DL burst batching using libosmo-trx API.

DL: driveTxPriorityQueue() now loops over osmo_trxd_burst_req_parse()
to handle datagrams potentially containing multiple batched BURST.req,
dispatching each via the new handleBurstReq().

UL: accumulate BURST.ind PDUs for the same FN into one msgb per channel
and flush as a single datagram once the next frame's PDU arrives or
the channel stops;  TRXDv0/v1 channels keep sending one PDU per
datagram via sendBurstInd().  Batching is unconditional for now;
making it configurable is left as a follow-up.

Change-Id: Ie6a33e3980b3ca4ab05a3d4221d5a8ba0132233d
Related: OS#5283
Vadim Yanitskiy at

#22496 (Jul 29, 2026, 1:01:15 PM)

libosmo-trx: generate Doxygen API documentation

Add Doxyfile.trx.in (based on Doxyfile.core.in from libosmocore.git,
upgraded using 'doxygen -u' to get rid of obsolete tags) and the
usual rules to build and install the HTML documentation, as well as
the --disable-doxygen configure option, like in other libosmo-*
projects.

Change-Id: I54cf8c0c60215c666d8fa55dafec53379a2382d5
Vadim Yanitskiy at

#22495 (Jul 29, 2026, 1:01:15 PM)

libosmo-trx/trxd: support NOPE.{ind,req} in TRXDv0/v1 PDUs

TRXDv0 (and TRXDv1 in the downlink direction) has no MTS field, but
NOPE indications/requests do exist there in practice: the burst payload
is simply omitted, i.e. a header-only PDU.  This is how osmocom-bb's
trxcon transmits NOPE.req (see trx_if_handle_phyif_burst_req()).

Change-Id: I1a59f31d0f00c8509a016dc2bac71b6aa467f3a4
Vadim Yanitskiy at

#22494 (Jul 29, 2026, 1:01:14 PM)

libosmo-trx/client: add TRXC client (command queue) API

Add the osmo_trxc_client module: a transport-agnostic generalization
of the TRXC command handling logic in osmo-bts-trx (trx_if.c):

* command queue with a single command in flight;
* retransmission on response timeout (default: 2 s);
* suppression of consecutive duplicate commands;
* RSP<->CMD matching, optionally including the parameters;
* filtering of duplicate responses caused by retransmissions;
* escalation of NACKed critical commands (OSMO_TRXC_F_CRITICAL)
  to the fatal_error call-back;
* TRXD PDU version negotiation (SETFORMAT), incl. the fallback to
  version 0 for old transceivers rejecting it with 'RSP ERR 1'.

The client neither opens nor owns a socket: the application transmits
serialized messages in the tx_msg call-back and feeds received
datagrams into osmo_trxc_client_rx().  The response call-back may
return N > 0 to request a re-transmission of the same command after
N seconds (e.g. POWERON retry, as implemented in osmo-bts-trx).

Change-Id: I817e394f74a10e3adae4a0b58342c82acdf0794e
Vadim Yanitskiy at

#22493 (Jul 29, 2026, 1:01:12 PM)

Transceiver52M: migrate to libosmo-trx

Replace the local TRXC/TRXD implementation with libosmo-trx's shared
osmo_trxc_msg/osmo_trxd_burst_{ind,req} API, including SETSLOT parsing
via osmo_trxc_setslot_parse()/_build().  Take a chance to fix SETSLOT
to always send a response, distinguishing bogus input from unsupported
VAMOS channel combinations.

Only the TRXC/TRXD build/parse API is used here, not the osmo_trx_ep
endpoint API: osmo-trx runs its socket I/O on dedicated threads that
don't drive osmo_select_main(), which osmo_trx_ep depends on.

Change-Id: I458ec85c56e2101d073c8c35f11c147191c4ea0c
Related: OS#5283
Vadim Yanitskiy at

#22492 (Jul 29, 2026, 1:01:11 PM)

libosmo-trx/trxc: enlarge the params buffer

The SETFH command (implemented by trxcon and fake_trx) carries the
whole Mobile Allocation as pairs of Rx/Tx frequencies in kHz:

  CMD SETFH <HSN> <MAIO> <RXF1> <TXF1> [... <RXFN> <TXFN>]

With up to 64 ARFCNs in the Mobile Allocation, the parameters string
alone can exceed 1000 characters, far beyond the old 128 byte limit.

Derive OSMO_TRXC_PARAMS_LEN_MAX from OSMO_TRXC_MSG_BUF_SIZE, so that
any message ("RSP " + verb + status + params) still fits the
recommended socket buffer size.  Also add the OSMO_TRXC_CMD_SETFH
verb constant and a regression test doing a round-trip of a maximum
size SETFH command (64 ARFCNs).

Change-Id: I2f65b213f5ada499eea4abae87d3727057e03e22
Vadim Yanitskiy at

#22491 (Jul 29, 2026, 1:00:59 PM)

Transceiver52M: make TRXDv2 burst batching configurable

Add a "trxd-batch (disable|enable)" VTY command under the TRX node
(default: enable) to allow disabling per-frame BURST.ind batching
even when TRXDv2 is negotiated, e.g. to trade datagram count for
latency.

Change-Id: I2f58f87d85de5254bae6d7a606dffcd0ad4069d5
Related: OS#5283
Vadim Yanitskiy at

#22490 (Jul 29, 2026, 1:00:58 PM)

libosmo-trx/client: make public API operate on parsed messages

The TRXC client engine and the TRX endpoint module did not compose:
osmo_trx_ep_rx_ctrl_msg() delivers a parsed struct osmo_trxc_msg,
while osmo_trxc_client_rx() accepts a raw datagram only; likewise,
the tx_msg call-back used to emit a serialized string, while
osmo_trx_ep_send_ctrl_msg() takes the parsed structure.  An
osmo_trx_ep user would have to needlessly re-parse and re-serialize
TRXC messages when gluing both modules together.

Make struct osmo_trxc_msg the currency at both module boundaries:

* add osmo_trxc_client_rx_msg(), accepting a parsed message;
  osmo_trxc_client_rx() becomes a parse-first convenience wrapper
  for applications managing the TRXC socket themselves;
* change the tx_msg call-back to take a parsed message: it's now
  up to the transport to serialize it (osmo_trx_ep users simply
  call osmo_trx_ep_send_ctrl_msg(), others osmo_trxc_msg_build()).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Idf53513d06be2337383601494b225b5722c93129
Vadim Yanitskiy at

#22489 (Jul 29, 2026, 1:00:56 PM)

debian: add packaging for libosmo-trx

Add the usual Debian packaging files, closely following the ones in
libosmocore.git: the shared library package libosmo-trx0, as well as
the -dev, -doc, and -dbg packages.

Change-Id: I56f0074ad121ecacb076b508d1adfdd71cce99ec
Vadim Yanitskiy at

#22488 (Jul 29, 2026, 1:00:51 PM)

libosmo-trx/ep: add TRX endpoint module

Add the osmo_trx_ep module, encapsulating the clock/ctrl/data UDP
socket management of the TRX protocol on top of osmo_io.  One endpoint
serves an (optional) clock socket plus N channels, each channel being
a ctrl + data socket pair.

The module is role-neutral: struct osmo_trx_ep_cfg carries a mode
(OSMO_TRX_EP_MODE_{L1,TRX}) selecting which side of the protocol the
endpoint implements.  The mode is needed to parse datagrams received
on the data sockets, as the wire format alone does not identify the
direction (BURST.ind vs BURST.req).  All local and remote ports are
derived from a single base port (default: 5700).

To avoid indirect calls on the hot path, the decoded Rx handlers
(osmo_trx_ep_rx_*) are plain function prototypes bound at link-time,
not function pointers.  The library provides weak default stubs to
stay link-complete (-no-undefined), so applications only implement
the handlers for the directions they consume, overriding the stubs.

The Tx path implements TRXDv2 PDU batching for burst requests:
osmo_trx_ep_send_burst_req() accumulates PDUs until it is called
with br == NULL (the batching breaker), like in osmo-bts-trx.

osmo-trx itself will not adopt this module: its per-channel/thread
socket ownership model (dedicated blocking-read threads per socket)
is incompatible with osmo_io's single-select-loop dispatch. It is
meant for osmo-bts, osmocom-bb/trxcon, and the upcoming C rewrite
of fake_trx.

Change-Id: I767fa43a9ca88be40c385f6dcb9de22891a6afc3
Vadim Yanitskiy at

#22487 (Jul 29, 2026, 1:00:51 PM)

libosmo-trx: add TRXC/TRXD message codec

Introduce libosmo-trx: a shared implementation of the TRXC/TRXD
(OpenBTS-style TRX) protocol, to be used by osmo-trx, osmo-bts,
trxcon, and the upcoming C rewrite of fake_trx.

This initial version provides two I/O-free codec modules:

* trxd: TRXD PDU codec for BURST.ind and BURST.req
* trxc: verb-agnostic TRXC message codec (CMD/RSP/IND)

The codec logic is based on the existing implementations in
osmo-bts (f0ee51997470e1c3020ddb85082385ed43ba0c68).

Change-Id: I933fc417a67d0043f74b04626b7643c79e381492
Vadim Yanitskiy at

#22486 (Jul 29, 2026, 12:56:52 PM)

libosmo-trx/trxc: add SETSLOT parameter parser/builder

Add struct osmo_trxc_setslot plus osmo_trxc_setslot_parse()/_build()
for the "<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]" SETSLOT parameters,
including VAMOS combinations (VFF/VHH/VFH/HVHH) with per-sub-channel
TSC overrides.

Change-Id: I17a1176b1418edd0caf750d50acda0482d4ad04a
Vadim Yanitskiy at

#22485 (Jul 29, 2026, 12:56:51 PM)

Transceiver52M: implement TRXDv2 support

TRXDv2 was proposed and implemented in osmo-bts a while ago, but
osmo-trx was still stuck at TRXDv1.  This patch implements TRXDv2
and UL/DL burst batching using libosmo-trx API.

DL: driveTxPriorityQueue() now loops over osmo_trxd_burst_req_parse()
to handle datagrams potentially containing multiple batched BURST.req,
dispatching each via the new handleBurstReq().

UL: accumulate BURST.ind PDUs for the same FN into one msgb per channel
and flush as a single datagram once the next frame's PDU arrives or
the channel stops;  TRXDv0/v1 channels keep sending one PDU per
datagram via sendBurstInd().  Batching is unconditional for now;
making it configurable is left as a follow-up.

Change-Id: Ie6a33e3980b3ca4ab05a3d4221d5a8ba0132233d
Related: OS#5283
Vadim Yanitskiy at

#22484 (Jul 29, 2026, 12:56:51 PM)

libosmo-trx/client: add optional limit for retransmissions

The client used to retransmit an unacknowledged command forever, like
osmo-bts-trx does.  trxcon, however, gives up after 3 retransmission
attempts, concluding that the transceiver is offline.  Add a new API
function osmo_trxc_client_set_max_retrans() enabling this behavior:
once a command has been retransmitted the given number of times
without a response, the client escalates to the fatal_error call-back
(with rsp == NULL) and freezes the command queue.  The default (0)
retains the old behavior (no limit).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Ib90a032b38c69ae26023e726992d3f5f7e502fcf
Vadim Yanitskiy at

#22483 (Jul 29, 2026, 12:56:51 PM)

Transceiver52M: migrate to libosmo-trx

Replace the local TRXC/TRXD implementation with libosmo-trx's shared
osmo_trxc_msg/osmo_trxd_burst_{ind,req} API, including SETSLOT parsing
via osmo_trxc_setslot_parse()/_build().  Take a chance to fix SETSLOT
to always send a response, distinguishing bogus input from unsupported
VAMOS channel combinations.

Only the TRXC/TRXD build/parse API is used here, not the osmo_trx_ep
endpoint API: osmo-trx runs its socket I/O on dedicated threads that
don't drive osmo_select_main(), which osmo_trx_ep depends on.

Change-Id: I458ec85c56e2101d073c8c35f11c147191c4ea0c
Related: OS#5283
Vadim Yanitskiy at

#22482 (Jul 29, 2026, 12:56:51 PM)

libosmo-trx/client: add TRXC client (command queue) API

Add the osmo_trxc_client module: a transport-agnostic generalization
of the TRXC command handling logic in osmo-bts-trx (trx_if.c):

* command queue with a single command in flight;
* retransmission on response timeout (default: 2 s);
* suppression of consecutive duplicate commands;
* RSP<->CMD matching, optionally including the parameters;
* filtering of duplicate responses caused by retransmissions;
* escalation of NACKed critical commands (OSMO_TRXC_F_CRITICAL)
  to the fatal_error call-back;
* TRXD PDU version negotiation (SETFORMAT), incl. the fallback to
  version 0 for old transceivers rejecting it with 'RSP ERR 1'.

The client neither opens nor owns a socket: the application transmits
serialized messages in the tx_msg call-back and feeds received
datagrams into osmo_trxc_client_rx().  The response call-back may
return N > 0 to request a re-transmission of the same command after
N seconds (e.g. POWERON retry, as implemented in osmo-bts-trx).

Change-Id: I817e394f74a10e3adae4a0b58342c82acdf0794e
Vadim Yanitskiy at

#22481 (Jul 29, 2026, 12:56:50 PM)

libosmo-trx: generate Doxygen API documentation

Add Doxyfile.trx.in (based on Doxyfile.core.in from libosmocore.git,
upgraded using 'doxygen -u' to get rid of obsolete tags) and the
usual rules to build and install the HTML documentation, as well as
the --disable-doxygen configure option, like in other libosmo-*
projects.

Change-Id: I54cf8c0c60215c666d8fa55dafec53379a2382d5
Vadim Yanitskiy at

#22480 (Jul 29, 2026, 12:56:50 PM)

libosmo-trx/trxd: support NOPE.{ind,req} in TRXDv0/v1 PDUs

TRXDv0 (and TRXDv1 in the downlink direction) has no MTS field, but
NOPE indications/requests do exist there in practice: the burst payload
is simply omitted, i.e. a header-only PDU.  This is how osmocom-bb's
trxcon transmits NOPE.req (see trx_if_handle_phyif_burst_req()).

Change-Id: I1a59f31d0f00c8509a016dc2bac71b6aa467f3a4
Vadim Yanitskiy at

#22479 (Jul 29, 2026, 12:56:50 PM)

Transceiver52M: make TRXDv2 burst batching configurable

Add a "trxd-batch (disable|enable)" VTY command under the TRX node
(default: enable) to allow disabling per-frame BURST.ind batching
even when TRXDv2 is negotiated, e.g. to trade datagram count for
latency.

Change-Id: I2f58f87d85de5254bae6d7a606dffcd0ad4069d5
Related: OS#5283
Vadim Yanitskiy at

#22478 (Jul 29, 2026, 12:56:50 PM)

libosmo-trx/trxc: enlarge the params buffer

The SETFH command (implemented by trxcon and fake_trx) carries the
whole Mobile Allocation as pairs of Rx/Tx frequencies in kHz:

  CMD SETFH <HSN> <MAIO> <RXF1> <TXF1> [... <RXFN> <TXFN>]

With up to 64 ARFCNs in the Mobile Allocation, the parameters string
alone can exceed 1000 characters, far beyond the old 128 byte limit.

Derive OSMO_TRXC_PARAMS_LEN_MAX from OSMO_TRXC_MSG_BUF_SIZE, so that
any message ("RSP " + verb + status + params) still fits the
recommended socket buffer size.  Also add the OSMO_TRXC_CMD_SETFH
verb constant and a regression test doing a round-trip of a maximum
size SETFH command (64 ARFCNs).

Change-Id: I2f65b213f5ada499eea4abae87d3727057e03e22
Vadim Yanitskiy at

#22477 (Jul 29, 2026, 12:56:49 PM)

libosmo-trx/client: make public API operate on parsed messages

The TRXC client engine and the TRX endpoint module did not compose:
osmo_trx_ep_rx_ctrl_msg() delivers a parsed struct osmo_trxc_msg,
while osmo_trxc_client_rx() accepts a raw datagram only; likewise,
the tx_msg call-back used to emit a serialized string, while
osmo_trx_ep_send_ctrl_msg() takes the parsed structure.  An
osmo_trx_ep user would have to needlessly re-parse and re-serialize
TRXC messages when gluing both modules together.

Make struct osmo_trxc_msg the currency at both module boundaries:

* add osmo_trxc_client_rx_msg(), accepting a parsed message;
  osmo_trxc_client_rx() becomes a parse-first convenience wrapper
  for applications managing the TRXC socket themselves;
* change the tx_msg call-back to take a parsed message: it's now
  up to the transport to serialize it (osmo_trx_ep users simply
  call osmo_trx_ep_send_ctrl_msg(), others osmo_trxc_msg_build()).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Idf53513d06be2337383601494b225b5722c93129
Vadim Yanitskiy at

#22476 (Jul 28, 2026, 7:06:31 PM)

firmware: card_emu: fix 7816-3 10.3.2 0=256 case

add_tpdu_byte() accumulates bytes received from the reader, but passes
reader_to_card = 0, but ISO 7816-3 10.3.2 says P3 == 0 means 256 not 0

Only reachable with P3 == 0 in a receive data phase, but
simtrace2-cardem-pcsc only requests PB_AND_RX when there is command data.

Fix this anyway.

Change-Id: I0fa4741bc1293549816595e6b4e8af9e22bcfbc1
ewild at

#22475 (Jul 28, 2026, 7:06:26 PM)

contrib/flash.py: fix typos

Python has no versoin nor printf.

Change-Id: I4fd4d2592b44b3ae827e00ae73d8c451aa2ec18f
ewild at

#22474 (Jul 28, 2026, 7:06:21 PM)

firmware: iso7816_3: fix F/D ratio for Di 8 and 9

iso7816_3_compute_fd_ratio() multiplied F by D for every d_index >= 8,
presumably because the upper half of ISO 7816-3 Table 8 encodes 1/D.

But 7816-3 2006 and 1997 differ!
That assumption is only true for the range 1010..1111, which in the
2006 version is RFU. Indices 1000 and 1001 are Di = 12 and Di = 20,
see iso7816_3_di_table[].

So right now Fi=372/Di=12 -> 372 * 12 = 4464 instead of 372 / 12 =
31.
In the cemu  value is rejected in emu_update_fidi()
and the old baud rate is silently kept.
In the sniffer update_fidi() programs US_FIDI as
4464 & 0x7ff = 368, which is garbage.

Use F/D for indices 1..9 and keep the legacy 1/D reading only for the RFU
range, where we cant really do anything useful anyway.

Change-Id: I44d6451d8b04aea2b0db7291b06a812afe84e52f
ewild at

#22473 (Jul 28, 2026, 7:06:21 PM)

firmware: sniffer: honor the ep argument of usb_msg_alloc_hdr()

Even though all callers pass the same endpoint anyway the arg should
be used and not discarded.

Change-Id: I1fa0097b9eef531900b359c7293a6c60040254e4
ewild at

#22472 (Jul 28, 2026, 7:06:20 PM)

host: simtrace2_api: do not log random memory

tx_cfg->features is logged before the memcpy() that fills it.
Looks like no one is using config.ac --enable-sanitize?

Change-Id: Id8369d312c8600ba9eea80c8f7782f196d7e20d1
ewild at

#22471 (Jul 28, 2026, 7:06:19 PM)

firmware: protect uart_tx_queue against ISR

cardem:
- dispatch_usb_command_cardem() appends to uart_tx_queue from the main loop
- tx_byte_tpdu() dequeues from the USART IRQ handler @ NVIC prio 0

card_handle_reset() has the same issue, drains queue and
frees uart_tx_msg from main loop while the ISR may own them.

All of this needs protection against the irq.

Needs a fixed llist_add_tail_irqsafe(), which called __enable_irq() instead of
restoring the saved PRIMASK for some unknown reason?!?!?!?

Change-Id: I7d9cdcc56263b27dfd4649dfb1da1d67761ee923
ewild at

#22470 (Jul 28, 2026, 7:06:18 PM)

firmware: use the full 11 bit US_FIDI.FI_DI_RATIO

US_FIDI_FI_DI_RATIO_Msk is 0x7ff,
cemu rejected >= 0x400 in emu_update_fidi() and masked with 0x3ff
in card_emu_uart_update_fidi(), but update_fidi() used by
the sniffer already used 0x7ff.

-> ratios 1024..2047 are unusable in cemu, which is the entire upper
half of ISO 7816-3 Table 7 at Di=1.

A reader trying one of those in a PPS gets the proposal echoed and
accepted, after which the card keeps transmitting at the old rate.

FI_DI_RATIO is clock periods per bit -> larger ratio is a SLOWER link.
The old check rejected slow values but accepted Fi=372/Di=64, ratio 5 !?

Unify and use the register mask (= shifed by 0 so usable as value) and
reject ratios that do not fit rather than truncating to garbage dividers.

Change-Id: I6211dd5be7c5c5d2150af2aa37a403b33e6d340d
ewild at

#22469 (Jul 28, 2026, 7:05:56 PM)

firmware: card_emu: use Di in the waiting time

ISO 7816-3 section 10.2 defines WT = WI x 960 x Fi/f seconds,
store as etu, etu = Fi / (D x f) seconds, so the Fi cancels,
but the D does not:

WT [etu] = WI x 960 x D

cemu dropped both (?!) -> WI x 960.
The old comment explains why Fi can be dropped, which is right, but
what about Di ?!
sniffer gets it right (wt_wi * 960UL * wt_d), so the two state machines
disagreed here again, by up to a factor of 64???!!?!!?

This was fixed in osmo-ccid-firmware in 066489d in 2020 but not ported
to st2.

Additionally the waiting time was only recalculated at the end of the ATR,
where D is still 1 by definition, so a PPS increasing D reprogrammed the
baud rate but left the waiting time untouched??!

etu duration shrinks with D by the same factor, wall clock WT is
independent of D, which is the whole point.
The old code decreased the waiting time by a factor of D:
after a PPS to D=8 the card emitted its NULL procedure byte at ~0.09s
instead of ~0.71s with a reader deadline of ~1.43s,
and the inactivity timeout fires 8x too early, which probably led to
unexplained wtime_exp errors.

Update wt when WI becomes known (end of ATR) and
where D changes (after the PPS response) + tests.

Change-Id: I4263176d6073029d01f9ff5b11a6311617956af6
ewild at

#22468 (Jul 28, 2026, 7:05:56 PM)

firmware: qmod: fix '@' debug command switching the wrong channel

Apparently copy paste mistake.

Change-Id: I9383adcfffab07ffa5f1fd3505e3aa244fb393ff
ewild at

#22467 (Jul 28, 2026, 7:05:55 PM)

firmware: sniffer: fix ~INS procedure byte comparison

(~g_tpdu.packet[1]) == byte can never be true.
Unary ~ applies the integer promotions first,
so for tpdu INS = 0xA4 lhs should be 0x5B but as int
it gets zero extended to at least 16 bits and then flipped,
so it is 0xFFFFFF5B = -165, byte promotes to 0..255.

The ack was therefore dead code -> fallthrough to SW1
branch, fails 0x6x/0x9x test, TPDU gets flagged
SNIFF_DATA_FLAG_ERROR_MALFORMED from what I can tell.
But I am losing track of all these arcane issues to be honest.

Narrow the complement back to 8 bits.
Fyi this is unrelated to signedness and not specific to ARM.

Change-Id: I800f50ef35356429d07aa685ea919e70ec34946e
ewild at

#22466 (Jul 28, 2026, 7:05:55 PM)

firmware: sniffer: do not drop maximum-length ATRs

7816-3 8.1/8.2.1 allow TS plus 32 bytes.
atr_i is a byte count, not an index, process_byte_atr() guards its own
store with the same condition before incrementing, so atr_i reaches 33.

Change-Id: Ic8398cbefc0b522946b6470fd0268fa70662dab1
ewild at

#22465 (Jul 28, 2026, 7:05:54 PM)

host: simtrace2-sniff: init exit code

Early failure i.e. of libusb return random values as exit code.

Change-Id: If920824d35c1f37efe16440b5fb190ca0fb19148
ewild at

#22464 (Jul 28, 2026, 7:04:46 PM)

contrib/flash.py: fix typos

Python has no versoin nor printf.

Change-Id: I4fd4d2592b44b3ae827e00ae73d8c451aa2ec18f
ewild at

#22463 (Jul 28, 2026, 7:04:05 PM)

firmware: card_emu: use Di in the waiting time

ISO 7816-3 section 10.2 defines WT = WI x 960 x Fi/f seconds,
store as etu, etu = Fi / (D x f) seconds, so the Fi cancels,
but the D does not:

WT [etu] = WI x 960 x D

cemu dropped both (?!) -> WI x 960.
The old comment explains why Fi can be dropped, which is right, but
what about Di ?!
sniffer gets it right (wt_wi * 960UL * wt_d), so the two state machines
disagreed here again, by up to a factor of 64???!!?!!?

This was fixed in osmo-ccid-firmware in 066489d in 2020 but not ported
to st2.

Additionally the waiting time was only recalculated at the end of the ATR,
where D is still 1 by definition, so a PPS increasing D reprogrammed the
baud rate but left the waiting time untouched??!

etu duration shrinks with D by the same factor, wall clock WT is
independent of D, which is the whole point.
The old code decreased the waiting time by a factor of D:
after a PPS to D=8 the card emitted its NULL procedure byte at ~0.09s
instead of ~0.71s with a reader deadline of ~1.43s,
and the inactivity timeout fires 8x too early, which probably led to
unexplained wtime_exp errors.

Update wt when WI becomes known (end of ATR) and
where D changes (after the PPS response) + tests.

Change-Id: I4263176d6073029d01f9ff5b11a6311617956af6
ewild at

#22462 (Jul 28, 2026, 7:04:05 PM)

firmware: protect uart_tx_queue against ISR

cardem:
- dispatch_usb_command_cardem() appends to uart_tx_queue from the main loop
- tx_byte_tpdu() dequeues from the USART IRQ handler @ NVIC prio 0

card_handle_reset() has the same issue, drains queue and
frees uart_tx_msg from main loop while the ISR may own them.

All of this needs protection against the irq.

Needs a fixed llist_add_tail_irqsafe(), which called __enable_irq() instead of
restoring the saved PRIMASK for some unknown reason?!?!?!?

Change-Id: I7d9cdcc56263b27dfd4649dfb1da1d67761ee923
ewild at

#22461 (Jul 28, 2026, 7:04:05 PM)

firmware: iso7816_3: fix F/D ratio for Di 8 and 9

iso7816_3_compute_fd_ratio() multiplied F by D for every d_index >= 8,
presumably because the upper half of ISO 7816-3 Table 8 encodes 1/D.

But 7816-3 2006 and 1997 differ!
That assumption is only true for the range 1010..1111, which in the
2006 version is RFU. Indices 1000 and 1001 are Di = 12 and Di = 20,
see iso7816_3_di_table[].

So right now Fi=372/Di=12 -> 372 * 12 = 4464 instead of 372 / 12 =
31.
In the cemu  value is rejected in emu_update_fidi()
and the old baud rate is silently kept.
In the sniffer update_fidi() programs US_FIDI as
4464 & 0x7ff = 368, which is garbage.

Use F/D for indices 1..9 and keep the legacy 1/D reading only for the RFU
range, where we cant really do anything useful anyway.

Change-Id: I44d6451d8b04aea2b0db7291b06a812afe84e52f
ewild at

#22460 (Jul 28, 2026, 7:04:05 PM)

host: simtrace2_api: do not log random memory

tx_cfg->features is logged before the memcpy() that fills it.
Looks like no one is using config.ac --enable-sanitize?

Change-Id: Id8369d312c8600ba9eea80c8f7782f196d7e20d1
ewild at

#22459 (Jul 28, 2026, 7:04:03 PM)

firmware: use the full 11 bit US_FIDI.FI_DI_RATIO

US_FIDI_FI_DI_RATIO_Msk is 0x7ff,
cemu rejected >= 0x400 in emu_update_fidi() and masked with 0x3ff
in card_emu_uart_update_fidi(), but update_fidi() used by
the sniffer already used 0x7ff.

-> ratios 1024..2047 are unusable in cemu, which is the entire upper
half of ISO 7816-3 Table 7 at Di=1.

A reader trying one of those in a PPS gets the proposal echoed and
accepted, after which the card keeps transmitting at the old rate.

FI_DI_RATIO is clock periods per bit -> larger ratio is a SLOWER link.
The old check rejected slow values but accepted Fi=372/Di=64, ratio 5 !?

Unify and use the register mask (= shifed by 0 so usable as value) and
reject ratios that do not fit rather than truncating to garbage dividers.

Change-Id: I6211dd5be7c5c5d2150af2aa37a403b33e6d340d
ewild at

#22458 (Jul 28, 2026, 7:04:02 PM)

firmware: sniffer: honor the ep argument of usb_msg_alloc_hdr()

Even though all callers pass the same endpoint anyway the arg should
be used and not discarded.

Change-Id: I1fa0097b9eef531900b359c7293a6c60040254e4
ewild at

#22457 (Jul 28, 2026, 7:04:01 PM)

firmware: sniffer: do not drop maximum-length ATRs

7816-3 8.1/8.2.1 allow TS plus 32 bytes.
atr_i is a byte count, not an index, process_byte_atr() guards its own
store with the same condition before incrementing, so atr_i reaches 33.

Change-Id: Ic8398cbefc0b522946b6470fd0268fa70662dab1
ewild at

#22456 (Jul 28, 2026, 7:04:00 PM)

firmware: card_emu: fix 7816-3 10.3.2 0=256 case

add_tpdu_byte() accumulates bytes received from the reader, but passes
reader_to_card = 0, but ISO 7816-3 10.3.2 says P3 == 0 means 256 not 0

Only reachable with P3 == 0 in a receive data phase, but
simtrace2-cardem-pcsc only requests PB_AND_RX when there is command data.

Fix this anyway.

Change-Id: I0fa4741bc1293549816595e6b4e8af9e22bcfbc1
ewild at

#22455 (Jul 28, 2026, 7:03:59 PM)

firmware: sniffer: fix ~INS procedure byte comparison

(~g_tpdu.packet[1]) == byte can never be true.
Unary ~ applies the integer promotions first,
so for tpdu INS = 0xA4 lhs should be 0x5B but as int
it gets zero extended to at least 16 bits and then flipped,
so it is 0xFFFFFF5B = -165, byte promotes to 0..255.

The ack was therefore dead code -> fallthrough to SW1
branch, fails 0x6x/0x9x test, TPDU gets flagged
SNIFF_DATA_FLAG_ERROR_MALFORMED from what I can tell.
But I am losing track of all these arcane issues to be honest.

Narrow the complement back to 8 bits.
Fyi this is unrelated to signedness and not specific to ARM.

Change-Id: I800f50ef35356429d07aa685ea919e70ec34946e
ewild at

#22454 (Jul 28, 2026, 7:03:59 PM)

firmware: qmod: fix '@' debug command switching the wrong channel

Apparently copy paste mistake.

Change-Id: I9383adcfffab07ffa5f1fd3505e3aa244fb393ff
ewild at

#22453 (Jul 28, 2026, 7:03:59 PM)

host: simtrace2-sniff: init exit code

Early failure i.e. of libusb return random values as exit code.

Change-Id: If920824d35c1f37efe16440b5fb190ca0fb19148
ewild at

#22452 (Jul 28, 2026, 9:47:48 AM)

libosmo-trx/ep: add TRX endpoint module

Add the osmo_trx_ep module, encapsulating the clock/ctrl/data UDP
socket management of the TRX protocol on top of osmo_io.  One endpoint
serves an (optional) clock socket plus N channels, each channel being
a ctrl + data socket pair.

The module is role-neutral: struct osmo_trx_ep_cfg carries a mode
(OSMO_TRX_EP_MODE_{L1,TRX}) selecting which side of the protocol the
endpoint implements.  The mode is needed to parse datagrams received
on the data sockets, as the wire format alone does not identify the
direction (BURST.ind vs BURST.req).  All local and remote ports are
derived from a single base port (default: 5700).

To avoid indirect calls on the hot path, the decoded Rx handlers
(osmo_trx_ep_rx_*) are plain function prototypes bound at link-time,
not function pointers.  The library provides weak default stubs to
stay link-complete (-no-undefined), so applications only implement
the handlers for the directions they consume, overriding the stubs.

The Tx path implements TRXDv2 PDU batching for burst requests:
osmo_trx_ep_send_burst_req() accumulates PDUs until it is called
with br == NULL (the batching breaker), like in osmo-bts-trx.

osmo-trx itself will not adopt this module: its per-channel/thread
socket ownership model (dedicated blocking-read threads per socket)
is incompatible with osmo_io's single-select-loop dispatch. It is
meant for osmo-bts, osmocom-bb/trxcon, and the upcoming C rewrite
of fake_trx.

Change-Id: I767fa43a9ca88be40c385f6dcb9de22891a6afc3
Vadim Yanitskiy at

#22451 (Jul 28, 2026, 9:47:16 AM)

libosmo-trx/client: make public API operate on parsed messages

The TRXC client engine and the TRX endpoint module did not compose:
osmo_trx_ep_rx_ctrl_msg() delivers a parsed struct osmo_trxc_msg,
while osmo_trxc_client_rx() accepts a raw datagram only; likewise,
the tx_msg call-back used to emit a serialized string, while
osmo_trx_ep_send_ctrl_msg() takes the parsed structure.  An
osmo_trx_ep user would have to needlessly re-parse and re-serialize
TRXC messages when gluing both modules together.

Make struct osmo_trxc_msg the currency at both module boundaries:

* add osmo_trxc_client_rx_msg(), accepting a parsed message;
  osmo_trxc_client_rx() becomes a parse-first convenience wrapper
  for applications managing the TRXC socket themselves;
* change the tx_msg call-back to take a parsed message: it's now
  up to the transport to serialize it (osmo_trx_ep users simply
  call osmo_trx_ep_send_ctrl_msg(), others osmo_trxc_msg_build()).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Idf53513d06be2337383601494b225b5722c93129
Vadim Yanitskiy at

#22450 (Jul 28, 2026, 9:46:45 AM)

Transceiver52M: implement TRXDv2 support

TRXDv2 was proposed and implemented in osmo-bts a while ago, but
osmo-trx was still stuck at TRXDv1.  This patch implements TRXDv2
and UL/DL burst batching using libosmo-trx API.

DL: driveTxPriorityQueue() now loops over osmo_trxd_burst_req_parse()
to handle datagrams potentially containing multiple batched BURST.req,
dispatching each via the new handleBurstReq().

UL: accumulate BURST.ind PDUs for the same FN into one msgb per channel
and flush as a single datagram once the next frame's PDU arrives or
the channel stops;  TRXDv0/v1 channels keep sending one PDU per
datagram via sendBurstInd().  Batching is unconditional for now;
making it configurable is left as a follow-up.

Change-Id: Ie6a33e3980b3ca4ab05a3d4221d5a8ba0132233d
Related: OS#5283
Vadim Yanitskiy at

#22449 (Jul 28, 2026, 9:46:42 AM)

tests: speed up InterthreadTest by shrinking the fuzz sleep

qWriter()/mapWriter() each had a 50% chance per iteration (20
iterations) of sleep(1), making the test take up to ~13s just to
exercise thread interleaving. The delay only needs to be long enough
to encourage preemption, not a full second.

Change-Id: Id6bc453f9217ae392dcd3288dfa6784c533f8eb6
Vadim Yanitskiy at

#22448 (Jul 28, 2026, 9:46:32 AM)

libosmo-trx/trxc: add SETSLOT parameter parser/builder

Add struct osmo_trxc_setslot plus osmo_trxc_setslot_parse()/_build()
for the "<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]" SETSLOT parameters,
including VAMOS combinations (VFF/VHH/VFH/HVHH) with per-sub-channel
TSC overrides.

Change-Id: I17a1176b1418edd0caf750d50acda0482d4ad04a
Vadim Yanitskiy at

#22447 (Jul 28, 2026, 9:46:25 AM)

libosmo-trx/trxd: support NOPE.{ind,req} in TRXDv0/v1 PDUs

TRXDv0 (and TRXDv1 in the downlink direction) has no MTS field, but
NOPE indications/requests do exist there in practice: the burst payload
is simply omitted, i.e. a header-only PDU.  This is how osmocom-bb's
trxcon transmits NOPE.req (see trx_if_handle_phyif_burst_req()).

Change-Id: I1a59f31d0f00c8509a016dc2bac71b6aa467f3a4
Vadim Yanitskiy at

#22446 (Jul 28, 2026, 9:45:33 AM)

libosmo-trx/client: add optional limit for retransmissions

The client used to retransmit an unacknowledged command forever, like
osmo-bts-trx does.  trxcon, however, gives up after 3 retransmission
attempts, concluding that the transceiver is offline.  Add a new API
function osmo_trxc_client_set_max_retrans() enabling this behavior:
once a command has been retransmitted the given number of times
without a response, the client escalates to the fatal_error call-back
(with rsp == NULL) and freezes the command queue.  The default (0)
retains the old behavior (no limit).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Ib90a032b38c69ae26023e726992d3f5f7e502fcf
Vadim Yanitskiy at

#22445 (Jul 28, 2026, 9:45:17 AM)

libosmo-trx: add TRXC/TRXD message codec

Introduce libosmo-trx: a shared implementation of the TRXC/TRXD
(OpenBTS-style TRX) protocol, to be used by osmo-trx, osmo-bts,
trxcon, and the upcoming C rewrite of fake_trx.

This initial version provides two I/O-free codec modules:

* trxd: TRXD PDU codec for BURST.ind and BURST.req
* trxc: verb-agnostic TRXC message codec (CMD/RSP/IND)

The codec logic is based on the existing implementations in
osmo-bts (f0ee51997470e1c3020ddb85082385ed43ba0c68).

Change-Id: I933fc417a67d0043f74b04626b7643c79e381492
Vadim Yanitskiy at

#22444 (Jul 28, 2026, 9:45:07 AM)

libosmo-trx/ep: flush pending TRXC messages on endpoint teardown

osmo_iofd_write_msgb() only enqueues the message; the actual
transmission happens asynchronously from within osmo_select_main().
An application sending a 'goodbye' command (like "CMD POWEROFF")
immediately before tearing down the endpoint would thus lose it:
osmo_iofd_free() discards the pending Tx queue.

Flush the TRXC Tx queue (best-effort) in osmo_trx_ep_close(), using
the new osmo_iofd_flush() API.  Pending Tx data batches are still
dropped, since queued bursts are worthless at teardown time.

Depends: libosmocore.git I4e09e91e472a4441977a2c199c07c2cb8005632f
Change-Id: I69e6a3bcf49afc3cfca4a72afdf459625cb91e56
Vadim Yanitskiy at

#22443 (Jul 28, 2026, 9:44:28 AM)

debian: add packaging for libosmo-trx

Add the usual Debian packaging files, closely following the ones in
libosmocore.git: the shared library package libosmotrx0, as well as
the -dev, -doc, and -dbg packages.

Change-Id: I56f0074ad121ecacb076b508d1adfdd71cce99ec
Vadim Yanitskiy at

#22442 (Jul 28, 2026, 9:44:17 AM)

libosmo-trx: generate Doxygen API documentation

Add Doxyfile.trx.in (based on Doxyfile.core.in from libosmocore.git,
upgraded using 'doxygen -u' to get rid of obsolete tags) and the
usual rules to build and install the HTML documentation, as well as
the --disable-doxygen configure option, like in other libosmo-*
projects.  Also document the missing buf/len parameters of
osmo_trxc_clock_ind_parse(), fixing the only Doxygen warning.

Change-Id: I54cf8c0c60215c666d8fa55dafec53379a2382d5
Vadim Yanitskiy at

#22441 (Jul 28, 2026, 9:44:16 AM)

libosmo-trx/trxc: enlarge the params buffer

The SETFH command (implemented by trxcon and fake_trx) carries the
whole Mobile Allocation as pairs of Rx/Tx frequencies in kHz:

  CMD SETFH <HSN> <MAIO> <RXF1> <TXF1> [... <RXFN> <TXFN>]

With up to 64 ARFCNs in the Mobile Allocation, the parameters string
alone can exceed 1000 characters, far beyond the old 128 byte limit.

Derive OSMO_TRXC_PARAMS_LEN_MAX from OSMO_TRXC_MSG_BUF_SIZE, so that
any message ("RSP " + verb + status + params) still fits the
recommended socket buffer size.  Also add the OSMO_TRXC_CMD_SETFH
verb constant and a regression test doing a round-trip of a maximum
size SETFH command (64 ARFCNs).

Change-Id: I2f65b213f5ada499eea4abae87d3727057e03e22
Vadim Yanitskiy at

#22440 (Jul 28, 2026, 9:43:55 AM)

Transceiver52M: make TRXDv2 burst batching configurable

Add a "trxd-batch (disable|enable)" VTY command under the TRX node
(default: enable) to allow disabling per-frame BURST.ind batching
even when TRXDv2 is negotiated, e.g. to trade datagram count for
latency.

Change-Id: I2f58f87d85de5254bae6d7a606dffcd0ad4069d5
Related: OS#5283
Vadim Yanitskiy at

#22439 (Jul 28, 2026, 9:43:53 AM)

libosmo-trx/client: add TRXC client (command queue) API

Add the osmo_trxc_client module: a transport-agnostic generalization
of the TRXC command handling logic in osmo-bts-trx (trx_if.c):

* command queue with a single command in flight;
* retransmission on response timeout (default: 2 s);
* suppression of consecutive duplicate commands;
* RSP<->CMD matching, optionally including the parameters;
* filtering of duplicate responses caused by retransmissions;
* escalation of NACKed critical commands (OSMO_TRXC_F_CRITICAL)
  to the fatal_error call-back;
* TRXD PDU version negotiation (SETFORMAT), incl. the fallback to
  version 0 for old transceivers rejecting it with 'RSP ERR 1'.

The client neither opens nor owns a socket: the application transmits
serialized messages in the tx_msg call-back and feeds received
datagrams into osmo_trxc_client_rx().  The response call-back may
return N > 0 to request a re-transmission of the same command after
N seconds (e.g. POWERON retry, as implemented in osmo-bts-trx).

Change-Id: I817e394f74a10e3adae4a0b58342c82acdf0794e
Vadim Yanitskiy at

#22438 (Jul 28, 2026, 9:43:30 AM)

Transceiver52M: migrate to libosmo-trx

Replace the local TRXC/TRXD implementation with libosmo-trx's shared
osmo_trxc_msg/osmo_trxd_burst_{ind,req} API, including SETSLOT parsing
via osmo_trxc_setslot_parse()/_build().  Take a chance to fix SETSLOT
to always send a response, distinguishing bogus input from unsupported
VAMOS channel combinations.

Only the TRXC/TRXD build/parse API is used here, not the osmo_trx_ep
endpoint API: osmo-trx runs its socket I/O on dedicated threads that
don't drive osmo_select_main(), which osmo_trx_ep depends on.

Change-Id: I458ec85c56e2101d073c8c35f11c147191c4ea0c
Related: OS#5283
Vadim Yanitskiy at

#22437 (Jul 28, 2026, 9:43:10 AM)

libosmo-trx/client: make public API operate on parsed messages

The TRXC client engine and the TRX endpoint module did not compose:
osmo_trx_ep_rx_ctrl_msg() delivers a parsed struct osmo_trxc_msg,
while osmo_trxc_client_rx() accepts a raw datagram only; likewise,
the tx_msg call-back used to emit a serialized string, while
osmo_trx_ep_send_ctrl_msg() takes the parsed structure.  An
osmo_trx_ep user would have to needlessly re-parse and re-serialize
TRXC messages when gluing both modules together.

Make struct osmo_trxc_msg the currency at both module boundaries:

* add osmo_trxc_client_rx_msg(), accepting a parsed message;
  osmo_trxc_client_rx() becomes a parse-first convenience wrapper
  for applications managing the TRXC socket themselves;
* change the tx_msg call-back to take a parsed message: it's now
  up to the transport to serialize it (osmo_trx_ep users simply
  call osmo_trx_ep_send_ctrl_msg(), others osmo_trxc_msg_build()).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Idf53513d06be2337383601494b225b5722c93129
Vadim Yanitskiy at

#22436 (Jul 28, 2026, 9:41:56 AM)

libosmo-trx/ep: add TRX endpoint module

Add the osmo_trx_ep module, encapsulating the clock/ctrl/data UDP
socket management of the TRX protocol on top of osmo_io.  One endpoint
serves an (optional) clock socket plus N channels, each channel being
a ctrl + data socket pair.

The module is role-neutral: struct osmo_trx_ep_cfg carries a mode
(OSMO_TRX_EP_MODE_{L1,TRX}) selecting which side of the protocol the
endpoint implements.  The mode is needed to parse datagrams received
on the data sockets, as the wire format alone does not identify the
direction (BURST.ind vs BURST.req).  All local and remote ports are
derived from a single base port (default: 5700).

To avoid indirect calls on the hot path, the decoded Rx handlers
(osmo_trx_ep_rx_*) are plain function prototypes bound at link-time,
not function pointers.  The library provides weak default stubs to
stay link-complete (-no-undefined), so applications only implement
the handlers for the directions they consume, overriding the stubs.

The Tx path implements TRXDv2 PDU batching for burst requests:
osmo_trx_ep_send_burst_req() accumulates PDUs until it is called
with br == NULL (the batching breaker), like in osmo-bts-trx.

osmo-trx itself will not adopt this module: its per-channel/thread
socket ownership model (dedicated blocking-read threads per socket)
is incompatible with osmo_io's single-select-loop dispatch. It is
meant for osmo-bts, osmocom-bb/trxcon, and the upcoming C rewrite
of fake_trx.

Change-Id: I767fa43a9ca88be40c385f6dcb9de22891a6afc3
Vadim Yanitskiy at

#22435 (Jul 28, 2026, 9:41:48 AM)

tests: speed up InterthreadTest by shrinking the fuzz sleep

qWriter()/mapWriter() each had a 50% chance per iteration (20
iterations) of sleep(1), making the test take up to ~13s just to
exercise thread interleaving. The delay only needs to be long enough
to encourage preemption, not a full second.

Change-Id: Id6bc453f9217ae392dcd3288dfa6784c533f8eb6
Vadim Yanitskiy at

#22434 (Jul 28, 2026, 9:41:45 AM)

Transceiver52M: implement TRXDv2 support

TRXDv2 was proposed and implemented in osmo-bts a while ago, but
osmo-trx was still stuck at TRXDv1.  This patch implements TRXDv2
and UL/DL burst batching using libosmo-trx API.

DL: driveTxPriorityQueue() now loops over osmo_trxd_burst_req_parse()
to handle datagrams potentially containing multiple batched BURST.req,
dispatching each via the new handleBurstReq().

UL: accumulate BURST.ind PDUs for the same FN into one msgb per channel
and flush as a single datagram once the next frame's PDU arrives or
the channel stops;  TRXDv0/v1 channels keep sending one PDU per
datagram via sendBurstInd().  Batching is unconditional for now;
making it configurable is left as a follow-up.

Change-Id: Ie6a33e3980b3ca4ab05a3d4221d5a8ba0132233d
Related: OS#5283
Vadim Yanitskiy at

#22433 (Jul 28, 2026, 9:41:45 AM)

libosmo-trx/trxc: add SETSLOT parameter parser/builder

Add struct osmo_trxc_setslot plus osmo_trxc_setslot_parse()/_build()
for the "<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]" SETSLOT parameters,
including VAMOS combinations (VFF/VHH/VFH/HVHH) with per-sub-channel
TSC overrides.

Change-Id: I17a1176b1418edd0caf750d50acda0482d4ad04a
Vadim Yanitskiy at

#22432 (Jul 28, 2026, 9:41:31 AM)

libosmo-trx/ep: flush pending TRXC messages on endpoint teardown

osmo_iofd_write_msgb() only enqueues the message; the actual
transmission happens asynchronously from within osmo_select_main().
An application sending a 'goodbye' command (like "CMD POWEROFF")
immediately before tearing down the endpoint would thus lose it:
osmo_iofd_free() discards the pending Tx queue.

Flush the TRXC Tx queue (best-effort) in osmo_trx_ep_close(), using
the new osmo_iofd_flush() API.  Pending Tx data batches are still
dropped, since queued bursts are worthless at teardown time.

Depends: libosmocore.git I4e09e91e472a4441977a2c199c07c2cb8005632f
Change-Id: I69e6a3bcf49afc3cfca4a72afdf459625cb91e56
Vadim Yanitskiy at

#22431 (Jul 28, 2026, 9:41:16 AM)

libosmo-trx: add TRXC/TRXD message codec

Introduce libosmo-trx: a shared implementation of the TRXC/TRXD
(OpenBTS-style TRX) protocol, to be used by osmo-trx, osmo-bts,
trxcon, and the upcoming C rewrite of fake_trx.

This initial version provides two I/O-free codec modules:

* trxd: TRXD PDU codec for BURST.ind and BURST.req
* trxc: verb-agnostic TRXC message codec (CMD/RSP/IND)

The codec logic is based on the existing implementations in
osmo-bts (f0ee51997470e1c3020ddb85082385ed43ba0c68).

Change-Id: I933fc417a67d0043f74b04626b7643c79e381492
Vadim Yanitskiy at

#22430 (Jul 28, 2026, 9:41:07 AM)

debian: add packaging for libosmo-trx

Add the usual Debian packaging files, closely following the ones in
libosmocore.git: the shared library package libosmotrx0, as well as
the -dev, -doc, and -dbg packages.

Change-Id: I56f0074ad121ecacb076b508d1adfdd71cce99ec
Vadim Yanitskiy at

#22429 (Jul 28, 2026, 9:40:08 AM)

libosmo-trx/trxd: support NOPE.{ind,req} in TRXDv0/v1 PDUs

TRXDv0 (and TRXDv1 in the downlink direction) has no MTS field, but
NOPE indications/requests do exist there in practice: the burst payload
is simply omitted, i.e. a header-only PDU.  This is how osmocom-bb's
trxcon transmits NOPE.req (see trx_if_handle_phyif_burst_req()).

Change-Id: I1a59f31d0f00c8509a016dc2bac71b6aa467f3a4
Vadim Yanitskiy at

#22428 (Jul 28, 2026, 9:39:11 AM)

libosmo-trx: generate Doxygen API documentation

Add Doxyfile.trx.in (based on Doxyfile.core.in from libosmocore.git,
upgraded using 'doxygen -u' to get rid of obsolete tags) and the
usual rules to build and install the HTML documentation, as well as
the --disable-doxygen configure option, like in other libosmo-*
projects.  Also document the missing buf/len parameters of
osmo_trxc_clock_ind_parse(), fixing the only Doxygen warning.

Change-Id: I54cf8c0c60215c666d8fa55dafec53379a2382d5
Vadim Yanitskiy at

#22427 (Jul 28, 2026, 9:39:01 AM)

libosmo-trx/trxc: enlarge the params buffer

The SETFH command (implemented by trxcon and fake_trx) carries the
whole Mobile Allocation as pairs of Rx/Tx frequencies in kHz:

  CMD SETFH <HSN> <MAIO> <RXF1> <TXF1> [... <RXFN> <TXFN>]

With up to 64 ARFCNs in the Mobile Allocation, the parameters string
alone can exceed 1000 characters, far beyond the old 128 byte limit.

Derive OSMO_TRXC_PARAMS_LEN_MAX from OSMO_TRXC_MSG_BUF_SIZE, so that
any message ("RSP " + verb + status + params) still fits the
recommended socket buffer size.  Also add the OSMO_TRXC_CMD_SETFH
verb constant and a regression test doing a round-trip of a maximum
size SETFH command (64 ARFCNs).

Change-Id: I2f65b213f5ada499eea4abae87d3727057e03e22
Vadim Yanitskiy at

#22426 (Jul 28, 2026, 9:39:00 AM)

libosmo-trx/client: add optional limit for retransmissions

The client used to retransmit an unacknowledged command forever, like
osmo-bts-trx does.  trxcon, however, gives up after 3 retransmission
attempts, concluding that the transceiver is offline.  Add a new API
function osmo_trxc_client_set_max_retrans() enabling this behavior:
once a command has been retransmitted the given number of times
without a response, the client escalates to the fatal_error call-back
(with rsp == NULL) and freezes the command queue.  The default (0)
retains the old behavior (no limit).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Ib90a032b38c69ae26023e726992d3f5f7e502fcf
Vadim Yanitskiy at

#22425 (Jul 28, 2026, 9:38:59 AM)

Transceiver52M: migrate to libosmo-trx

Replace the local TRXC/TRXD implementation with libosmo-trx's shared
osmo_trxc_msg/osmo_trxd_burst_{ind,req} API, including SETSLOT parsing
via osmo_trxc_setslot_parse()/_build().  Take a chance to fix SETSLOT
to always send a response, distinguishing bogus input from unsupported
VAMOS channel combinations.

Only the TRXC/TRXD build/parse API is used here, not the osmo_trx_ep
endpoint API: osmo-trx runs its socket I/O on dedicated threads that
don't drive osmo_select_main(), which osmo_trx_ep depends on.

Change-Id: I458ec85c56e2101d073c8c35f11c147191c4ea0c
Related: OS#5283
Vadim Yanitskiy at

#22424 (Jul 28, 2026, 9:38:59 AM)

Transceiver52M: make TRXDv2 burst batching configurable

Add a "trxd-batch (disable|enable)" VTY command under the TRX node
(default: enable) to allow disabling per-frame BURST.ind batching
even when TRXDv2 is negotiated, e.g. to trade datagram count for
latency.

Change-Id: I2f58f87d85de5254bae6d7a606dffcd0ad4069d5
Related: OS#5283
Vadim Yanitskiy at

#22423 (Jul 28, 2026, 9:38:59 AM)

libosmo-trx/client: add TRXC client (command queue) API

Add the osmo_trxc_client module: a transport-agnostic generalization
of the TRXC command handling logic in osmo-bts-trx (trx_if.c):

* command queue with a single command in flight;
* retransmission on response timeout (default: 2 s);
* suppression of consecutive duplicate commands;
* RSP<->CMD matching, optionally including the parameters;
* filtering of duplicate responses caused by retransmissions;
* escalation of NACKed critical commands (OSMO_TRXC_F_CRITICAL)
  to the fatal_error call-back;
* TRXD PDU version negotiation (SETFORMAT), incl. the fallback to
  version 0 for old transceivers rejecting it with 'RSP ERR 1'.

The client neither opens nor owns a socket: the application transmits
serialized messages in the tx_msg call-back and feeds received
datagrams into osmo_trxc_client_rx().  The response call-back may
return N > 0 to request a re-transmission of the same command after
N seconds (e.g. POWERON retry, as implemented in osmo-bts-trx).

Change-Id: I817e394f74a10e3adae4a0b58342c82acdf0794e
Vadim Yanitskiy at

#22422 (Jul 28, 2026, 9:37:53 AM)

osmo_io: add osmo_iofd_flush() to transmit the pending Tx queue

osmo_iofd_write_msgb() and friends only enqueue the given message;
the actual transmission happens asynchronously from within
osmo_select_main().  An application that needs to say 'goodbye'
right before calling osmo_iofd_free() (think of a connection
teardown datagram, like TRXC "CMD POWEROFF") currently has no way
to do so reliably: osmo_iofd_free() discards the Tx queue, so a
message enqueued in the same event loop iteration never reaches
the socket.

Add osmo_iofd_flush(), which synchronously transmits the pending
Tx queue, stopping on -EAGAIN or other errors.  Only the poll
backend implements it for now;  the io_uring backend returns
-ENOTSUP, since in-flight SQE submissions make a synchronous
flush non-trivial there.

Change-Id: I4e09e91e472a4441977a2c199c07c2cb8005632f
Vadim Yanitskiy at

#22421 (Jul 28, 2026, 9:37:52 AM)

osmo_io: add osmo_iofd_flush() to transmit the pending Tx queue

osmo_iofd_write_msgb() and friends only enqueue the given message;
the actual transmission happens asynchronously from within
osmo_select_main().  An application that needs to say 'goodbye'
right before calling osmo_iofd_free() (think of a connection
teardown datagram, like TRXC "CMD POWEROFF") currently has no way
to do so reliably: osmo_iofd_free() discards the Tx queue, so a
message enqueued in the same event loop iteration never reaches
the socket.

Add osmo_iofd_flush(), which synchronously transmits the pending
Tx queue, stopping on -EAGAIN or other errors.  Only the poll
backend implements it for now;  the io_uring backend returns
-ENOTSUP, since in-flight SQE submissions make a synchronous
flush non-trivial there.

Change-Id: I4e09e91e472a4441977a2c199c07c2cb8005632f
Vadim Yanitskiy at

#22420 (Jul 28, 2026, 9:37:51 AM)

osmo_io: add osmo_iofd_flush() to transmit the pending Tx queue

osmo_iofd_write_msgb() and friends only enqueue the given message;
the actual transmission happens asynchronously from within
osmo_select_main().  An application that needs to say 'goodbye'
right before calling osmo_iofd_free() (think of a connection
teardown datagram, like TRXC "CMD POWEROFF") currently has no way
to do so reliably: osmo_iofd_free() discards the Tx queue, so a
message enqueued in the same event loop iteration never reaches
the socket.

Add osmo_iofd_flush(), which synchronously transmits the pending
Tx queue, stopping on -EAGAIN or other errors.  Only the poll
backend implements it for now;  the io_uring backend returns
-ENOTSUP, since in-flight SQE submissions make a synchronous
flush non-trivial there.

Change-Id: I4e09e91e472a4441977a2c199c07c2cb8005632f
Vadim Yanitskiy at

#22419 (Jul 28, 2026, 9:08:46 AM)

README: update

* Convert to markdown
* Add a short summary on top
* Modernize installation instructions
* Change the example from deprecated openbsc and deprecated
  osmodumpdoc.py to libosmocore's osmo-ns-dummy and osmotestconfig.py
* Remove mention of twisted_ipa.py, as it was removed in 5d0fac9d

Change-Id: I13c6327ca210e29cde3f9bb75c93c892682a5a28
Oliver Smith at

#22418 (Jul 28, 2026, 9:08:45 AM)

README: update

* Convert to markdown
* Add a short summary on top
* Modernize installation instructions
* Change the example from deprecated openbsc and deprecated
  osmodumpdoc.py to libosmocore's osmo-ns-dummy and osmotestconfig.py
* Remove mention of twisted_ipa.py, as it was removed in 5d0fac9d

Change-Id: I13c6327ca210e29cde3f9bb75c93c892682a5a28
Oliver Smith at

#22417 (Jul 28, 2026, 9:04:07 AM)

README: update

* Convert to markdown
* Add a short summary on top
* Modernize installation instructions
* Change the example from deprecated openbsc and deprecated
  osmodumpdoc.py to libosmocore's osmo-ns-dummy and osmotestconfig.py
* Remove mention of twisted_ipa.py, as it was removed in 5d0fac9d

Change-Id: I13c6327ca210e29cde3f9bb75c93c892682a5a28
Oliver Smith at

#22416 (Jul 28, 2026, 9:04:07 AM)

README: update

* Convert to markdown
* Add a short summary on top
* Modernize installation instructions
* Change the example from deprecated openbsc and deprecated
  osmodumpdoc.py to libosmocore's osmo-ns-dummy and osmotestconfig.py
* Remove mention of twisted_ipa.py, as it was removed in 5d0fac9d

Change-Id: I13c6327ca210e29cde3f9bb75c93c892682a5a28
Oliver Smith at

#22415 (Jul 28, 2026, 9:03:47 AM)

README: update

* Convert to markdown
* Add a short summary on top
* Modernize installation instructions
* Change the example from deprecated openbsc and deprecated
  osmodumpdoc.py to libosmocore's osmo-ns-dummy and osmotestconfig.py
* Remove mention of twisted_ipa.py, as it was removed in 5d0fac9d

Change-Id: I13c6327ca210e29cde3f9bb75c93c892682a5a28
Oliver Smith at

#22414 (Jul 28, 2026, 9:03:45 AM)

README: update

* Convert to markdown
* Add a short summary on top
* Modernize installation instructions
* Change the example from deprecated openbsc and deprecated
  osmodumpdoc.py to libosmocore's osmo-ns-dummy and osmotestconfig.py
* Remove mention of twisted_ipa.py, as it was removed in 5d0fac9d

Change-Id: I13c6327ca210e29cde3f9bb75c93c892682a5a28
Oliver Smith at

#22413 (Jul 27, 2026, 1:46:08 PM)

tests/v42bis: Remove unused variable

Change-Id: I715e57513ee62b7c61492a1d206232a5db107ea0
Pau Espin Pedrol at

#22412 (Jul 27, 2026, 1:46:08 PM)

tests/v42bis: Remove unused variable

Change-Id: I715e57513ee62b7c61492a1d206232a5db107ea0
Pau Espin Pedrol at

#22411 (Jul 27, 2026, 1:45:16 PM)

sndcp: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: Ie2bd3d2935cd7e0ad023a163c9be9a05b83fbc5e
Pau Espin Pedrol at

#22410 (Jul 27, 2026, 1:45:14 PM)

sndcp: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: Ie2bd3d2935cd7e0ad023a163c9be9a05b83fbc5e
Pau Espin Pedrol at

#22409 (Jul 27, 2026, 1:38:22 PM)

sndcp: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: I110e3bca19f726382beff673bc91b494e0fba912
Pau Espin Pedrol at

#22408 (Jul 27, 2026, 1:38:19 PM)

sndcp: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: I110e3bca19f726382beff673bc91b494e0fba912
Pau Espin Pedrol at

#22407 (Jul 27, 2026, 1:29:36 PM)

tests/osmo_io: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: I0bdfe5ed6803042277ed8d21171b5f9c11495ca3
Pau Espin Pedrol at

#22406 (Jul 27, 2026, 1:29:36 PM)

tests/osmo_io: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: I0bdfe5ed6803042277ed8d21171b5f9c11495ca3
Pau Espin Pedrol at

#22405 (Jul 27, 2026, 1:29:34 PM)

tests/osmo_io: Remove unused variable

gcc 16.1.1 warns about it.

Change-Id: I0bdfe5ed6803042277ed8d21171b5f9c11495ca3
Pau Espin Pedrol at

#22404 (Jul 23, 2026, 11:39:02 PM)

translate AUTS field in UTRAN as well as E-UTRAN requests

Change-Id: Ie3ecfc668cff50ebdbc190e8384e891e05e7ad27
q at

#22403 (Jul 23, 2026, 11:39:01 PM)

translate AUTS field in UTRAN as well as E-UTRAN requests

Change-Id: Ie3ecfc668cff50ebdbc190e8384e891e05e7ad27
q at

#22402 (Jul 22, 2026, 4:01:32 PM)

set Item-Number in UTRAN and GERAN vectors

Change-Id: I75da04b806f23452c9b4cfaad0446dceb32a0369
q at

#22401 (Jul 22, 2026, 4:01:30 PM)

set Item-Number in UTRAN and GERAN vectors

Change-Id: I75da04b806f23452c9b4cfaad0446dceb32a0369
q at

#22400 (Jul 22, 2026, 9:32:20 AM)

Bump version: 1.14.0.6-ac289-dirty → 1.14.1

Change-Id: I671d21db38d915370e7191ada34ff640ee3a49dd
Oliver Smith at

#22399 (Jul 22, 2026, 9:32:20 AM)

Bump version: 1.14.0.6-ac289-dirty → 1.14.1

Change-Id: I671d21db38d915370e7191ada34ff640ee3a49dd
Oliver Smith at

#22398 (Jul 22, 2026, 9:32:18 AM)

Bump version: 1.14.0.6-ac289-dirty → 1.14.1

Change-Id: I671d21db38d915370e7191ada34ff640ee3a49dd
Oliver Smith at

#22397 (Jul 21, 2026, 6:20:29 PM)

gsm/Makefile.am: add missing kdf/crypto.h

Change-Id: I55fb391d61969357bb55f0834b389f9c701554aa
lynxis at

#22396 (Jul 21, 2026, 6:20:26 PM)

gsm/Makefile.am: add missing kdf/crypto.h

Change-Id: I55fb391d61969357bb55f0834b389f9c701554aa
lynxis at

#22395 (Jul 21, 2026, 6:20:25 PM)

gsm/Makefile.am: add missing kdf/crypto.h

Change-Id: I55fb391d61969357bb55f0834b389f9c701554aa
lynxis at

#22394 (Jul 21, 2026, 12:15:39 PM)

Bump version: 0.1.2

Change-Id: I350f6ed32b1c9543c2985c7991ee3d5a6dce1c1c
Oliver Smith at

#22393 (Jul 21, 2026, 12:15:39 PM)

Bump version: 0.1.2

Change-Id: I350f6ed32b1c9543c2985c7991ee3d5a6dce1c1c
Oliver Smith at

#22392 (Jul 17, 2026, 11:29:07 AM)

rebar.lock: use a more recent version of gen_netlink

This works around a compiler bug in OTP 29.0.3 [1].

Change-Id: Iae0c4b3827c7ae5c8076fbf782adf8db02d975ea
Related: [1] https://github.com/erlang/otp/issues/11368
Related: OS#7025
Vadim Yanitskiy at

#22391 (Jul 17, 2026, 11:29:04 AM)

rebar.lock: use a more recent version of gen_netlink

This works around a compiler bug in OTP 29.0.3 [1].

Change-Id: Iae0c4b3827c7ae5c8076fbf782adf8db02d975ea
Related: [1] https://github.com/erlang/otp/issues/11368
Related: OS#7025
Vadim Yanitskiy at

#22390 (Jul 17, 2026, 7:03:50 AM)

Bump version: 1.9.2.3-2ef2 → 1.9.3

Change-Id: I276fec3ff862da688eefd9b2738fedbdedd4ef32
Oliver Smith at

#22389 (Jul 17, 2026, 7:03:47 AM)

Bump version: 1.9.2.3-2ef2 → 1.9.3

Change-Id: I276fec3ff862da688eefd9b2738fedbdedd4ef32
Oliver Smith at

#22388 (Jul 16, 2026, 2:59:16 PM)

Modernize python packaging

When building the debian package, we get the following deprecation
warning. Modernize the python packaging to fix it, before it stops
working altogether. Keep the old setup.py in contrib so we can still
build for older debian releases.

Fix for:
  SetuptoolsDeprecationWarning: setup.py install is deprecated.
  !!

          ********************************************************************************
          Please avoid running ``setup.py`` directly.
          Instead, use pypa/build, pypa/installer or other
          standards-based tools.

          See https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html for details.
          ********************************************************************************

  !!

Depends: docker-playground I9bb5d13897dbf1be9855c4eba29c6b3a2c35729c
Change-Id: I186544163ab02834c33f1363f3a06cd380898f56
Oliver Smith at

#22387 (Jul 16, 2026, 2:59:13 PM)

Modernize python packaging

When building the debian package, we get the following deprecation
warning. Modernize the python packaging to fix it, before it stops
working altogether. Keep the old setup.py in contrib so we can still
build for older debian releases.

Fix for:
  SetuptoolsDeprecationWarning: setup.py install is deprecated.
  !!

          ********************************************************************************
          Please avoid running ``setup.py`` directly.
          Instead, use pypa/build, pypa/installer or other
          standards-based tools.

          See https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html for details.
          ********************************************************************************

  !!

Depends: docker-playground I9bb5d13897dbf1be9855c4eba29c6b3a2c35729c
Change-Id: I186544163ab02834c33f1363f3a06cd380898f56
Oliver Smith at

#22386 (Jul 16, 2026, 1:29:39 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22385 (Jul 16, 2026, 1:29:38 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22384 (Jul 16, 2026, 1:27:06 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22383 (Jul 16, 2026, 1:26:49 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22382 (Jul 15, 2026, 6:45:28 PM)

rebar.config: use more recent rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  Our pull request [1] has
been merged upstream, but no release has been tagged yet.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Related: OS#7025
Vadim Yanitskiy at

#22381 (Jul 15, 2026, 6:45:28 PM)

rebar.config: use more recent rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  Our pull request [1] has
been merged upstream, but no release has been tagged yet.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Related: OS#7025
Vadim Yanitskiy at

#22380 (Jul 15, 2026, 5:42:51 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22379 (Jul 15, 2026, 5:42:46 PM)

firmware: Drop CEMU_TX_DATA when sim is in-active

When the emulated sim is in reset or without power, drop
CEMU_TX_DATA.

Change-Id: I796e548225a742cddfde12bd6a60e4d2e5c04c8f
lynxis at

#22378 (Jul 15, 2026, 5:42:46 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22377 (Jul 15, 2026, 5:42:46 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22376 (Jul 15, 2026, 5:42:46 PM)

firmware: Drop CEMU_TX_DATA when sim is in-active

When the emulated sim is in reset or without power, drop
CEMU_TX_DATA.

Change-Id: I796e548225a742cddfde12bd6a60e4d2e5c04c8f
lynxis at

#22375 (Jul 15, 2026, 5:42:44 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22374 (Jul 15, 2026, 5:32:47 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config
* vty tests

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22373 (Jul 15, 2026, 5:32:46 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config
* vty tests

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22372 (Jul 15, 2026, 5:29:07 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config
* vty tests

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22371 (Jul 15, 2026, 5:29:06 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config
* vty tests

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22370 (Jul 15, 2026, 5:12:52 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config
* vty tests

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22369 (Jul 15, 2026, 5:12:51 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config
* vty tests

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22368 (Jul 15, 2026, 4:58:42 PM)

TCAP: Refactoring unroutable messages into own function

In preparation of adding another method to handle those.

Change-Id: Ib4d114273423730418458767d17b11de9bd815d4
lynxis at

#22367 (Jul 15, 2026, 4:58:42 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22366 (Jul 15, 2026, 4:58:42 PM)

TCAP: implement a fallback routing

If a TCAP message from an ongoing session can't be routed by
either the TCAP session cache or by the destination TID to a known
node, allow to route the MSU to a different destination.

Change-Id: I3e4e634b38a1845c2ce62a3805ff91a530520d88
lynxis at

#22365 (Jul 15, 2026, 4:58:41 PM)

WIP: implement loop prevention over AS groups

TODOs:

* show as: groups
* show asp: groups
* show group GROUPNAME
* write vty config

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22364 (Jul 15, 2026, 4:58:41 PM)

TCAP: Refactoring unroutable messages into own function

In preparation of adding another method to handle those.

Change-Id: Ib4d114273423730418458767d17b11de9bd815d4
lynxis at

#22363 (Jul 15, 2026, 4:58:41 PM)

TCAP: implement a fallback routing

If a TCAP message from an ongoing session can't be routed by
either the TCAP session cache or by the destination TID to a known
node, allow to route the MSU to a different destination.

Change-Id: I3e4e634b38a1845c2ce62a3805ff91a530520d88
lynxis at

#22362 (Jul 15, 2026, 9:55:27 AM)

systemd: run db-upgrade script in ExecStartPre

We have seen in CI jobs that calling the DB upgrade script from
debian/postinst does not work reliably.

When doing a fresh install of osmo-hlr, it usually works as expected:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: nothing to do (no existing database)

But sometimes:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: database upgrade is required
  osmo-hlr-post-upgrade: stopping osmo-hlr service
  osmo-hlr-post-upgrade: creating backup: /var/lib/osmocom/hlr.db.20260706135658.bak
  osmo-hlr-post-upgrade: performing database upgrade
  <0001> db.c:600 using database: /var/lib/osmocom/hlr.db
  <0001> db.c:103 (283) recovered 4 frames from WAL file /var/lib/osmocom/hlr.db-wal
  <0001> db.c:679 Database '/var/lib/osmocom/hlr.db' has HLR DB schema version 0
  <0001> db.c:103 (1) duplicate column name: last_lu_seen in "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL"
  <0001> db.c:248 Unable to prepare SQL statement 'ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL'
  <0001> db.c:318 Unable to update HLR database schema to version 1
  <0001> db.c:685 Failed to upgrade HLR DB schema to version 1: (rc=1) duplicate column name: last_lu_seen
  <0000> hlr_db_tool.c:509 Error opening database

It seems that osmo-hlr can get started before the osmo-hlr-post-upgrade
script runs, then starts to create the database with the current schema,
and gets stopped before it is done, leading to the failure above.

Rename the script to osmo-hlr-db-upgrade.sh, remove logic for stopping
and starting the service and let systemd call it in ExecStartPre. That
way we are sure that it runs *before* osmo-hlr starts up.

Related: SYS#8125
Change-Id: If13f4c8b49397e6630956e92a7825843c7d55ebd
Oliver Smith at

#22361 (Jul 15, 2026, 9:55:26 AM)

systemd: run db-upgrade script in ExecStartPre

We have seen in CI jobs that calling the DB upgrade script from
debian/postinst does not work reliably.

When doing a fresh install of osmo-hlr, it usually works as expected:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: nothing to do (no existing database)

But sometimes:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: database upgrade is required
  osmo-hlr-post-upgrade: stopping osmo-hlr service
  osmo-hlr-post-upgrade: creating backup: /var/lib/osmocom/hlr.db.20260706135658.bak
  osmo-hlr-post-upgrade: performing database upgrade
  <0001> db.c:600 using database: /var/lib/osmocom/hlr.db
  <0001> db.c:103 (283) recovered 4 frames from WAL file /var/lib/osmocom/hlr.db-wal
  <0001> db.c:679 Database '/var/lib/osmocom/hlr.db' has HLR DB schema version 0
  <0001> db.c:103 (1) duplicate column name: last_lu_seen in "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL"
  <0001> db.c:248 Unable to prepare SQL statement 'ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL'
  <0001> db.c:318 Unable to update HLR database schema to version 1
  <0001> db.c:685 Failed to upgrade HLR DB schema to version 1: (rc=1) duplicate column name: last_lu_seen
  <0000> hlr_db_tool.c:509 Error opening database

It seems that osmo-hlr can get started before the osmo-hlr-post-upgrade
script runs, then starts to create the database with the current schema,
and gets stopped before it is done, leading to the failure above.

Rename the script to osmo-hlr-db-upgrade.sh, remove logic for stopping
and starting the service and let systemd call it in ExecStartPre. That
way we are sure that it runs *before* osmo-hlr starts up.

Related: SYS#8125
Change-Id: If13f4c8b49397e6630956e92a7825843c7d55ebd
Oliver Smith at

#22360 (Jul 15, 2026, 9:50:28 AM)

systemd: run db-upgrade script in ExecStartPre

We have seen in CI jobs that calling the DB upgrade script from
debian/postinst does not work reliably.

When doing a fresh install of osmo-hlr, it usually works as expected:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: nothing to do (no existing database)

But sometimes:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: database upgrade is required
  osmo-hlr-post-upgrade: stopping osmo-hlr service
  osmo-hlr-post-upgrade: creating backup: /var/lib/osmocom/hlr.db.20260706135658.bak
  osmo-hlr-post-upgrade: performing database upgrade
  <0001> db.c:600 using database: /var/lib/osmocom/hlr.db
  <0001> db.c:103 (283) recovered 4 frames from WAL file /var/lib/osmocom/hlr.db-wal
  <0001> db.c:679 Database '/var/lib/osmocom/hlr.db' has HLR DB schema version 0
  <0001> db.c:103 (1) duplicate column name: last_lu_seen in "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL"
  <0001> db.c:248 Unable to prepare SQL statement 'ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL'
  <0001> db.c:318 Unable to update HLR database schema to version 1
  <0001> db.c:685 Failed to upgrade HLR DB schema to version 1: (rc=1) duplicate column name: last_lu_seen
  <0000> hlr_db_tool.c:509 Error opening database

It seems that osmo-hlr can get started before the osmo-hlr-post-upgrade
script runs, then starts to create the database with the current schema,
and gets stopped before it is done, leading to the failure above.

Rename the script to osmo-hlr-db-upgrade.sh, remove logic for stopping
and starting the service and let systemd call it in ExecStartPre. That
way we are sure that it runs *before* osmo-hlr starts up.

Related: SYS#8125
Change-Id: If13f4c8b49397e6630956e92a7825843c7d55ebd
Oliver Smith at

#22359 (Jul 15, 2026, 9:50:26 AM)

systemd: run db-upgrade script in ExecStartPre

We have seen in CI jobs that calling the DB upgrade script from
debian/postinst does not work reliably.

When doing a fresh install of osmo-hlr, it usually works as expected:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: nothing to do (no existing database)

But sometimes:

  Setting up osmo-hlr (1.9.2) ...
  osmo-hlr-post-upgrade: database upgrade is required
  osmo-hlr-post-upgrade: stopping osmo-hlr service
  osmo-hlr-post-upgrade: creating backup: /var/lib/osmocom/hlr.db.20260706135658.bak
  osmo-hlr-post-upgrade: performing database upgrade
  <0001> db.c:600 using database: /var/lib/osmocom/hlr.db
  <0001> db.c:103 (283) recovered 4 frames from WAL file /var/lib/osmocom/hlr.db-wal
  <0001> db.c:679 Database '/var/lib/osmocom/hlr.db' has HLR DB schema version 0
  <0001> db.c:103 (1) duplicate column name: last_lu_seen in "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL"
  <0001> db.c:248 Unable to prepare SQL statement 'ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL'
  <0001> db.c:318 Unable to update HLR database schema to version 1
  <0001> db.c:685 Failed to upgrade HLR DB schema to version 1: (rc=1) duplicate column name: last_lu_seen
  <0000> hlr_db_tool.c:509 Error opening database

It seems that osmo-hlr can get started before the osmo-hlr-post-upgrade
script runs, then starts to create the database with the current schema,
and gets stopped before it is done, leading to the failure above.

Rename the script to osmo-hlr-db-upgrade.sh, remove logic for stopping
and starting the service and let systemd call it in ExecStartPre. That
way we are sure that it runs *before* osmo-hlr starts up.

Related: SYS#8125
Change-Id: If13f4c8b49397e6630956e92a7825843c7d55ebd
Oliver Smith at

#22358 (Jul 15, 2026, 6:47:37 AM)

WIP: implement loop prevention over AS groups

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22357 (Jul 15, 2026, 6:47:35 AM)

WIP: implement loop prevention over AS groups

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22356 (Jul 15, 2026, 1:27:32 AM)

TCAP: Refactoring unroutable messages into own function

In preparation of adding another method to handle those.

Change-Id: Ib4d114273423730418458767d17b11de9bd815d4
lynxis at

#22355 (Jul 15, 2026, 1:27:31 AM)

WIP: implement loop prevention over AS groups

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22354 (Jul 15, 2026, 1:27:29 AM)

TCAP: implement a fallback routing

If a TCAP message from an ongoing session can't be routed by
either the TCAP session cache or by the destination TID to a known
node, allow to route the MSU to a different destination.

Change-Id: I3e4e634b38a1845c2ce62a3805ff91a530520d88
lynxis at

#22353 (Jul 15, 2026, 1:27:29 AM)

WIP: implement loop prevention over AS groups

Change-Id: Ice548cedf12d4a9e69f5e7aaf1d2df9e14d7f016
lynxis at

#22352 (Jul 15, 2026, 1:27:28 AM)

TCAP: Refactoring unroutable messages into own function

In preparation of adding another method to handle those.

Change-Id: Ib4d114273423730418458767d17b11de9bd815d4
lynxis at

#22351 (Jul 15, 2026, 1:27:27 AM)

TCAP: implement a fallback routing

If a TCAP message from an ongoing session can't be routed by
either the TCAP session cache or by the destination TID to a known
node, allow to route the MSU to a different destination.

Change-Id: I3e4e634b38a1845c2ce62a3805ff91a530520d88
lynxis at

#22350 (Jul 14, 2026, 5:56:27 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22349 (Jul 14, 2026, 5:56:27 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22348 (Jul 14, 2026, 5:56:26 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22347 (Jul 14, 2026, 5:56:26 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22346 (Jul 14, 2026, 4:29:43 PM)

contrib: add usb_vendor_request.py script to collect debug infos

Change-Id: Ie18e171c684ce9d67e711e3d6fda6850d5fc9e7e
lynxis at

#22345 (Jul 14, 2026, 4:29:35 PM)

firmware: card_emu.h: add missing header stdbool.h.

Change-Id: I4ad6d5cf0b4477cbd5f761d70c4cd92fb3ca1fcd
lynxis at

#22344 (Jul 14, 2026, 4:29:35 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22343 (Jul 14, 2026, 4:29:19 PM)

firmware: Drop CEMU_TX_DATA when sim is in-active

When the emulated sim is in reset or without power, drop
CEMU_TX_DATA.

Change-Id: I796e548225a742cddfde12bd6a60e4d2e5c04c8f
lynxis at

#22342 (Jul 14, 2026, 4:29:19 PM)

README.md: describe the debug uart

Change-Id: I4cf929fded962e7ffb4c01628279385b2af04157
lynxis at

#22341 (Jul 14, 2026, 4:28:46 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22340 (Jul 14, 2026, 4:28:46 PM)

firmware: card_emu.h: declare usb_buf_upd_len_and_submit()

usb_buf_upd_len_and_submit() already a public function and should be
accessible.

Change-Id: I734d4b2d782223dd2f735f140d8c9bc6fc00a086
lynxis at

#22339 (Jul 14, 2026, 4:28:14 PM)

contrib: add usb_vendor_request.py script to collect debug infos

Change-Id: Ie18e171c684ce9d67e711e3d6fda6850d5fc9e7e
lynxis at

#22338 (Jul 14, 2026, 4:28:13 PM)

firmware: Drop CEMU_TX_DATA when sim is in-active

When the emulated sim is in reset or without power, drop
CEMU_TX_DATA.

Change-Id: I796e548225a742cddfde12bd6a60e4d2e5c04c8f
lynxis at

#22337 (Jul 14, 2026, 4:28:11 PM)

README.md: describe the debug uart

Change-Id: I4cf929fded962e7ffb4c01628279385b2af04157
lynxis at

#22336 (Jul 14, 2026, 4:28:10 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22335 (Jul 14, 2026, 4:28:10 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22334 (Jul 14, 2026, 4:28:05 PM)

firmware: card_emu.h: add missing header stdbool.h.

Change-Id: I4ad6d5cf0b4477cbd5f761d70c4cd92fb3ca1fcd
lynxis at

#22333 (Jul 14, 2026, 4:28:05 PM)

firmware: card_emu.h: declare usb_buf_upd_len_and_submit()

usb_buf_upd_len_and_submit() already a public function and should be
accessible.

Change-Id: I734d4b2d782223dd2f735f140d8c9bc6fc00a086
lynxis at

#22332 (Jul 14, 2026, 4:26:31 PM)

README.md: fix typo in firmware

Change-Id: I16721418fce55322c8730920ceaa4e65f91a8a7e
lynxis at

#22331 (Jul 14, 2026, 4:26:30 PM)

contrib: add usb_vendor_request.py script to collect debug infos

Change-Id: Ie18e171c684ce9d67e711e3d6fda6850d5fc9e7e
lynxis at

#22330 (Jul 14, 2026, 4:26:29 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22329 (Jul 14, 2026, 4:26:28 PM)

firmare: Drop CEMU_TX_DATA when sim is in-active

When the emulated sim is in reset or without power, drop
CEMU_TX_DATA.

Change-Id: I796e548225a742cddfde12bd6a60e4d2e5c04c8f
lynxis at

#22328 (Jul 14, 2026, 4:26:26 PM)

firmware: card_emu.h: declare usb_buf_upd_len_and_submit()

usb_buf_upd_len_and_submit() already a public function and should be
accessible.

Change-Id: I734d4b2d782223dd2f735f140d8c9bc6fc00a086
lynxis at

#22327 (Jul 14, 2026, 4:24:51 PM)

README.md: describe the debug uart

Change-Id: I4cf929fded962e7ffb4c01628279385b2af04157
lynxis at

#22326 (Jul 14, 2026, 4:24:42 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22325 (Jul 14, 2026, 4:23:55 PM)

firmware: card_emu.h: add missing header stdbool.h.

Change-Id: I4ad6d5cf0b4477cbd5f761d70c4cd92fb3ca1fcd
lynxis at

#22324 (Jul 14, 2026, 4:23:43 PM)

README.md: fix typo in firmware

Change-Id: I16721418fce55322c8730920ceaa4e65f91a8a7e
lynxis at

#22323 (Jul 14, 2026, 4:23:42 PM)

firmare: Drop CEMU_TX_DATA when sim is in-active

When the emulated sim is in reset or without power, drop
CEMU_TX_DATA.

Change-Id: I796e548225a742cddfde12bd6a60e4d2e5c04c8f
lynxis at

#22322 (Jul 14, 2026, 4:23:42 PM)

contrib: add usb_vendor_request.py script to collect debug infos

Change-Id: Ie18e171c684ce9d67e711e3d6fda6850d5fc9e7e
lynxis at

#22321 (Jul 14, 2026, 4:23:42 PM)

firmware: Add talloc_report_buf() encode the allocation by bits

First byte encodes the amount of blocks.
The following bytes encode a block as a single bit.

Change-Id: I3a8ddbe4100f342db2c59ad1fb9aa0014efc62b8
lynxis at

#22320 (Jul 14, 2026, 4:23:42 PM)

firmware: card_emu.h: add missing header stdbool.h.

Change-Id: I4ad6d5cf0b4477cbd5f761d70c4cd92fb3ca1fcd
lynxis at

#22319 (Jul 14, 2026, 4:23:42 PM)

firmware: card_emu.h: declare usb_buf_upd_len_and_submit()

usb_buf_upd_len_and_submit() already a public function and should be
accessible.

Change-Id: I734d4b2d782223dd2f735f140d8c9bc6fc00a086
lynxis at

#22318 (Jul 14, 2026, 4:23:41 PM)

README.md: describe the debug uart

Change-Id: I4cf929fded962e7ffb4c01628279385b2af04157
lynxis at

#22317 (Jul 14, 2026, 4:23:41 PM)

firmware: Implement debug command via USB control vendor class

Allows to collect talloc reports and other debug information
from a script while the remsim-client is still running.

Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
lynxis at

#22316 (Jul 9, 2026, 1:11:45 PM)

rebar.config: use a fork of rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  A pull request [1] has been
submitted upstream.  Once merged, we get switch back to upstream.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Vadim Yanitskiy at

#22315 (Jul 9, 2026, 1:11:45 PM)

rebar.config: use a fork of rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  A pull request [1] has been
submitted upstream.  Once merged, we get switch back to upstream.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Vadim Yanitskiy at

#22314 (Jul 9, 2026, 11:54:51 AM)

rebar.config: use a fork of rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  A pull request [1] has been
submitted upstream.  Once merged, we get switch back to upstream.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Vadim Yanitskiy at

#22313 (Jul 9, 2026, 11:54:51 AM)

rebar.config: use a fork of rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  A pull request [1] has been
submitted upstream.  Once merged, we get switch back to upstream.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Vadim Yanitskiy at

#22312 (Jul 8, 2026, 7:43:45 AM)

rebar.config: bump meck version: 0.9.2 -> v1.2.0

This fixes a compilation error with recent Erlang/OTP 29:

[  335s] ===> Compiling meck
[  335s] ===> Compiling _checkouts/meck/src/meck_matcher.erl failed
[  335s] meck_matcher.erl:76:6: 'catch ...' is deprecated; please use 'try ... catch ... end' instead.
[  335s] Compile directive 'nowarn_deprecated_catch' can be used to suppress
[  335s] warnings in selected modules.

Change-Id: If3409de1e09ac1b6ce3355d19e47ef0e160a2d3b
(cherry picked from commit a013155e8af1b4cca604e10f81dcb683a5e7812c)
Oliver Smith at

#22311 (Jul 8, 2026, 7:43:45 AM)

Bump version: 0.4.1

Change-Id: I17c9806400a48b4cdf7be19a824e10c56620d655
Oliver Smith at

#22310 (Jul 8, 2026, 7:43:40 AM)

rebar.config: bump meck version: 0.9.2 -> v1.2.0

This fixes a compilation error with recent Erlang/OTP 29:

[  335s] ===> Compiling meck
[  335s] ===> Compiling _checkouts/meck/src/meck_matcher.erl failed
[  335s] meck_matcher.erl:76:6: 'catch ...' is deprecated; please use 'try ... catch ... end' instead.
[  335s] Compile directive 'nowarn_deprecated_catch' can be used to suppress
[  335s] warnings in selected modules.

Change-Id: If3409de1e09ac1b6ce3355d19e47ef0e160a2d3b
(cherry picked from commit a013155e8af1b4cca604e10f81dcb683a5e7812c)
Oliver Smith at

#22309 (Jul 8, 2026, 7:43:40 AM)

Bump version: 0.4.1

Change-Id: I17c9806400a48b4cdf7be19a824e10c56620d655
Oliver Smith at

#22308 (Jul 8, 2026, 6:49:01 AM)

Bump version: 0.9.0.4-3248-dirty → 0.9.1

Change-Id: I0d06c6f15aa99be7609eac9afb6b9df8e6cf3dc5
Oliver Smith at

#22307 (Jul 8, 2026, 6:49:00 AM)

Bump version: 0.9.0.4-3248-dirty → 0.9.1

Change-Id: I0d06c6f15aa99be7609eac9afb6b9df8e6cf3dc5
Oliver Smith at

#22306 (Jul 7, 2026, 1:57:41 PM)

Add missing const for struct hostent *hostent

The hostent parameter is supposed to be const. This is being enforced in
c-ares 1.34.7, which is why osmo-sgsn currently fails to build in debian
unstable. The c-ares developers are preparing a new release that reverts
this change to avoid breakage with other users of libc-ares, and only
document that this should basically be const. But let's use the API as
intended so the compiler knows that osmo-sgsn is not supposed to modify
the hostent parameter.

Fix for:

  sgsn_ares.c:141:63: error: passing argument 4 of 'ares_gethostbyname' from incompatible pointer type [-Wincompatible-pointer-types]
    141 |         ares_gethostbyname(sgsn->ares_channel, name, AF_INET, ares_cb, cb_data);
        |                                                               ^~~~~~~
        |                                                               |
        |                                                               void (*)(void *, int,  int,  struct hostent *)
  /usr/include/ares.h:881:22: note: expected 'ares_host_callback' {aka 'void (*)(void *, int,  int,  const struct hostent *)'} but argument is of type 'void (*)(void *, int,  int,  struct hostent *)'

Related: https://github.com/c-ares/c-ares/pull/1060
Related: https://github.com/c-ares/c-ares/pull/1244
Change-Id: Ibe3debc5d3b7af5883001960c40efb296692f93d
Oliver Smith at

#22305 (Jul 7, 2026, 1:57:41 PM)

Add missing const for struct hostent *hostent

The hostent parameter is supposed to be const. This is being enforced in
c-ares 1.34.7, which is why osmo-sgsn currently fails to build in debian
unstable. The c-ares developers are preparing a new release that reverts
this change to avoid breakage with other users of libc-ares, and only
document that this should basically be const. But let's use the API as
intended so the compiler knows that osmo-sgsn is not supposed to modify
the hostent parameter.

Fix for:

  sgsn_ares.c:141:63: error: passing argument 4 of 'ares_gethostbyname' from incompatible pointer type [-Wincompatible-pointer-types]
    141 |         ares_gethostbyname(sgsn->ares_channel, name, AF_INET, ares_cb, cb_data);
        |                                                               ^~~~~~~
        |                                                               |
        |                                                               void (*)(void *, int,  int,  struct hostent *)
  /usr/include/ares.h:881:22: note: expected 'ares_host_callback' {aka 'void (*)(void *, int,  int,  const struct hostent *)'} but argument is of type 'void (*)(void *, int,  int,  struct hostent *)'

Related: https://github.com/c-ares/c-ares/pull/1060
Related: https://github.com/c-ares/c-ares/pull/1244
Change-Id: Ibe3debc5d3b7af5883001960c40efb296692f93d
Oliver Smith at

#22304 (Jul 7, 2026, 7:38:00 AM)

tcap_as_loadshare: Forward UDTS to the correct tcap-loadshare ASP

Related: SYS#8090
Change-Id: I2051aa9e84e553feb17daabb93ba3ce82358e0e4
dwillmann at

#22303 (Jul 7, 2026, 7:37:58 AM)

tcap_as_loadshare: Forward UDTS to the correct tcap-loadshare ASP

Related: SYS#8090
Change-Id: I2051aa9e84e553feb17daabb93ba3ce82358e0e4
dwillmann at

#22302 (Jun 30, 2026, 4:22:27 PM)

common: reset lchan meas state in gsm_lchan_release()

lchan->meas (including interf_meas_num and num_ul_meas) is normally
only reset by lchan_meas_reset() called from rsl_tx_chan_act_ack() on
RSL CHANNEL ACTIVATION.  Idle logical channels are never RSL-activated,
so their measurement state is never reset via that path.

On an OML link re-establishment, osmo-bts does not exit: abis.c tears
down the signalling links, the bts_shutdown FSM powers down all TRXs,
and then waits for reconnect.  The gsm_bts/trx/ts/lchan structures
remain in memory, so stale interf_meas_num survives the reconnect.

This is why we're seeing these ERRORs while running ttcn3-bts-test:

(bts=0,trx=2,ts=4,ss=6) Not enough room to store interference report (0dBm)

Add a lchan_meas_reset() call to gsm_lchan_release(), which is called
from gsm_ts_release() when the nm_channel_fsm enters state
NM_CHAN_ST_OP_DISABLED_NOTINSTALLED.  This is exactly the right
moment: the radio is fully stopped, so no new samples arrive.

Change-Id: I18dc9d30417b0c5b2e579660d4a087d93445f956
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#22301 (Jun 30, 2026, 4:22:22 PM)

common: stop buffering UL measurements when SACCH is deactivated

When the BSC sends RSL DEACT SACCH, the per-SACCH UL measurement drain
stops (it runs on SACCH timing), but the producer in lchan_new_ul_meas()
keeps appending the measurement contributions from every received
TCH/SDCCH burst.  After one SACCH period (104 frames) the 104-slot
uplink measurement buffer fills up, yielding a flood of:

  NOTICE measurement.c:336 no space for uplink measurement, num_ul_meas=104

Add a bool sacch_active flag to gsm_lchan, set to true in the common
l1sap_chan_act() and clear in l1sap_chan_deact_sacch().  Guard
lchan_new_ul_meas() with this flag so that measurements are silently
discarded while SACCH is inactive - there is nothing to drain the
buffer and no SACCH channel on which to report the results to the BSC.

Change-Id: I3943c788cab5d2411b06ac681d4d412852bac0a7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#22300 (Jun 30, 2026, 4:22:22 PM)

common: flush paging queue in nm_bts_fsm's NOTINSTALLED on_enter

paging_reset() exists to flush stale paging records from the queue,
but was never called anywhere.  Stale paging records can accumulate
when the OML link goes down: osmo-bts does not exit, so the paging
queue survives into the next BSC session.

Call it alongside bts_cbch_reset() and bts_asci_notification_reset()
in st_op_disabled_notinstalled_on_enter(), which fires after all TRXs
are confirmed closed and before a new OML connection is accepted.

Change-Id: I109ab282986b68b68ba5c11859c44b771c0416fd
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#22299 (Jun 30, 2026, 4:22:22 PM)

common: reset lchan meas state in gsm_lchan_release()

lchan->meas (including interf_meas_num and num_ul_meas) is normally
only reset by lchan_meas_reset() called from rsl_tx_chan_act_ack() on
RSL CHANNEL ACTIVATION.  Idle logical channels are never RSL-activated,
so their measurement state is never reset via that path.

On an OML link re-establishment, osmo-bts does not exit: abis.c tears
down the signalling links, the bts_shutdown FSM powers down all TRXs,
and then waits for reconnect.  The gsm_bts/trx/ts/lchan structures
remain in memory, so stale interf_meas_num survives the reconnect.

This is why we're seeing these ERRORs while running ttcn3-bts-test:

(bts=0,trx=2,ts=4,ss=6) Not enough room to store interference report (0dBm)

Add a lchan_meas_reset() call to gsm_lchan_release(), which is called
from gsm_ts_release() when the nm_channel_fsm enters state
NM_CHAN_ST_OP_DISABLED_NOTINSTALLED.  This is exactly the right
moment: the radio is fully stopped, so no new samples arrive.

Change-Id: I18dc9d30417b0c5b2e579660d4a087d93445f956
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#22298 (Jun 30, 2026, 4:22:22 PM)

common: stop buffering UL measurements when SACCH is deactivated

When the BSC sends RSL DEACT SACCH, the per-SACCH UL measurement drain
stops (it runs on SACCH timing), but the producer in lchan_new_ul_meas()
keeps appending the measurement contributions from every received
TCH/SDCCH burst.  After one SACCH period (104 frames) the 104-slot
uplink measurement buffer fills up, yielding a flood of:

  NOTICE measurement.c:336 no space for uplink measurement, num_ul_meas=104

Add a bool sacch_active flag to gsm_lchan, set to true in the common
l1sap_chan_act() and clear in l1sap_chan_deact_sacch().  Guard
lchan_new_ul_meas() with this flag so that measurements are silently
discarded while SACCH is inactive - there is nothing to drain the
buffer and no SACCH channel on which to report the results to the BSC.

Change-Id: I3943c788cab5d2411b06ac681d4d412852bac0a7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#22297 (Jun 30, 2026, 4:22:20 PM)

common: flush paging queue in nm_bts_fsm's NOTINSTALLED on_enter

paging_reset() exists to flush stale paging records from the queue,
but was never called anywhere.  Stale paging records can accumulate
when the OML link goes down: osmo-bts does not exit, so the paging
queue survives into the next BSC session.

Call it alongside bts_cbch_reset() and bts_asci_notification_reset()
in st_op_disabled_notinstalled_on_enter(), which fires after all TRXs
are confirmed closed and before a new OML connection is accepted.

Change-Id: I109ab282986b68b68ba5c11859c44b771c0416fd
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#22296 (Jun 30, 2026, 9:12:02 AM)

rebar.config: bump meck version: 0.9.2 -> v1.2.0

This fixes a compilation error with recent Erlang/OTP 29:

[  335s] ===> Compiling meck
[  335s] ===> Compiling _checkouts/meck/src/meck_matcher.erl failed
[  335s] meck_matcher.erl:76:6: 'catch ...' is deprecated; please use 'try ... catch ... end' instead.
[  335s] Compile directive 'nowarn_deprecated_catch' can be used to suppress
[  335s] warnings in selected modules.

Change-Id: If3409de1e09ac1b6ce3355d19e47ef0e160a2d3b
Vadim Yanitskiy at

#22295 (Jun 30, 2026, 9:11:58 AM)

rebar.config: bump meck version: 0.9.2 -> v1.2.0

This fixes a compilation error with recent Erlang/OTP 29:

[  335s] ===> Compiling meck
[  335s] ===> Compiling _checkouts/meck/src/meck_matcher.erl failed
[  335s] meck_matcher.erl:76:6: 'catch ...' is deprecated; please use 'try ... catch ... end' instead.
[  335s] Compile directive 'nowarn_deprecated_catch' can be used to suppress
[  335s] warnings in selected modules.

Change-Id: If3409de1e09ac1b6ce3355d19e47ef0e160a2d3b
Vadim Yanitskiy at