diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-firmware_node | 17 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 54 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 1 |
3 files changed, 70 insertions, 2 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-firmware_node b/Documentation/ABI/testing/sysfs-devices-firmware_node new file mode 100644 index 000000000000..46badc9ea284 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-firmware_node @@ -0,0 +1,17 @@ +What: /sys/devices/.../firmware_node/ +Date: September 2012 +Contact: <> +Description: + The /sys/devices/.../firmware_node directory contains attributes + allowing the user space to check and modify some firmware + related properties of given device. + +What: /sys/devices/.../firmware_node/description +Date: September 2012 +Contact: Lance Ortiz <lance.ortiz@hp.com> +Description: + The /sys/devices/.../firmware/description attribute contains a string + that describes the device as provided by the _STR method in the ACPI + namespace. This attribute is read-only. If the device does not have + an _STR method associated with it in the ACPI namespace, this + attribute is not present. diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d1ecca2b641a..04302835723d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -10,6 +10,7 @@ #include <linux/signal.h> #include <linux/kthread.h> #include <linux/dmi.h> +#include <linux/nls.h> #include <acpi/acpi_drivers.h> @@ -232,8 +233,35 @@ end: } static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); +/* sysfs file that shows description text from the ACPI _STR method */ +static ssize_t description_show(struct device *dev, + struct device_attribute *attr, + char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); + int result; + + if (acpi_dev->pnp.str_obj == NULL) + return 0; + + /* + * The _STR object contains a Unicode identifier for a device. + * We need to convert to utf-8 so it can be displayed. + */ + result = utf16s_to_utf8s( + (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer, + acpi_dev->pnp.str_obj->buffer.length, + UTF16_LITTLE_ENDIAN, buf, + PAGE_SIZE); + + buf[result++] = '\n'; + + return result; +} +static DEVICE_ATTR(description, 0444, description_show, NULL); + static int acpi_device_setup_files(struct acpi_device *dev) { + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_status status; acpi_handle temp; int result = 0; @@ -257,6 +285,21 @@ static int acpi_device_setup_files(struct acpi_device *dev) goto end; } + /* + * If device has _STR, 'description' file is created + */ + status = acpi_get_handle(dev->handle, "_STR", &temp); + if (ACPI_SUCCESS(status)) { + status = acpi_evaluate_object(dev->handle, "_STR", + NULL, &buffer); + if (ACPI_FAILURE(status)) + buffer.pointer = NULL; + dev->pnp.str_obj = buffer.pointer; + result = device_create_file(&dev->dev, &dev_attr_description); + if (result) + goto end; + } + /* * If device has _EJ0, 'eject' file is created that is used to trigger * hot-removal function from userland. @@ -274,8 +317,15 @@ static void acpi_device_remove_files(struct acpi_device *dev) acpi_handle temp; /* - * If device has _EJ0, 'eject' file is created that is used to trigger - * hot-removal function from userland. + * If device has _STR, remove 'description' file + */ + status = acpi_get_handle(dev->handle, "_STR", &temp); + if (ACPI_SUCCESS(status)) { + kfree(dev->pnp.str_obj); + device_remove_file(&dev->dev, &dev_attr_description); + } + /* + * If device has _EJ0, remove 'eject' file. */ status = acpi_get_handle(dev->handle, "_EJ0", &temp); if (ACPI_SUCCESS(status)) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index bde976ee068d..3eb9de318824 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -208,6 +208,7 @@ struct acpi_device_pnp { struct list_head ids; /* _HID and _CIDs */ acpi_device_name device_name; /* Driver-determined */ acpi_device_class device_class; /* " */ + union acpi_object *str_obj; /* unicode string for _STR method */ }; #define acpi_device_bid(d) ((d)->pnp.bus_id) |