Skip to content

Add extended QMI service support: WDA, UIM provisioning, WDS profiles, and improved error handling#218

Open
mlainez wants to merge 10 commits intonerves-networking:mainfrom
mlainez:main
Open

Add extended QMI service support: WDA, UIM provisioning, WDS profiles, and improved error handling#218
mlainez wants to merge 10 commits intonerves-networking:mainfrom
mlainez:main

Conversation

@mlainez
Copy link
Copy Markdown

@mlainez mlainez commented Feb 13, 2026

New Services

  • WDA (Wireless Data Administrative)QMI.WirelessDataAdmin with get_data_format/1 and set_data_format/2 for controlling the link-layer protocol (raw_ip vs 802.3) and aggregation settings. For modems whose qmi_wwan driver does not expose the sysfs raw_ip toggle.
  • UIM card status & session provisioningQMI.UserIdentity.get_cards_status/1 to query all card slots (including per-application PIN state and personalization info), and provision_uim_session/2 to activate a primary GW provisioning session for a specific SIM application. This is needed for the Fairphone2 modem support which is dual sim.

WDS (Wireless Data) Enhancements

  • Profile settings read supportget_profile_settings/3 and get_profile_list/2 to read individual profiles and enumerate all configured profiles on the modem.
  • Extended modify_profile_settings — APN, PDP type, username, password, and authentication method can now be configured (TLVs 0x10–0x14).
  • Full IPv4/IPv6 network config in current settings — Parse address, gateway, subnet mask, and DNS servers from the Get Current Settings response.

Tweaks to existing functionality

  • Configurable timeout for QMI.call/3 — Override the default 5s timeout, with param support in start_network_interface/2 for modems that take longer to establish data sessions.
  • More verbose call end reason parsing — Decode TLV 0x10/0x11 in error responses to log human-readable failure reasons (e.g. :three_gpp_specification_defined, :internal).
  • Conditional raw_ip sysfs writeconfigure_linux/1 no longer raises when the qmi/raw_ip sysfs file is absent, returning :ok instead.

Not all modems expose the /sys/class/net/<ifname>/qmi/raw_ip sysfs file.
When the file is absent, File.write!/2 raises an exception that prevents
configure_linux/1 from completing.

Check for file existence before writing so that configure_linux/1 returns
:ok on modems that do not support sysfs-based raw IP configuration.
Allow callers to override the default 5-second call timeout by passing
a :timeout option. The timeout is forwarded to QMI.Driver.call/4 which
already supports it.

This is useful for operations like start_network_interface that may
take longer than 5 seconds on some modems.
When a QMI request fails, the modem may include TLV 0x10 (call end reason)
and TLV 0x11 (verbose call end reason with type) in the response. Parse
these TLVs and log them alongside the error to provide better diagnostics
when network operations like start_network_interface fail.

The verbose reason type is decoded into human-readable atoms (e.g.
:three_gpp_specification_defined, :internal, :mobile_ip) following the
QMI WDS specification.
Add two new UIM (User Identity Module) commands:

- get_cards_status/0: Queries all card slots and returns their state,
  including per-slot application details (type, state, PIN status,
  personalization info, and application identifiers).

- provision_uim_session/2: Activates a primary GW provisioning session
  for a specific application on a given card slot. This is needed before
  communicating with a particular SIM application.

Both the codec layer (QMI.Codec.UserIdentity) and the public API layer
(QMI.UserIdentity) are updated.
Parse additional TLVs from the WDS Get Current Settings response to
return the complete network configuration assigned by the modem:

IPv4 (little-endian byte order, converted to dotted-decimal):
- TLV 0x1E: IPv4 address
- TLV 0x20: IPv4 gateway
- TLV 0x21: IPv4 subnet mask
- TLV 0x15: IPv4 primary DNS
- TLV 0x16: IPv4 secondary DNS

IPv6 (formatted via :inet.ntoa/1):
- TLV 0x1A: IPv6 address + prefix length
- TLV 0x1C: IPv6 gateway
- TLV 0x1E: IPv6 primary DNS (16-byte variant)
- TLV 0x20: IPv6 secondary DNS (16-byte variant)

The current_settings type is expanded accordingly and the public API
documentation in QMI.WirelessData is updated with the full list of
returned fields.
Add the ability to read individual profile settings and enumerate all
configured profiles:

Codec layer (QMI.Codec.WirelessData):
- get_profile_settings/2: Builds a QMI request for message 0x002B
  (WDS Get Profile Settings). Parses the response TLVs for APN (0x10),
  PDP type (0x11), username (0x12), password (0x13), and auth method (0x14).
- New types: pdp_type, auth_method, profile_settings.

Public API (QMI.WirelessData):
- get_profile_settings/3: Read settings for a single profile by index.
- get_profile_list/2: Iterate from index 1 upward, collecting profiles
  until the modem returns :extended_internal (no more profiles).
Add support for configuring additional profile settings when calling
modify_profile_settings:

- APN (TLV 0x10): Access Point Name string
- PDP type (TLV 0x11): IPv4, IPv6, IPv4v6, or PPP
- Username (TLV 0x12): Authentication username
- Password (TLV 0x13): Authentication password
- Auth method (TLV 0x14): None, PAP, CHAP, or PAP/CHAP

These are the standard 3GPP profile fields needed to configure a modem
for a specific carrier. The profile_setting type and public API
documentation are updated accordingly.
Allow callers to pass a :timeout option to start_network_interface/2
which is forwarded to QMI.call/3. The timeout is separated from the
request options so it is not sent to the modem as a TLV.

This is useful because some modems take significantly longer than the
default 5 seconds to establish a data session, especially during
initial registration or roaming.
Add a new QMI service module for WDA (service ID 0x1A), which controls
the data format used between the modem and the host driver.

Codec layer (QMI.Codec.WirelessDataAdmin):
- get_data_format/0: Query the current link-layer protocol, aggregation
  settings, QoS format, and DL max datagram/size.
- set_data_format/1: Configure link-layer protocol (raw_ip or 802.3),
  uplink/downlink aggregation protocol, QoS, and endpoint info.

Public API (QMI.WirelessDataAdmin):
- get_data_format/1 and set_data_format/2 wrap the codec with QMI.call.

On modems whose qmi_wwan driver does not expose the sysfs raw_ip toggle,
this service is the only way to switch between 802.3 and raw-IP framing
before starting a data session.
Add catch-all clause to QMI.Codec.WirelessData.parse_call_end_reason_type/1
to match the existing pattern in QMI.Driver. Without this, an unknown
call_end_reason_type byte from the modem would cause a FunctionClauseError,
crashing indication parsing.

Also fix typo in typespec (:call_manger_defined -> :call_manager_defined)
and add {:unknown, non_neg_integer()} to the call_end_reason_type() type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant