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