Skip to content

platform/surface: aggregator_tabletsw: accept zero-padded source-list responses - #173

Open
zR-JB wants to merge 1 commit into
linux-surface:v6.19-surface-develfrom
zR-JB:ssam-pos-zero-padding
Open

platform/surface: aggregator_tabletsw: accept zero-padded source-list responses#173
zR-JB wants to merge 1 commit into
linux-surface:v6.19-surface-develfrom
zR-JB:ssam-pos-zero-padding

Conversation

@zR-JB

@zR-JB zR-JB commented Aug 12, 2026

Copy link
Copy Markdown

Summary

Allow the Surface Aggregator POS source-list parser to accept bounded, zero-filled trailing response data.

The Surface Pro 12 for Business Intel provides a reproducer (In combination with Flex Keyboard). Its POS source-list command returns a 24-byte response:

count = 1
id[0] = 0x00
remaining 16 bytes = 0x00

This describes one Type-Cover posture source. The additional bytes are zero-filled trailing data, not additional posture sources.

The current driver requires the response length to exactly equal:

sizeof(count) + count * sizeof(source_id)

and its source-list response buffer is only 20 bytes.

As a result, the POS/tablet-mode client fails to probe on the SP12.

Proposed handling

This PR:

  1. increases the source-list response capacity from 20 to 24 bytes;
  2. validates that the reported source count fits in the existing
    four-entry source array;
  3. calculates the minimum response length represented by that count; and
  4. accepts any remaining bytes only when every trailing byte is zero.

The resulting validation is effectively:

count = get_unaligned_le32(&sources->count);

if (count > ARRAY_SIZE(sources->id))
        return -EPROTO;

expected = sizeof(sources->count) +
           count * sizeof(sources->id[0]);

if (rsp.length < expected ||
    memchr_inv((u8 *)sources + expected, 0, rsp.length - expected))
        return -EPROTO;

So this does not generally relax response validation.

The following continue to be rejected:

  • a response shorter than required by count;
  • more sources than fit in the fixed source array;
  • any non-zero trailing response data.

Existing exact-length responses continue to be accepted unchanged.

Why add four bytes to the response structure?

The existing structure contains:

count:       4 bytes
id[4]:      16 bytes
--------------------
total:      20 bytes

and is also used directly as the response buffer:

rsp.capacity = sizeof(*sources);

The SP12 returns 24 bytes, so validating trailing data alone is not sufficient: the response buffer must first be large enough to receive the complete response.

An additional four-byte padding field raises the maximum accepted response size to 24 bytes.

For the observed SP12 response with count = 1, the semantic payload is 8 bytes and all 16 bytes after it are verified to be zero.

Surface Pro 12 reproducer

Tested on:

Microsoft Surface Pro for Business 13in 12th Ed Intel
MSHW0743 / Panther Lake

Before this change the SSAM POS/tablet-mode client failed during probe.

The SP12 firmware response was observed as:

response length: 24 bytes
count:           1
source id[0]:    0x00
trailing bytes:  16 x 0x00

With this patch:

  • surface_aggregator_tabletsw binds normally at boot;
  • Microsoft Surface POS Tablet Mode Switch is created;
  • the device exposes EV_SW / SW_TABLET_MODE.

Physical testing produced:

Flex Keyboard attached:    SW_TABLET_MODE = 0
Flex Keyboard detached:    SW_TABLET_MODE = 1
Flex Keyboard reattached:  SW_TABLET_MODE = 0

The full SP12 investigation is documented here:

linux-surface/linux-surface#2144 (comment)

Testing / review scope

The exact patch in this PR has already been runtime-tested on the SP12.

It has also been compile-tested against v6.19-surface-devel using the current linux-surface Arch kernel configuration.

Because this changes the generic SSAM POS source-list parser rather than adding an SP12-specific device quirk, testing on other devices using the POS tablet-mode implementation would be useful.

In particular I would like to confirm that existing exact-length responses continue to behave unchanged.

Surface Pro 12 enablement

This is one independently reviewable part of the broader Surface Pro 12
Intel enablement work:

linux-surface/linux-surface#2144

Related draft PRs:

… responses

Some Surface firmware returns a fixed-size POS source-list response
with unused bytes zero-filled instead of returning only the bytes
described by the source count.

On the Surface Pro 12 Intel, the POS source-list command returns 24
bytes with count 1, source ID 0 for the Type Cover, and all remaining
16 bytes set to zero. The current parser only provides 20 bytes of
response capacity and requires the response length to exactly match
4 + count * 4, so the POS tablet-mode client fails to probe.

Provide space for the observed additional trailing word and allow
trailing response data only when it is entirely zero. Also validate
the source count against the fixed source array before calculating the
expected payload size.

Exact-length responses remain accepted unchanged. Short responses,
source counts larger than the available array, and non-zero trailing
data continue to fail with -EPROTO.

This allows the Surface Pro 12 POS tablet-mode client to bind while
keeping the parser bounded and rejecting unexpected response data.

Link: linux-surface/linux-surface#2144 (comment)
Signed-off-by: Jan Baisch <jan.baisch@protonmail.com>
Link: linux-surface#173
Patchset: surface-sam
@zR-JB
zR-JB force-pushed the ssam-pos-zero-padding branch from 45513b6 to 51b3d8d Compare August 12, 2026 21:37
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