platform/surface: Add DTX driver

The Microsoft Surface Book series devices consist of a so-called
clipboard part (containing the CPU, touchscreen, and primary battery)
and a base part (containing keyboard, secondary battery, and optional
discrete GPU). These parts can be separated, i.e. the clipboard can be
detached and used as tablet.

This detachment process is initiated by pressing a button. On the
Surface Book 2 and 3 (targeted with this commit), the Surface Aggregator
Module (i.e. the embedded controller on those devices) attempts to send
a notification to any listening client driver and waits for further
instructions (i.e. whether the detachment process should continue or be
aborted). If it does not receive a response in a certain time-frame, the
detachment process (by default) continues and the clipboard can be
physically separated. In other words, (by default and) without a driver,
the detachment process takes about 10 seconds to complete.

This commit introduces a driver for this detachment system (called DTX).
This driver allows a user-space daemon to control and influence the
detachment behavior. Specifically, it forwards any detachment requests
to user-space, allows user-space to make such requests itself, and
allows handling of those requests. Requests can be handled by either
aborting, continuing/allowing, or delaying (i.e. resetting the timeout
via a heartbeat commend). The user-space API is implemented via the
/dev/surface/dtx miscdevice.

In addition, user-space can change the default behavior on timeout from
allowing detachment to disallowing it, which is useful if the (optional)
discrete GPU is in use.

Furthermore, this driver allows user-space to receive notifications
about the state of the base, specifically when it is physically removed
(as opposed to detachment requested), in what manner it is connected
(i.e. in reverse-/tent-/studio- or laptop-mode), and what type of base
is connected. Based on this information, the driver also provides a
simple tablet-mode switch (aliasing all modes without keyboard access,
i.e. tablet-mode and studio-mode to its reported tablet-mode).

An implementation of such a user-space daemon, allowing configuration of
detachment behavior via scripts (e.g. safely unmounting USB devices
connected to the base before continuing) can be found at [1].

[1]: https://github.com/linux-surface/surface-dtx-daemon

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Link: https://lore.kernel.org/r/20210308184819.437438-2-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Maximilian Luz 2021-03-08 19:48:17 +01:00 committed by Hans de Goede
parent 87eaede453
commit 1d60999283
6 changed files with 1373 additions and 0 deletions

View File

@ -327,6 +327,8 @@ Code Seq# Include File Comments
0xA4 00-1F uapi/asm/sgx.h <mailto:linux-sgx@vger.kernel.org>
0xA5 01 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator
<mailto:luzmaximilian@gmail.com>
0xA5 20-2F linux/surface_aggregator/dtx.h Microsoft Surface DTX driver
<mailto:luzmaximilian@gmail.com>
0xAA 00-3F linux/uapi/linux/userfaultfd.h
0xAB 00-1F linux/nbd.h
0xAC 00-1F linux/raw.h

View File

@ -11861,6 +11861,13 @@ F: drivers/scsi/smartpqi/smartpqi*.[ch]
F: include/linux/cciss*.h
F: include/uapi/linux/cciss*.h
MICROSOFT SURFACE DTX DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/surface/surface_dtx.c
F: include/uapi/linux/surface_aggregator/dtx.h
MICROSOFT SURFACE GPE LID SUPPORT DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org

View File

@ -104,6 +104,22 @@ config SURFACE_AGGREGATOR_REGISTRY
the respective client devices. Drivers for these devices still need to
be selected via the other options.
config SURFACE_DTX
tristate "Surface DTX (Detachment System) Driver"
depends on SURFACE_AGGREGATOR
depends on INPUT
help
Driver for the Surface Book clipboard detachment system (DTX).
On the Surface Book series devices, the display part containing the
CPU (called the clipboard) can be detached from the base (containing a
battery, the keyboard, and, optionally, a discrete GPU) by (if
necessary) unlocking and opening the latch connecting both parts.
This driver provides a user-space interface that can influence the
behavior of this process, which includes the option to abort it in
case the base is still in use or speed it up in case it is not.
config SURFACE_GPE
tristate "Surface GPE/Lid Support Driver"
depends on DMI

View File

@ -11,6 +11,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o
obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o
obj-$(CONFIG_SURFACE_PLATFORM_PROFILE) += surface_platform_profile.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* Surface DTX (clipboard detachment system driver) user-space interface.
*
* Definitions, structs, and IOCTLs for the /dev/surface/dtx misc device. This
* device allows user-space to control the clipboard detachment process on
* Surface Book series devices.
*
* Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
*/
#ifndef _UAPI_LINUX_SURFACE_AGGREGATOR_DTX_H
#define _UAPI_LINUX_SURFACE_AGGREGATOR_DTX_H
#include <linux/ioctl.h>
#include <linux/types.h>
/* Status/error categories */
#define SDTX_CATEGORY_STATUS 0x0000
#define SDTX_CATEGORY_RUNTIME_ERROR 0x1000
#define SDTX_CATEGORY_HARDWARE_ERROR 0x2000
#define SDTX_CATEGORY_UNKNOWN 0xf000
#define SDTX_CATEGORY_MASK 0xf000
#define SDTX_CATEGORY(value) ((value) & SDTX_CATEGORY_MASK)
#define SDTX_STATUS(code) ((code) | SDTX_CATEGORY_STATUS)
#define SDTX_ERR_RT(code) ((code) | SDTX_CATEGORY_RUNTIME_ERROR)
#define SDTX_ERR_HW(code) ((code) | SDTX_CATEGORY_HARDWARE_ERROR)
#define SDTX_UNKNOWN(code) ((code) | SDTX_CATEGORY_UNKNOWN)
#define SDTX_SUCCESS(value) (SDTX_CATEGORY(value) == SDTX_CATEGORY_STATUS)
/* Latch status values */
#define SDTX_LATCH_CLOSED SDTX_STATUS(0x00)
#define SDTX_LATCH_OPENED SDTX_STATUS(0x01)
/* Base state values */
#define SDTX_BASE_DETACHED SDTX_STATUS(0x00)
#define SDTX_BASE_ATTACHED SDTX_STATUS(0x01)
/* Runtime errors (non-critical) */
#define SDTX_DETACH_NOT_FEASIBLE SDTX_ERR_RT(0x01)
#define SDTX_DETACH_TIMEDOUT SDTX_ERR_RT(0x02)
/* Hardware errors (critical) */
#define SDTX_ERR_FAILED_TO_OPEN SDTX_ERR_HW(0x01)
#define SDTX_ERR_FAILED_TO_REMAIN_OPEN SDTX_ERR_HW(0x02)
#define SDTX_ERR_FAILED_TO_CLOSE SDTX_ERR_HW(0x03)
/* Base types */
#define SDTX_DEVICE_TYPE_HID 0x0100
#define SDTX_DEVICE_TYPE_SSH 0x0200
#define SDTX_DEVICE_TYPE_MASK 0x0f00
#define SDTX_DEVICE_TYPE(value) ((value) & SDTX_DEVICE_TYPE_MASK)
#define SDTX_BASE_TYPE_HID(id) ((id) | SDTX_DEVICE_TYPE_HID)
#define SDTX_BASE_TYPE_SSH(id) ((id) | SDTX_DEVICE_TYPE_SSH)
/**
* enum sdtx_device_mode - Mode describing how (and if) the clipboard is
* attached to the base of the device.
* @SDTX_DEVICE_MODE_TABLET: The clipboard is detached from the base and the
* device operates as tablet.
* @SDTX_DEVICE_MODE_LAPTOP: The clipboard is attached normally to the base
* and the device operates as laptop.
* @SDTX_DEVICE_MODE_STUDIO: The clipboard is attached to the base in reverse.
* The device operates as tablet with keyboard and
* touchpad deactivated, however, the base battery
* and, if present in the specific device model, dGPU
* are available to the system.
*/
enum sdtx_device_mode {
SDTX_DEVICE_MODE_TABLET = 0x00,
SDTX_DEVICE_MODE_LAPTOP = 0x01,
SDTX_DEVICE_MODE_STUDIO = 0x02,
};
/**
* struct sdtx_event - Event provided by reading from the DTX device file.
* @length: Length of the event payload, in bytes.
* @code: Event code, detailing what type of event this is.
* @data: Payload of the event, containing @length bytes.
*
* See &enum sdtx_event_code for currently valid event codes.
*/
struct sdtx_event {
__u16 length;
__u16 code;
__u8 data[];
} __attribute__((__packed__));
/**
* enum sdtx_event_code - Code describing the type of an event.
* @SDTX_EVENT_REQUEST: Detachment request event type.
* @SDTX_EVENT_CANCEL: Cancel detachment process event type.
* @SDTX_EVENT_BASE_CONNECTION: Base/clipboard connection change event type.
* @SDTX_EVENT_LATCH_STATUS: Latch status change event type.
* @SDTX_EVENT_DEVICE_MODE: Device mode change event type.
*
* Used in &struct sdtx_event to describe the type of the event. Further event
* codes are reserved for future use. Any event parser should be able to
* gracefully handle unknown events, i.e. by simply skipping them.
*
* Consult the DTX user-space interface documentation for details regarding
* the individual event types.
*/
enum sdtx_event_code {
SDTX_EVENT_REQUEST = 1,
SDTX_EVENT_CANCEL = 2,
SDTX_EVENT_BASE_CONNECTION = 3,
SDTX_EVENT_LATCH_STATUS = 4,
SDTX_EVENT_DEVICE_MODE = 5,
};
/**
* struct sdtx_base_info - Describes if and what type of base is connected.
* @state: The state of the connection. Valid values are %SDTX_BASE_DETACHED,
* %SDTX_BASE_ATTACHED, and %SDTX_DETACH_NOT_FEASIBLE (in case a base
* is attached but low clipboard battery prevents detachment). Other
* values are currently reserved.
* @base_id: The type of base connected. Zero if no base is connected.
*/
struct sdtx_base_info {
__u16 state;
__u16 base_id;
} __attribute__((__packed__));
/* IOCTLs */
#define SDTX_IOCTL_EVENTS_ENABLE _IO(0xa5, 0x21)
#define SDTX_IOCTL_EVENTS_DISABLE _IO(0xa5, 0x22)
#define SDTX_IOCTL_LATCH_LOCK _IO(0xa5, 0x23)
#define SDTX_IOCTL_LATCH_UNLOCK _IO(0xa5, 0x24)
#define SDTX_IOCTL_LATCH_REQUEST _IO(0xa5, 0x25)
#define SDTX_IOCTL_LATCH_CONFIRM _IO(0xa5, 0x26)
#define SDTX_IOCTL_LATCH_HEARTBEAT _IO(0xa5, 0x27)
#define SDTX_IOCTL_LATCH_CANCEL _IO(0xa5, 0x28)
#define SDTX_IOCTL_GET_BASE_INFO _IOR(0xa5, 0x29, struct sdtx_base_info)
#define SDTX_IOCTL_GET_DEVICE_MODE _IOR(0xa5, 0x2a, __u16)
#define SDTX_IOCTL_GET_LATCH_STATUS _IOR(0xa5, 0x2b, __u16)
#endif /* _UAPI_LINUX_SURFACE_AGGREGATOR_DTX_H */