1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* This code gives functions to avoid code duplication while interacting with
* the TUXEDO NB04 wmi interfaces.
*
* Copyright (C) 2024-2025 Werner Sembach <wse@tuxedocomputers.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/cleanup.h>
#include <linux/wmi.h>
#include "wmi_util.h"
static int __wmi_method_acpi_object_out(struct wmi_device *wdev,
u32 wmi_method_id,
u8 *in,
acpi_size in_len,
union acpi_object **out)
{
struct acpi_buffer acpi_buffer_in = { in_len, in };
struct acpi_buffer acpi_buffer_out = { ACPI_ALLOCATE_BUFFER, NULL };
dev_dbg(&wdev->dev, "Evaluate WMI method: %u in:\n", wmi_method_id);
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, in, in_len);
acpi_status status = wmidev_evaluate_method(wdev, 0, wmi_method_id,
&acpi_buffer_in,
&acpi_buffer_out);
if (ACPI_FAILURE(status)) {
dev_err(&wdev->dev, "Failed to evaluate WMI method.\n");
return -EIO;
}
if (!acpi_buffer_out.pointer) {
dev_err(&wdev->dev, "Unexpected empty out buffer.\n");
return -ENODATA;
}
*out = acpi_buffer_out.pointer;
return 0;
}
static int __wmi_method_buffer_out(struct wmi_device *wdev,
u32 wmi_method_id,
u8 *in,
acpi_size in_len,
u8 *out,
acpi_size out_len)
{
int ret;
union acpi_object *acpi_object_out __free(kfree) = NULL;
ret = __wmi_method_acpi_object_out(wdev, wmi_method_id,
in, in_len,
&acpi_object_out);
if (ret)
return ret;
if (acpi_object_out->type != ACPI_TYPE_BUFFER) {
dev_err(&wdev->dev, "Unexpected out buffer type. Expected: %u Got: %u\n",
ACPI_TYPE_BUFFER, acpi_object_out->type);
return -EIO;
}
if (acpi_object_out->buffer.length < out_len) {
dev_err(&wdev->dev, "Unexpected out buffer length.\n");
return -EIO;
}
memcpy(out, acpi_object_out->buffer.pointer, out_len);
return 0;
}
int tux_wmi_xx_8in_80out(struct wmi_device *wdev,
enum tux_wmi_xx_8in_80out_methods method,
union tux_wmi_xx_8in_80out_in_t *in,
union tux_wmi_xx_8in_80out_out_t *out)
{
return __wmi_method_buffer_out(wdev, method, in->raw, 8, out->raw, 80);
}
int tux_wmi_xx_496in_80out(struct wmi_device *wdev,
enum tux_wmi_xx_496in_80out_methods method,
union tux_wmi_xx_496in_80out_in_t *in,
union tux_wmi_xx_496in_80out_out_t *out)
{
return __wmi_method_buffer_out(wdev, method, in->raw, 496, out->raw, 80);
}
|