]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/acpi/device_sysfs.c
[media] s5p-mfc: Correct misuse of %0x<decimal>
[karo-tx-linux.git] / drivers / acpi / device_sysfs.c
1 /*
2  * drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.
3  *
4  * Copyright (C) 2015, Intel Corp.
5  * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
6  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
7  *
8  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2 as published
12  *  by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful, but
15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  General Public License for more details.
18  *
19  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20  */
21
22 #include <linux/acpi.h>
23 #include <linux/device.h>
24 #include <linux/export.h>
25 #include <linux/nls.h>
26
27 #include "internal.h"
28
29 /**
30  * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
31  * @acpi_dev: ACPI device object.
32  * @modalias: Buffer to print into.
33  * @size: Size of the buffer.
34  *
35  * Creates hid/cid(s) string needed for modalias and uevent
36  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
37  * char *modalias: "acpi:IBM0001:ACPI0001"
38  * Return: 0: no _HID and no _CID
39  *         -EINVAL: output error
40  *         -ENOMEM: output is truncated
41 */
42 static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
43                                int size)
44 {
45         int len;
46         int count;
47         struct acpi_hardware_id *id;
48
49         /*
50          * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
51          * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
52          * device's list.
53          */
54         count = 0;
55         list_for_each_entry(id, &acpi_dev->pnp.ids, list)
56                 if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
57                         count++;
58
59         if (!count)
60                 return 0;
61
62         len = snprintf(modalias, size, "acpi:");
63         if (len <= 0)
64                 return len;
65
66         size -= len;
67
68         list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
69                 if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
70                         continue;
71
72                 count = snprintf(&modalias[len], size, "%s:", id->id);
73                 if (count < 0)
74                         return -EINVAL;
75
76                 if (count >= size)
77                         return -ENOMEM;
78
79                 len += count;
80                 size -= count;
81         }
82         modalias[len] = '\0';
83         return len;
84 }
85
86 /**
87  * create_of_modalias - Creates DT compatible string for modalias and uevent
88  * @acpi_dev: ACPI device object.
89  * @modalias: Buffer to print into.
90  * @size: Size of the buffer.
91  *
92  * Expose DT compatible modalias as of:NnameTCcompatible.  This function should
93  * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
94  * ACPI/PNP IDs.
95  */
96 static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
97                               int size)
98 {
99         struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
100         const union acpi_object *of_compatible, *obj;
101         int len, count;
102         int i, nval;
103         char *c;
104
105         acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
106         /* DT strings are all in lower case */
107         for (c = buf.pointer; *c != '\0'; c++)
108                 *c = tolower(*c);
109
110         len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
111         ACPI_FREE(buf.pointer);
112
113         if (len <= 0)
114                 return len;
115
116         of_compatible = acpi_dev->data.of_compatible;
117         if (of_compatible->type == ACPI_TYPE_PACKAGE) {
118                 nval = of_compatible->package.count;
119                 obj = of_compatible->package.elements;
120         } else { /* Must be ACPI_TYPE_STRING. */
121                 nval = 1;
122                 obj = of_compatible;
123         }
124         for (i = 0; i < nval; i++, obj++) {
125                 count = snprintf(&modalias[len], size, "C%s",
126                                  obj->string.pointer);
127                 if (count < 0)
128                         return -EINVAL;
129
130                 if (count >= size)
131                         return -ENOMEM;
132
133                 len += count;
134                 size -= count;
135         }
136         modalias[len] = '\0';
137         return len;
138 }
139
140 int __acpi_device_uevent_modalias(struct acpi_device *adev,
141                                   struct kobj_uevent_env *env)
142 {
143         int len;
144
145         if (!adev)
146                 return -ENODEV;
147
148         if (list_empty(&adev->pnp.ids))
149                 return 0;
150
151         if (add_uevent_var(env, "MODALIAS="))
152                 return -ENOMEM;
153
154         len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
155                                   sizeof(env->buf) - env->buflen);
156         if (len < 0)
157                 return len;
158
159         env->buflen += len;
160         if (!adev->data.of_compatible)
161                 return 0;
162
163         if (len > 0 && add_uevent_var(env, "MODALIAS="))
164                 return -ENOMEM;
165
166         len = create_of_modalias(adev, &env->buf[env->buflen - 1],
167                                  sizeof(env->buf) - env->buflen);
168         if (len < 0)
169                 return len;
170
171         env->buflen += len;
172
173         return 0;
174 }
175
176 /**
177  * acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.
178  *
179  * Create the uevent modalias field for ACPI-enumerated devices.
180  *
181  * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
182  * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
183  */
184 int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
185 {
186         return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
187 }
188 EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
189
190 static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
191 {
192         int len, count;
193
194         if (!adev)
195                 return -ENODEV;
196
197         if (list_empty(&adev->pnp.ids))
198                 return 0;
199
200         len = create_pnp_modalias(adev, buf, size - 1);
201         if (len < 0) {
202                 return len;
203         } else if (len > 0) {
204                 buf[len++] = '\n';
205                 size -= len;
206         }
207         if (!adev->data.of_compatible)
208                 return len;
209
210         count = create_of_modalias(adev, buf + len, size - 1);
211         if (count < 0) {
212                 return count;
213         } else if (count > 0) {
214                 len += count;
215                 buf[len++] = '\n';
216         }
217
218         return len;
219 }
220
221 /**
222  * acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.
223  *
224  * Create the modalias sysfs attribute for ACPI-enumerated devices.
225  *
226  * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
227  * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
228  */
229 int acpi_device_modalias(struct device *dev, char *buf, int size)
230 {
231         return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
232 }
233 EXPORT_SYMBOL_GPL(acpi_device_modalias);
234
235 static ssize_t
236 acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
237         return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
238 }
239 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
240
241 static ssize_t real_power_state_show(struct device *dev,
242                                      struct device_attribute *attr, char *buf)
243 {
244         struct acpi_device *adev = to_acpi_device(dev);
245         int state;
246         int ret;
247
248         ret = acpi_device_get_power(adev, &state);
249         if (ret)
250                 return ret;
251
252         return sprintf(buf, "%s\n", acpi_power_state_string(state));
253 }
254
255 static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);
256
257 static ssize_t power_state_show(struct device *dev,
258                                 struct device_attribute *attr, char *buf)
259 {
260         struct acpi_device *adev = to_acpi_device(dev);
261
262         return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
263 }
264
265 static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);
266
267 static ssize_t
268 acpi_eject_store(struct device *d, struct device_attribute *attr,
269                 const char *buf, size_t count)
270 {
271         struct acpi_device *acpi_device = to_acpi_device(d);
272         acpi_object_type not_used;
273         acpi_status status;
274
275         if (!count || buf[0] != '1')
276                 return -EINVAL;
277
278         if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
279             && !acpi_device->driver)
280                 return -ENODEV;
281
282         status = acpi_get_type(acpi_device->handle, &not_used);
283         if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
284                 return -ENODEV;
285
286         get_device(&acpi_device->dev);
287         status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
288         if (ACPI_SUCCESS(status))
289                 return count;
290
291         put_device(&acpi_device->dev);
292         acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
293                           ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
294         return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
295 }
296
297 static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
298
299 static ssize_t
300 acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
301         struct acpi_device *acpi_dev = to_acpi_device(dev);
302
303         return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
304 }
305 static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
306
307 static ssize_t acpi_device_uid_show(struct device *dev,
308                                     struct device_attribute *attr, char *buf)
309 {
310         struct acpi_device *acpi_dev = to_acpi_device(dev);
311
312         return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
313 }
314 static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
315
316 static ssize_t acpi_device_adr_show(struct device *dev,
317                                     struct device_attribute *attr, char *buf)
318 {
319         struct acpi_device *acpi_dev = to_acpi_device(dev);
320
321         return sprintf(buf, "0x%08x\n",
322                        (unsigned int)(acpi_dev->pnp.bus_address));
323 }
324 static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
325
326 static ssize_t
327 acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
328         struct acpi_device *acpi_dev = to_acpi_device(dev);
329         struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
330         int result;
331
332         result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
333         if (result)
334                 goto end;
335
336         result = sprintf(buf, "%s\n", (char*)path.pointer);
337         kfree(path.pointer);
338 end:
339         return result;
340 }
341 static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
342
343 /* sysfs file that shows description text from the ACPI _STR method */
344 static ssize_t description_show(struct device *dev,
345                                 struct device_attribute *attr,
346                                 char *buf) {
347         struct acpi_device *acpi_dev = to_acpi_device(dev);
348         int result;
349
350         if (acpi_dev->pnp.str_obj == NULL)
351                 return 0;
352
353         /*
354          * The _STR object contains a Unicode identifier for a device.
355          * We need to convert to utf-8 so it can be displayed.
356          */
357         result = utf16s_to_utf8s(
358                 (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
359                 acpi_dev->pnp.str_obj->buffer.length,
360                 UTF16_LITTLE_ENDIAN, buf,
361                 PAGE_SIZE);
362
363         buf[result++] = '\n';
364
365         return result;
366 }
367 static DEVICE_ATTR(description, 0444, description_show, NULL);
368
369 static ssize_t
370 acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
371                      char *buf) {
372         struct acpi_device *acpi_dev = to_acpi_device(dev);
373         acpi_status status;
374         unsigned long long sun;
375
376         status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
377         if (ACPI_FAILURE(status))
378                 return -ENODEV;
379
380         return sprintf(buf, "%llu\n", sun);
381 }
382 static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
383
384 static ssize_t status_show(struct device *dev, struct device_attribute *attr,
385                                 char *buf) {
386         struct acpi_device *acpi_dev = to_acpi_device(dev);
387         acpi_status status;
388         unsigned long long sta;
389
390         status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
391         if (ACPI_FAILURE(status))
392                 return -ENODEV;
393
394         return sprintf(buf, "%llu\n", sta);
395 }
396 static DEVICE_ATTR_RO(status);
397
398 /**
399  * acpi_device_setup_files - Create sysfs attributes of an ACPI device.
400  * @dev: ACPI device object.
401  */
402 int acpi_device_setup_files(struct acpi_device *dev)
403 {
404         struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
405         acpi_status status;
406         int result = 0;
407
408         /*
409          * Devices gotten from FADT don't have a "path" attribute
410          */
411         if (dev->handle) {
412                 result = device_create_file(&dev->dev, &dev_attr_path);
413                 if (result)
414                         goto end;
415         }
416
417         if (!list_empty(&dev->pnp.ids)) {
418                 result = device_create_file(&dev->dev, &dev_attr_hid);
419                 if (result)
420                         goto end;
421
422                 result = device_create_file(&dev->dev, &dev_attr_modalias);
423                 if (result)
424                         goto end;
425         }
426
427         /*
428          * If device has _STR, 'description' file is created
429          */
430         if (acpi_has_method(dev->handle, "_STR")) {
431                 status = acpi_evaluate_object(dev->handle, "_STR",
432                                         NULL, &buffer);
433                 if (ACPI_FAILURE(status))
434                         buffer.pointer = NULL;
435                 dev->pnp.str_obj = buffer.pointer;
436                 result = device_create_file(&dev->dev, &dev_attr_description);
437                 if (result)
438                         goto end;
439         }
440
441         if (dev->pnp.type.bus_address)
442                 result = device_create_file(&dev->dev, &dev_attr_adr);
443         if (dev->pnp.unique_id)
444                 result = device_create_file(&dev->dev, &dev_attr_uid);
445
446         if (acpi_has_method(dev->handle, "_SUN")) {
447                 result = device_create_file(&dev->dev, &dev_attr_sun);
448                 if (result)
449                         goto end;
450         }
451
452         if (acpi_has_method(dev->handle, "_STA")) {
453                 result = device_create_file(&dev->dev, &dev_attr_status);
454                 if (result)
455                         goto end;
456         }
457
458         /*
459          * If device has _EJ0, 'eject' file is created that is used to trigger
460          * hot-removal function from userland.
461          */
462         if (acpi_has_method(dev->handle, "_EJ0")) {
463                 result = device_create_file(&dev->dev, &dev_attr_eject);
464                 if (result)
465                         return result;
466         }
467
468         if (dev->flags.power_manageable) {
469                 result = device_create_file(&dev->dev, &dev_attr_power_state);
470                 if (result)
471                         return result;
472
473                 if (dev->power.flags.power_resources)
474                         result = device_create_file(&dev->dev,
475                                                     &dev_attr_real_power_state);
476         }
477
478 end:
479         return result;
480 }
481
482 /**
483  * acpi_device_remove_files - Remove sysfs attributes of an ACPI device.
484  * @dev: ACPI device object.
485  */
486 void acpi_device_remove_files(struct acpi_device *dev)
487 {
488         if (dev->flags.power_manageable) {
489                 device_remove_file(&dev->dev, &dev_attr_power_state);
490                 if (dev->power.flags.power_resources)
491                         device_remove_file(&dev->dev,
492                                            &dev_attr_real_power_state);
493         }
494
495         /*
496          * If device has _STR, remove 'description' file
497          */
498         if (acpi_has_method(dev->handle, "_STR")) {
499                 kfree(dev->pnp.str_obj);
500                 device_remove_file(&dev->dev, &dev_attr_description);
501         }
502         /*
503          * If device has _EJ0, remove 'eject' file.
504          */
505         if (acpi_has_method(dev->handle, "_EJ0"))
506                 device_remove_file(&dev->dev, &dev_attr_eject);
507
508         if (acpi_has_method(dev->handle, "_SUN"))
509                 device_remove_file(&dev->dev, &dev_attr_sun);
510
511         if (dev->pnp.unique_id)
512                 device_remove_file(&dev->dev, &dev_attr_uid);
513         if (dev->pnp.type.bus_address)
514                 device_remove_file(&dev->dev, &dev_attr_adr);
515         device_remove_file(&dev->dev, &dev_attr_modalias);
516         device_remove_file(&dev->dev, &dev_attr_hid);
517         if (acpi_has_method(dev->handle, "_STA"))
518                 device_remove_file(&dev->dev, &dev_attr_status);
519         if (dev->handle)
520                 device_remove_file(&dev->dev, &dev_attr_path);
521 }