Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: Add new sysfs interface to export device description

Add support to export the device description obtained from the ACPI _STR
method, if one exists for a device, to user-space via a sysfs interface.
This new interface provides a standard and platform neutral way for users
to obtain the description text stored in the ACPI _STR method. If no
_STR method exists for the device, no sysfs 'description' file will be
created. The 'description' file will be located in the /sys/devices/
directory using the device's path.

/sys/device/<bus>/<bridge path>/<device path>.../firmware_node/description

Example:

/sys/devices/pci0000:00/0000:00.07.0/0000:0e:00.0/firmware_node/description

It can also be located using the ACPI device path, for example:

/sys/devices/LNXSYSTM:00/device:00/ACPI0004:00/PNP0A08:00/device:13/device:15/description
/sys/devices/LNXSYSTM:00/device:00/ACPI0004:00/ACPI0004:01/ACPI0007:02/description

Execute the 'cat' command on the 'description' file to obtain the
description string for that device.

This patch also includes documentation describing how the new sysfs
interface works

Changes from v1-v2 based on comments by Len Brown and Fengguang Wu
* Removed output "No Description" and leaving a NULL attribute if the
_STR method failed to evaluate.

* In acpi_device_remove_files() removed the redundent check of
dev->pnp.str_obj before calling free. This check triggered a message
from smatch.

Signed-off-by: Lance Ortiz <lance.ortiz@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Lance Ortiz and committed by
Len Brown
d1efe3c3 369d913b

+70 -2
+17
Documentation/ABI/testing/sysfs-devices-firmware_node
··· 1 + What: /sys/devices/.../firmware_node/ 2 + Date: September 2012 3 + Contact: <> 4 + Description: 5 + The /sys/devices/.../firmware_node directory contains attributes 6 + allowing the user space to check and modify some firmware 7 + related properties of given device. 8 + 9 + What: /sys/devices/.../firmware_node/description 10 + Date: September 2012 11 + Contact: Lance Ortiz <lance.ortiz@hp.com> 12 + Description: 13 + The /sys/devices/.../firmware/description attribute contains a string 14 + that describes the device as provided by the _STR method in the ACPI 15 + namespace. This attribute is read-only. If the device does not have 16 + an _STR method associated with it in the ACPI namespace, this 17 + attribute is not present.
+52 -2
drivers/acpi/scan.c
··· 10 10 #include <linux/signal.h> 11 11 #include <linux/kthread.h> 12 12 #include <linux/dmi.h> 13 + #include <linux/nls.h> 13 14 14 15 #include <acpi/acpi_drivers.h> 15 16 ··· 233 232 } 234 233 static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); 235 234 235 + /* sysfs file that shows description text from the ACPI _STR method */ 236 + static ssize_t description_show(struct device *dev, 237 + struct device_attribute *attr, 238 + char *buf) { 239 + struct acpi_device *acpi_dev = to_acpi_device(dev); 240 + int result; 241 + 242 + if (acpi_dev->pnp.str_obj == NULL) 243 + return 0; 244 + 245 + /* 246 + * The _STR object contains a Unicode identifier for a device. 247 + * We need to convert to utf-8 so it can be displayed. 248 + */ 249 + result = utf16s_to_utf8s( 250 + (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer, 251 + acpi_dev->pnp.str_obj->buffer.length, 252 + UTF16_LITTLE_ENDIAN, buf, 253 + PAGE_SIZE); 254 + 255 + buf[result++] = '\n'; 256 + 257 + return result; 258 + } 259 + static DEVICE_ATTR(description, 0444, description_show, NULL); 260 + 236 261 static int acpi_device_setup_files(struct acpi_device *dev) 237 262 { 263 + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 238 264 acpi_status status; 239 265 acpi_handle temp; 240 266 int result = 0; ··· 285 257 goto end; 286 258 } 287 259 260 + /* 261 + * If device has _STR, 'description' file is created 262 + */ 263 + status = acpi_get_handle(dev->handle, "_STR", &temp); 264 + if (ACPI_SUCCESS(status)) { 265 + status = acpi_evaluate_object(dev->handle, "_STR", 266 + NULL, &buffer); 267 + if (ACPI_FAILURE(status)) 268 + buffer.pointer = NULL; 269 + dev->pnp.str_obj = buffer.pointer; 270 + result = device_create_file(&dev->dev, &dev_attr_description); 271 + if (result) 272 + goto end; 273 + } 274 + 288 275 /* 289 276 * If device has _EJ0, 'eject' file is created that is used to trigger 290 277 * hot-removal function from userland. ··· 317 274 acpi_handle temp; 318 275 319 276 /* 320 - * If device has _EJ0, 'eject' file is created that is used to trigger 321 - * hot-removal function from userland. 277 + * If device has _STR, remove 'description' file 278 + */ 279 + status = acpi_get_handle(dev->handle, "_STR", &temp); 280 + if (ACPI_SUCCESS(status)) { 281 + kfree(dev->pnp.str_obj); 282 + device_remove_file(&dev->dev, &dev_attr_description); 283 + } 284 + /* 285 + * If device has _EJ0, remove 'eject' file. 322 286 */ 323 287 status = acpi_get_handle(dev->handle, "_EJ0", &temp); 324 288 if (ACPI_SUCCESS(status))
+1
include/acpi/acpi_bus.h
··· 208 208 struct list_head ids; /* _HID and _CIDs */ 209 209 acpi_device_name device_name; /* Driver-determined */ 210 210 acpi_device_class device_class; /* " */ 211 + union acpi_object *str_obj; /* unicode string for _STR method */ 211 212 }; 212 213 213 214 #define acpi_device_bid(d) ((d)->pnp.bus_id)