mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Armin Wolf <W_Armin@gmx.de>
To: hansg@kernel.org, ilpo.jarvinen@linux.intel.com
Cc: platform-driver-x86@vger.kernel.org,
	linux-kernel@vger.kernel.org, i@rsplwe.com,
	rahulbheda131313@gmail.com, kento@kekto.ru, qby140326@gmail.com,
	martiya.ar@gmail.com, vlku.milos.fun@gmail.com,
	mm3885525@gmail.com, wleizc7319@gmail.com
Subject: [PATCH 1/2] platform/x86: bitland-mifs-wmi: Detect failed function calls
Date: Sat,  5 Sep 2026 00:45:15 +0200	[thread overview]
Message-ID: <20260904224516.8893-2-W_Armin@gmx.de> (raw)
In-Reply-To: <20260904224516.8893-1-W_Armin@gmx.de>

The first 16-bit field inside the output data of a Mifs method call
contains a return code that specifies if the method call succeeded
(0x8000) or failed due to missing support (0xE000). The second 16-bit
field should then contain the previously executed function id.

Rework the layout of both input and output data to match the format
used by the Mifs firmware and check the return code.

Tested-by: Martiya Aryan Mehr <martiya.ar@gmail.com>
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
 .../wmi/devices/bitland-mifs-wmi.rst          |  61 +++++---
 drivers/platform/x86/bitland-mifs-wmi.c       | 140 +++++++++---------
 2 files changed, 110 insertions(+), 91 deletions(-)

diff --git a/Documentation/wmi/devices/bitland-mifs-wmi.rst b/Documentation/wmi/devices/bitland-mifs-wmi.rst
index 9e86ecc2993c..314b3fbdda45 100644
--- a/Documentation/wmi/devices/bitland-mifs-wmi.rst
+++ b/Documentation/wmi/devices/bitland-mifs-wmi.rst
@@ -67,7 +67,7 @@ WMI Methods (MICommonInterface)
 
 The ``MICommonInterface`` class (GUID: ``{b60bfb48-3e5b-49e4-a0e9-8cffe1b3434b}``)
 is the primary control interface. It uses a 32-byte buffer for both input
-(``InData``) and output (``OutData``).
+(``InData``) and output (``OutData`` + ``Reserved``).
 
 Method Structure
 ----------------
@@ -77,53 +77,78 @@ The data packet follows a standardized format:
 +----------+------------------------------------------------------------------+
 | Byte     | Description                                                      |
 +==========+==================================================================+
-| 1        | Method Type: Get (0xFA / 250) or Set (0xFB / 251)                |
+| 1 and 2  | Method Type or Return Code                                       |
 +----------+------------------------------------------------------------------+
-| 3        | Command ID (Method Name)                                         |
+| 3 and 4  | Command ID (Method Name)                                         |
 +----------+------------------------------------------------------------------+
-| 4 - 31   | Arguments (for Set) or Return Data (for Get)                     |
+| 5 - 32   | Arguments (for Set) or Return Data (for Get)                     |
 +----------+------------------------------------------------------------------+
 
+Method Types
+------------
+
+The following Method types are understood by the underlying firmware:
+
++--------+---------+
+| Type   | Meaning |
++========+=========+
+| 0xFA00 | Read    |
++--------+---------+
+| 0xFB00 | Write   |
++--------+---------+
+
+Return Codes
+------------
+
+The following Return Codes are know to be returned in response to a WMI method invocation:
+
++--------+--------------------+
+| Code   | Meaning            |
++========+====================+
+| 0x8000 | Success            |
++--------+--------------------+
+| 0xE000 | Invalid Command ID |
++--------+--------------------+
 
 Command IDs
 -----------
 
-The following Command IDs are used in the third byte of the buffer:
+The following Command IDs know to be used on some models:
 
 +----------+-----------------------+------------------------------------------+
 | ID       | Name                  | Values / Description                     |
 +==========+=======================+==========================================+
-| 8        | SystemPerMode         | 0: Balance, 1: Performance, 2: Quiet,    |
+| 0x0800   | SystemPerMode         | 0: Balance, 1: Performance, 2: Quiet,    |
 |          |                       | 3: Full-speed                            |
 +----------+-----------------------+------------------------------------------+
-| 9        | GPUMode               | 0: Hybrid, 1: Discrete, 2: UMA           |
+| 0x0900   | GPUMode               | 0: Hybrid, 1: Discrete, 2: UMA           |
 +----------+-----------------------+------------------------------------------+
-| 10       | KeyboardType          | 0: White, 1: Single RGB, 2: Zone RGB     |
+| 0x0A00   | KeyboardType          | 0: White, 1: Single RGB, 2: Zone RGB     |
 +----------+-----------------------+------------------------------------------+
-| 11       | FnLock                | 0: Off, 1: On                            |
+| 0x0B00   | FnLock                | 0: Off, 1: On                            |
 +----------+-----------------------+------------------------------------------+
-| 12       | TPLock                | 0: Unlock, 1: Lock (Touchpad)            |
+| 0x0C00   | TPLock                | 0: Unlock, 1: Lock (Touchpad)            |
 +----------+-----------------------+------------------------------------------+
-| 13       | CPUGPUSYSFanSpeed     | Returns 12 bytes of fan data:            |
+| 0x0D00   | CPUGPUSYSFanSpeed     | Returns 12 bytes of fan data:            |
 |          |                       | Bytes 4-5: CPU Fan RPM (Little Endian)   |
 |          |                       | Bytes 6-7: GPU Fan RPM (Little Endian)   |
 |          |                       | Bytes 10-11: SYS Fan RPM (Little Endian) |
 +----------+-----------------------+------------------------------------------+
-| 16       | RGBKeyboardMode       | 0: Off, 1: Auto Cyclic, 2: Fixed,        |
+| 0x1000   | RGBKeyboardMode       | 0: Off, 1: Auto Cyclic, 2: Fixed,        |
 |          |                       | 3: Custom                                |
 +----------+-----------------------+------------------------------------------+
-| 17       | RGBKeyboardColor      | Bytes 4, 5, 6: Red, Green, Blue values   |
+| 0x1100   | RGBKeyboardColor      | Bytes 4, 5, 6: Red, Green, Blue values   |
 +----------+-----------------------+------------------------------------------+
-| 18       | RGBKeyboardBrightness | 0-10: Brightness Levels, 128: Auto       |
+| 0x1200   | RGBKeyboardBrightness | 0-10: Brightness Levels, 128: Auto       |
 +----------+-----------------------+------------------------------------------+
-| 19       | SystemAcType          | 1: Type-C, 2: Circular Hole (DC)         |
+| 0x1300   | SystemAcType          | 1: Type-C, 2: Circular Hole (DC)         |
 +----------+-----------------------+------------------------------------------+
-| 20       | MaxFanSpeedSwitch     | Byte 4: Fan Type (0: CPU/GPU, 1: SYS)    |
+| 0x1400   | MaxFanSpeedSwitch     | Byte 4: Fan Type (0: CPU/GPU, 1: SYS)    |
 |          |                       | Byte 5: State (0: Off, 1: On)            |
 +----------+-----------------------+------------------------------------------+
-| 21       | MaxFanSpeed           | Sets manual fan speed duty cycle         |
+| 0x1500   | MaxFanSpeed           | Sets manual fan speed duty cycle         |
 +----------+-----------------------+------------------------------------------+
-| 22       | CPUThermometer        | Returns CPU Temperature                  |
+| 0x1600   | CPUThermometer        | Returns CPU Temperature                  |
 +----------+-----------------------+------------------------------------------+
 
 WMI Events (HID_EVENT20)
diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
index 3a373184519d..cdb930eb678d 100644
--- a/drivers/platform/x86/bitland-mifs-wmi.c
+++ b/drivers/platform/x86/bitland-mifs-wmi.c
@@ -30,6 +30,7 @@
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/sysfs.h>
+#include <linux/types.h>
 #include <linux/unaligned.h>
 #include <linux/units.h>
 #include <linux/wmi.h>
@@ -39,25 +40,30 @@
 #define BITLAND_EVENT_GUID	"46C93E13-EE9B-4262-8488-563BCA757FEF"
 
 enum bitland_mifs_operation {
-	WMI_METHOD_GET	= 250,
-	WMI_METHOD_SET	= 251,
+	WMI_METHOD_GET	= 0xFA00,
+	WMI_METHOD_SET	= 0xFB00,
 };
 
 enum bitland_mifs_function {
-	WMI_FN_SYSTEM_PER_MODE		= 8,
-	WMI_FN_GPU_MODE			= 9,
-	WMI_FN_KBD_TYPE			= 10,
-	WMI_FN_FN_LOCK			= 11,
-	WMI_FN_TP_LOCK			= 12,
-	WMI_FN_FAN_SPEEDS		= 13,
-	WMI_FN_RGB_KB_MODE		= 16,
-	WMI_FN_RGB_KB_COLOR		= 17,
-	WMI_FN_RGB_KB_BRIGHTNESS	= 18,
-	WMI_FN_SYSTEM_AC_TYPE		= 19,
-	WMI_FN_MAX_FAN_SWITCH		= 20,
-	WMI_FN_MAX_FAN_SPEED		= 21,
-	WMI_FN_CPU_THERMOMETER		= 22,
-	WMI_FN_CPU_POWER		= 23,
+	WMI_FN_SYSTEM_PER_MODE		= 0x0800,
+	WMI_FN_GPU_MODE			= 0x0900,
+	WMI_FN_KBD_TYPE			= 0x0A00,
+	WMI_FN_FN_LOCK			= 0x0B00,
+	WMI_FN_TP_LOCK			= 0x0C00,
+	WMI_FN_FAN_SPEEDS		= 0x0D00,
+	WMI_FN_RGB_KB_MODE		= 0x1000,
+	WMI_FN_RGB_KB_COLOR		= 0x1100,
+	WMI_FN_RGB_KB_BRIGHTNESS	= 0x1200,
+	WMI_FN_SYSTEM_AC_TYPE		= 0x1300,
+	WMI_FN_MAX_FAN_SWITCH		= 0x1400,
+	WMI_FN_MAX_FAN_SPEED		= 0x1500,
+	WMI_FN_CPU_THERMOMETER		= 0x1600,
+	WMI_FN_CPU_POWER		= 0x1700,
+};
+
+enum bitland_mifs_return_code {
+	WMI_RETURN_CODE_SUCCESS			= 0x8000,
+	WMI_RETURN_CODE_UNKNOWN_FUNCTION	= 0xE000,
 };
 
 enum bitland_system_ac_mode {
@@ -114,18 +120,14 @@ enum bitland_wmi_device_type {
 };
 
 struct bitland_mifs_input {
-	u8 reserved1;
-	u8 operation;
-	u8 reserved2;
-	u8 function;
+	__le16 operation;
+	__le16 function;
 	u8 payload[28];
 } __packed;
 
 struct bitland_mifs_output {
-	u8 reserved1;
-	u8 operation;
-	u8 reserved2;
-	u8 function;
+	__le16 return_code;
+	__le16 function;
 	u8 data[28];
 } __packed;
 
@@ -171,15 +173,27 @@ static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data,
 
 	guard(mutex)(&data->lock);
 
-	if (!output)
-		return wmidev_invoke_procedure(data->wdev, 0, 1, &in_buf);
-
-	ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output));
+	ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf,
+				   sizeof(struct bitland_mifs_output));
 	if (ret)
 		return ret;
 
-	memcpy(output, out_buf.data, sizeof(*output));
-	kfree(out_buf.data);
+	struct bitland_mifs_output *result __free(kfree) = out_buf.data;
+
+	switch (le16_to_cpu(result->return_code)) {
+	case WMI_RETURN_CODE_SUCCESS:
+		break;
+	case WMI_RETURN_CODE_UNKNOWN_FUNCTION:
+		return -EOPNOTSUPP;
+	default:
+		return -EIO;
+	}
+
+	if (result->function != input->function)
+		return -ENOMSG;
+
+	if (output)
+		memcpy(output, result, sizeof(*output));
 
 	return 0;
 }
@@ -189,10 +203,8 @@ static int laptop_profile_get(struct device *dev,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_GET,
-		.reserved2 = 0,
-		.function = WMI_FN_SYSTEM_PER_MODE,
+		.operation = cpu_to_le16(WMI_METHOD_GET),
+		.function = cpu_to_le16(WMI_FN_SYSTEM_PER_MODE),
 	};
 	struct bitland_mifs_output result;
 	int ret;
@@ -223,8 +235,8 @@ static int laptop_profile_get(struct device *dev,
 static int bitland_check_performance_capability(struct bitland_mifs_wmi_data *data)
 {
 	struct bitland_mifs_input input = {
-		.operation = WMI_METHOD_GET,
-		.function = WMI_FN_SYSTEM_AC_TYPE,
+		.operation = cpu_to_le16(WMI_METHOD_GET),
+		.function = cpu_to_le16(WMI_FN_SYSTEM_AC_TYPE),
 	};
 	struct bitland_mifs_output output;
 	int ret;
@@ -248,10 +260,8 @@ static int laptop_profile_set(struct device *dev,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_SET,
-		.reserved2 = 0,
-		.function = WMI_FN_SYSTEM_PER_MODE,
+		.operation = cpu_to_le16(WMI_METHOD_SET),
+		.function = cpu_to_le16(WMI_FN_SYSTEM_PER_MODE),
 	};
 	int ret;
 	u8 val;
@@ -344,22 +354,20 @@ static int laptop_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_GET,
-		.reserved2 = 0,
+		.operation = cpu_to_le16(WMI_METHOD_GET),
 	};
 	struct bitland_mifs_output res;
 	int ret;
 
 	switch (type) {
 	case hwmon_temp:
-		input.function = WMI_FN_CPU_THERMOMETER;
+		input.function = cpu_to_le16(WMI_FN_CPU_THERMOMETER);
 		ret = bitland_mifs_wmi_call(data, &input, &res);
 		if (!ret)
 			*val = res.data[0] * MILLIDEGREE_PER_DEGREE;
 		return ret;
 	case hwmon_fan:
-		input.function = WMI_FN_FAN_SPEEDS;
+		input.function = cpu_to_le16(WMI_FN_FAN_SPEEDS);
 		ret = bitland_mifs_wmi_call(data, &input, &res);
 		if (ret)
 			return ret;
@@ -420,10 +428,8 @@ static int laptop_kbd_led_set(struct led_classdev *led_cdev,
 	struct bitland_mifs_wmi_data *data =
 		container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_SET,
-		.reserved2 = 0,
-		.function = WMI_FN_RGB_KB_BRIGHTNESS,
+		.operation = cpu_to_le16(WMI_METHOD_SET),
+		.function = cpu_to_le16(WMI_FN_RGB_KB_BRIGHTNESS),
 	};
 
 	input.payload[0] = (u8)value;
@@ -436,10 +442,8 @@ static enum led_brightness laptop_kbd_led_get(struct led_classdev *led_cdev)
 	struct bitland_mifs_wmi_data *data =
 		container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_GET,
-		.reserved2 = 0,
-		.function = WMI_FN_RGB_KB_BRIGHTNESS,
+		.operation = cpu_to_le16(WMI_METHOD_GET),
+		.function = cpu_to_le16(WMI_FN_RGB_KB_BRIGHTNESS),
 	};
 	struct bitland_mifs_output res;
 	int ret;
@@ -463,10 +467,8 @@ static ssize_t gpu_mode_show(struct device *dev, struct device_attribute *attr,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_GET,
-		.reserved2 = 0,
-		.function = WMI_FN_GPU_MODE,
+		.operation = cpu_to_le16(WMI_METHOD_GET),
+		.function = cpu_to_le16(WMI_FN_GPU_MODE),
 	};
 	struct bitland_mifs_output res;
 	u8 mode_val;
@@ -488,10 +490,8 @@ static ssize_t gpu_mode_store(struct device *dev, struct device_attribute *attr,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_SET,
-		.reserved2 = 0,
-		.function = WMI_FN_GPU_MODE,
+		.operation = cpu_to_le16(WMI_METHOD_SET),
+		.function = cpu_to_le16(WMI_FN_GPU_MODE),
 	};
 	int val;
 	int ret;
@@ -521,10 +521,8 @@ static ssize_t kb_mode_show(struct device *dev, struct device_attribute *attr,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_GET,
-		.reserved2 = 0,
-		.function = WMI_FN_RGB_KB_MODE,
+		.operation = cpu_to_le16(WMI_METHOD_GET),
+		.function = cpu_to_le16(WMI_FN_RGB_KB_MODE),
 	};
 	struct bitland_mifs_output res;
 	u8 mode_val;
@@ -546,10 +544,8 @@ static ssize_t kb_mode_store(struct device *dev, struct device_attribute *attr,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_SET,
-		.reserved2 = 0,
-		.function = WMI_FN_RGB_KB_MODE,
+		.operation = cpu_to_le16(WMI_METHOD_SET),
+		.function = cpu_to_le16(WMI_FN_RGB_KB_MODE),
 	};
 	// the wmi value (0, 1, 2 or 3)
 	int val;
@@ -575,10 +571,8 @@ static ssize_t fan_boost_store(struct device *dev,
 {
 	struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
 	struct bitland_mifs_input input = {
-		.reserved1 = 0,
-		.operation = WMI_METHOD_SET,
-		.reserved2 = 0,
-		.function = WMI_FN_MAX_FAN_SWITCH,
+		.operation = cpu_to_le16(WMI_METHOD_SET),
+		.function = cpu_to_le16(WMI_FN_MAX_FAN_SWITCH),
 	};
 	bool val;
 	int ret;
-- 
2.39.5


  reply	other threads:[~2026-09-04 22:45 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04 22:45 [PATCH 0/2] Fix for platform profile issues on USB-C-only models Armin Wolf
2026-09-04 22:45 ` Armin Wolf [this message]
2026-09-04 22:45 ` [PATCH 2/2] platform/x86: bitland-mifs-wmi: Treat WMI_FN_SYSTEM_AC_TYPE as optional Armin Wolf
2026-09-15 11:32 ` [PATCH 0/2] Fix for platform profile issues on USB-C-only models Ilpo Järvinen
2026-09-15 21:26   ` Armin Wolf

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=20260904224516.8893-2-W_Armin@gmx.de \
    --to=w_armin@gmx.de \
    --cc=hansg@kernel.org \
    --cc=i@rsplwe.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=kento@kekto.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martiya.ar@gmail.com \
    --cc=mm3885525@gmail.com \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=qby140326@gmail.com \
    --cc=rahulbheda131313@gmail.com \
    --cc=vlku.milos.fun@gmail.com \
    --cc=wleizc7319@gmail.com \
    /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

all inboxes | Powered by JetHome®