Rust for Linux List
 help / color / mirror / Atom feed
From: Mike Lothian <mike@fireburn.co.uk>
To: rust-for-linux@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org,
	"David Airlie" <airlied@gmail.com>,
	"Simona Vetter" <simona@ffwll.ch>,
	"Thomas Zimmermann" <tzimmermann@suse.de>,
	"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
	"Maxime Ripard" <mripard@kernel.org>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Lyude Paul" <lyude@redhat.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	linux-kernel@vger.kernel.org,
	"Mike Lothian" <mike@fireburn.co.uk>
Subject: [RFC PATCH v2 01/10] drm/vino: add DisplayLink DL3 dock skeleton and protocol framing
Date: Fri,  3 Jul 2026 04:02:06 +0100	[thread overview]
Message-ID: <20260703030217.2886-2-mike@fireburn.co.uk> (raw)
In-Reply-To: <20260703030217.2886-1-mike@fireburn.co.uk>

New drm/vino driver for DisplayLink DL3 USB docks (Dell D6000,
17e9:6006), replacing the out-of-tree EVDI module plus the
DisplayLinkManager userspace daemon.

This patch adds the module skeleton (Kconfig/Makefile, registered in
drivers/gpu/drm/{Kconfig,Makefile}) and two small standalone pieces:
proto.rs (the DL3 USB wire framing this driver builds every message on
top of) and rng.rs (a thin wrapper over the kernel RNG for HDCP nonces).
Neither depends on anything else added by later patches in this series.

Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
Assisted-by: Claude:claude-sonnet-5 [Claude-Code]
---
 drivers/gpu/drm/Kconfig       |  1 +
 drivers/gpu/drm/Makefile      |  1 +
 drivers/gpu/drm/vino/Kconfig  | 20 ++++++++++
 drivers/gpu/drm/vino/Makefile |  2 +
 drivers/gpu/drm/vino/proto.rs | 73 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vino/rng.rs   | 12 ++++++
 6 files changed, 109 insertions(+)
 create mode 100644 drivers/gpu/drm/vino/Kconfig
 create mode 100644 drivers/gpu/drm/vino/Makefile
 create mode 100644 drivers/gpu/drm/vino/proto.rs
 create mode 100644 drivers/gpu/drm/vino/rng.rs

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 323422861e8f..8fb9c9f787ba 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -361,6 +361,7 @@ source "drivers/gpu/drm/vgem/Kconfig"
 source "drivers/gpu/drm/virtio/Kconfig"
 source "drivers/gpu/drm/vkms/Kconfig"
 source "drivers/gpu/drm/vmwgfx/Kconfig"
+source "drivers/gpu/drm/vino/Kconfig"
 source "drivers/gpu/drm/xe/Kconfig"
 source "drivers/gpu/drm/xen/Kconfig"
 source "drivers/gpu/drm/xlnx/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e97faabcd783..42a04359cc63 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -185,6 +185,7 @@ obj-$(CONFIG_DRM_VC4)  += vc4/
 obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VGEM)	+= vgem/
 obj-$(CONFIG_DRM_VKMS)	+= vkms/
+obj-$(CONFIG_DRM_VINO)	+= vino/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
 obj-$(CONFIG_DRM_NOVA) += nova/
 obj-$(CONFIG_DRM_EXYNOS) +=exynos/
diff --git a/drivers/gpu/drm/vino/Kconfig b/drivers/gpu/drm/vino/Kconfig
new file mode 100644
index 000000000000..f5fe6670a488
--- /dev/null
+++ b/drivers/gpu/drm/vino/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0
+config DRM_VINO
+	tristate "DisplayLink DL3 (Vino) open driver"
+	depends on USB
+	depends on DRM
+	depends on RUST
+	select DRM_KMS_HELPER
+	select RUST_DRM_GEM_SHMEM_HELPER
+	select CRYPTO_LIB_RSA
+	help
+	  Open in-kernel Rust driver for DisplayLink DL3 USB docks (Dell
+	  Universal Dock D6000 and relatives).
+
+	  It binds the dock over USB, runs the HDCP 2.2 control plane, mode-set
+	  and the Vino codec, and registers a DRM/KMS sink that scans out to the
+	  dock's video endpoints.
+
+	  To compile this as a module, choose M here: the module is called vino.
+
+	  If unsure, say N.
diff --git a/drivers/gpu/drm/vino/Makefile b/drivers/gpu/drm/vino/Makefile
new file mode 100644
index 000000000000..6e39668040f3
--- /dev/null
+++ b/drivers/gpu/drm/vino/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_DRM_VINO) += vino.o
diff --git a/drivers/gpu/drm/vino/proto.rs b/drivers/gpu/drm/vino/proto.rs
new file mode 100644
index 000000000000..cae6eae46b7a
--- /dev/null
+++ b/drivers/gpu/drm/vino/proto.rs
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! The DL3 "universal" wire framing and the plaintext session-init messages (sec 3/sec 4).
+
+use super::*;
+
+/// Append a sec 3-framed message to `out` with an explicit `sub_len_dw`: a 16-byte
+/// little-endian header (`pad(2) | size(2)=total-4 | type(4) | sub_id(2) |
+/// sub_len_dw(2) | seq(4)`) followed by `body`.
+///
+/// HDCP OUT messages (sec 5.1) carry DLM-fixed `sub_len_dw` values that are *not*
+/// `body.len() / 4`, so the framer cannot derive it -- the caller passes it.
+pub(super) fn push_frame_with(
+    out: &mut KVec<u8>,
+    msg_type: u32,
+    sub_id: u16,
+    sub_len_dw: u16,
+    seq: u32,
+    body: &[u8],
+) -> Result {
+    let size = ((16 + body.len()) - 4) as u16;
+    out.extend_from_slice(&[0, 0], GFP_KERNEL)?;
+    out.extend_from_slice(&size.to_le_bytes(), GFP_KERNEL)?;
+    out.extend_from_slice(&msg_type.to_le_bytes(), GFP_KERNEL)?;
+    out.extend_from_slice(&sub_id.to_le_bytes(), GFP_KERNEL)?;
+    out.extend_from_slice(&sub_len_dw.to_le_bytes(), GFP_KERNEL)?;
+    out.extend_from_slice(&seq.to_le_bytes(), GFP_KERNEL)?;
+    out.extend_from_slice(body, GFP_KERNEL)?;
+    Ok(())
+}
+
+/// `init_25` body (sec 4, verified 2026-05-27). Framed with `sub_len_dw=0` -- the
+/// DLM-fixed value, NOT `body.len()/4` (the dock ignores/rejects otherwise).
+pub(super) const INIT_25: [u8; 16] =
+    [0x05, 0, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+/// `init_4` (Part A) body (sec 4), also framed with `sub_len_dw=0`.
+pub(super) const INIT_4: [u8; 16] =
+    [0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+/// The first HDCP-channel probe **body** (Part B of the init_4+probe transfer,
+/// sec 4): a 32-byte body leading with `14 00 76 00`, the rest zero. It is wrapped
+/// in its own type=4 sub=0x04 frame (`sub_len_dw=0x0a`) -- see [`init_4_probe`].
+/// The dock only ACKs once this framed probe arrives.
+pub(super) const PROBE_BODY: [u8; 32] = {
+    let mut p = [0u8; 32];
+    p[0] = 0x14;
+    p[2] = 0x76;
+    p
+};
+
+/// `init_0`: 16-byte framing header only, empty body (sec 4).
+pub(super) fn init_0() -> Result<KVec<u8>> {
+    let mut buf = KVec::with_capacity(16, GFP_KERNEL)?;
+    push_frame_with(&mut buf, 0x01, 0x00, 0, 0, &[])?;
+    Ok(buf)
+}
+
+/// `init_25`: type=2 sub=0x25, `sub_len_dw=0`, 32 bytes total (sec 4).
+pub(super) fn init_25() -> Result<KVec<u8>> {
+    let mut buf = KVec::with_capacity(32, GFP_KERNEL)?;
+    push_frame_with(&mut buf, 0x02, 0x25, 0, 0, &INIT_25)?;
+    Ok(buf)
+}
+
+/// `init_4` + HDCP probe as one 80-byte transfer (sec 4): Part A (type=2 sub=0x04,
+/// `sub_len_dw=0`, 32 B) concatenated with Part B -- the probe framed as type=4
+/// sub=0x04 with `sub_len_dw=0x0a` over the 32-byte [`PROBE_BODY`] (48 B). This
+/// is the message the dock ACKs.
+pub(super) fn init_4_probe() -> Result<KVec<u8>> {
+    let mut buf = KVec::with_capacity(80, GFP_KERNEL)?;
+    push_frame_with(&mut buf, 0x02, 0x04, 0, 0, &INIT_4)?; // Part A
+    push_frame_with(&mut buf, 0x04, 0x04, 0x0a, 0, &PROBE_BODY)?; // Part B (framed probe)
+    Ok(buf)
+}
diff --git a/drivers/gpu/drm/vino/rng.rs b/drivers/gpu/drm/vino/rng.rs
new file mode 100644
index 000000000000..8720d55174ae
--- /dev/null
+++ b/drivers/gpu/drm/vino/rng.rs
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Cryptographically-secure randomness for the per-session HDCP nonces/keys
+//! (`rtx`, `km`, `rn`, `ks`, `riv`, the OAEP seed).
+#![allow(dead_code)] // RNG helpers; some are reached only on the post-engagement CP path
+
+/// Fills `buf` with random bytes from the kernel CSPRNG (`get_random_bytes`).
+pub(super) fn fill(buf: &mut [u8]) {
+    // SAFETY: `buf` is valid for writes of `buf.len()` bytes; `get_random_bytes`
+    // writes exactly that many and never sleeps/faults on a kernel buffer.
+    unsafe { kernel::bindings::get_random_bytes(buf.as_mut_ptr().cast(), buf.len()) };
+}
-- 
2.55.0


  reply	other threads:[~2026-07-03  3:02 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-17 15:12 [RFC PATCH 0/7] drm/vino: DisplayLink DL3 dock driver (RFC, help wanted) Mike Lothian
2026-06-17 15:12 ` [RFC PATCH 1/7] drm/vino: add DisplayLink DL3 dock skeleton and plaintext bring-up Mike Lothian
2026-06-17 15:17   ` Miguel Ojeda
2026-06-18 10:39   ` Julian Braha
2026-06-17 15:12 ` [RFC PATCH 2/7] drm/vino: add the clean-room HDCP 2.2 AKE/LC/SKE Mike Lothian
2026-06-17 16:18   ` Eric Biggers
2026-06-17 15:12 ` [RFC PATCH 3/7] drm/vino: add the AES-CTR/AES-CMAC control-plane seal and arm Mike Lothian
2026-06-17 15:12 ` [RFC PATCH 4/7] drm/vino: add the Vino (RawRl mode-2) framebuffer codec Mike Lothian
2026-06-17 15:12 ` [RFC PATCH 5/7] drm/vino: register a DRM/KMS device and scan out to EP08 Mike Lothian
2026-06-17 15:12 ` [RFC PATCH 6/7] drm/vino: add DDC/CI brightness/contrast, DPMS power and DFU info Mike Lothian
2026-06-17 15:12 ` [RFC PATCH 7/7] drm/vino: add KUnit self-tests for the protocol and crypto paths Mike Lothian
2026-06-17 15:55 ` [RFC PATCH 0/7] drm/vino: DisplayLink DL3 dock driver (RFC, help wanted) Danilo Krummrich
2026-07-03  3:02 ` [RFC PATCH v2 00/10] drm/vino: DisplayLink DL3 dock driver Mike Lothian
2026-07-03  3:02   ` Mike Lothian [this message]
2026-07-03  3:02   ` [RFC PATCH v2 02/10] drm/vino: add the clean-room HDCP 2.2 AKE/LC/SKE handshake Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 03/10] drm/vino: add the AES-CTR/AES-CMAC control-plane seal and arm sequence Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 04/10] drm/vino: add the Vino framebuffer codec Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 05/10] drm/vino: add the DRM/KMS sink, built on the safe KMS mode-object layer Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 06/10] drm/vino: add the DisplayLink DL3 dock driver Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 07/10] drm/vino: wire the hardware cursor plane Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 08/10] drm/vino: wire CRTC gamma, plane rotation and DDC/CI monitor controls Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 09/10] drm/vino: two heads, 90/270 rotation, damage clips and connector probe Mike Lothian
2026-07-03  3:02   ` [RFC PATCH v2 10/10] drm/vino: hrtimer-driven software vblank Mike Lothian

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260703030217.2886-2-mike@fireburn.co.uk \
    --to=mike@fireburn.co.uk \
    --cc=a.hindborg@kernel.org \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=lyude@redhat.com \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tmgross@umich.edu \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox