aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorLance Ortiz <lance.ortiz@hp.com>2012-10-02 14:43:23 -0400
committerLen Brown <len.brown@intel.com>2012-10-06 15:52:16 -0400
commitd1efe3c324ead77d3f6cd85093b50f6bd2e17aba (patch)
tree7c85ab68cc0d906c0479e816d955481723e945b1 /drivers/acpi/scan.c
parent369d913b242cae2205471b11b6e33ac368ed33ec (diff)
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>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c54
1 files changed, 52 insertions, 2 deletions
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 @@
10#include <linux/signal.h> 10#include <linux/signal.h>
11#include <linux/kthread.h> 11#include <linux/kthread.h>
12#include <linux/dmi.h> 12#include <linux/dmi.h>
13#include <linux/nls.h>
13 14
14#include <acpi/acpi_drivers.h> 15#include <acpi/acpi_drivers.h>
15 16
@@ -232,8 +233,35 @@ end:
232} 233}
233static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); 234static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
234 235
236/* sysfs file that shows description text from the ACPI _STR method */
237static ssize_t description_show(struct device *dev,
238 struct device_attribute *attr,
239 char *buf) {
240 struct acpi_device *acpi_dev = to_acpi_device(dev);
241 int result;
242
243 if (acpi_dev->pnp.str_obj == NULL)
244 return 0;
245
246 /*
247 * The _STR object contains a Unicode identifier for a device.
248 * We need to convert to utf-8 so it can be displayed.
249 */
250 result = utf16s_to_utf8s(
251 (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
252 acpi_dev->pnp.str_obj->buffer.length,
253 UTF16_LITTLE_ENDIAN, buf,
254 PAGE_SIZE);
255
256 buf[result++] = '\n';
257
258 return result;
259}
260static DEVICE_ATTR(description, 0444, description_show, NULL);
261
235static int acpi_device_setup_files(struct acpi_device *dev) 262static int acpi_device_setup_files(struct acpi_device *dev)
236{ 263{
264 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
237 acpi_status status; 265 acpi_status status;
238 acpi_handle temp; 266 acpi_handle temp;
239 int result = 0; 267 int result = 0;
@@ -257,6 +285,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
257 goto end; 285 goto end;
258 } 286 }
259 287
288 /*
289 * If device has _STR, 'description' file is created
290 */
291 status = acpi_get_handle(dev->handle, "_STR", &temp);
292 if (ACPI_SUCCESS(status)) {
293 status = acpi_evaluate_object(dev->handle, "_STR",
294 NULL, &buffer);
295 if (ACPI_FAILURE(status))
296 buffer.pointer = NULL;
297 dev->pnp.str_obj = buffer.pointer;
298 result = device_create_file(&dev->dev, &dev_attr_description);
299 if (result)
300 goto end;
301 }
302
260 /* 303 /*
261 * If device has _EJ0, 'eject' file is created that is used to trigger 304 * If device has _EJ0, 'eject' file is created that is used to trigger
262 * hot-removal function from userland. 305 * hot-removal function from userland.
@@ -274,8 +317,15 @@ static void acpi_device_remove_files(struct acpi_device *dev)
274 acpi_handle temp; 317 acpi_handle temp;
275 318
276 /* 319 /*
277 * If device has _EJ0, 'eject' file is created that is used to trigger 320 * If device has _STR, remove 'description' file
278 * hot-removal function from userland. 321 */
322 status = acpi_get_handle(dev->handle, "_STR", &temp);
323 if (ACPI_SUCCESS(status)) {
324 kfree(dev->pnp.str_obj);
325 device_remove_file(&dev->dev, &dev_attr_description);
326 }
327 /*
328 * If device has _EJ0, remove 'eject' file.
279 */ 329 */
280 status = acpi_get_handle(dev->handle, "_EJ0", &temp); 330 status = acpi_get_handle(dev->handle, "_EJ0", &temp);
281 if (ACPI_SUCCESS(status)) 331 if (ACPI_SUCCESS(status))