diff options
-rw-r--r-- | Documentation/leds/leds-class.rst | 70 | ||||
-rw-r--r-- | drivers/leds/led-class.c | 20 | ||||
-rw-r--r-- | drivers/leds/led-core.c | 127 | ||||
-rw-r--r-- | drivers/leds/leds.h | 1 | ||||
-rw-r--r-- | include/linux/leds.h | 45 | ||||
-rwxr-xr-x | tools/leds/get_led_device_info.sh | 201 |
6 files changed, 458 insertions, 6 deletions
diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-class.rst index df0120a1ee3c..a0708d3f3d0b 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst | |||
@@ -43,9 +43,73 @@ LED Device Naming | |||
43 | 43 | ||
44 | Is currently of the form: | 44 | Is currently of the form: |
45 | 45 | ||
46 | "devicename:colour:function" | 46 | "devicename:color:function" |
47 | 47 | ||
48 | There have been calls for LED properties such as colour to be exported as | 48 | - devicename: |
49 | it should refer to a unique identifier created by the kernel, | ||
50 | like e.g. phyN for network devices or inputN for input devices, rather | ||
51 | than to the hardware; the information related to the product and the bus | ||
52 | to which given device is hooked is available in sysfs and can be | ||
53 | retrieved using get_led_device_info.sh script from tools/leds; generally | ||
54 | this section is expected mostly for LEDs that are somehow associated with | ||
55 | other devices. | ||
56 | |||
57 | - color: | ||
58 | one of LED_COLOR_ID_* definitions from the header | ||
59 | include/dt-bindings/leds/common.h. | ||
60 | |||
61 | - function: | ||
62 | one of LED_FUNCTION_* definitions from the header | ||
63 | include/dt-bindings/leds/common.h. | ||
64 | |||
65 | If required color or function is missing, please submit a patch | ||
66 | to linux-leds@vger.kernel.org. | ||
67 | |||
68 | It is possible that more than one LED with the same color and function will | ||
69 | be required for given platform, differing only with an ordinal number. | ||
70 | In this case it is preferable to just concatenate the predefined LED_FUNCTION_* | ||
71 | name with required "-N" suffix in the driver. fwnode based drivers can use | ||
72 | function-enumerator property for that and then the concatenation will be handled | ||
73 | automatically by the LED core upon LED class device registration. | ||
74 | |||
75 | LED subsystem has also a protection against name clash, that may occur | ||
76 | when LED class device is created by a driver of hot-pluggable device and | ||
77 | it doesn't provide unique devicename section. In this case numerical | ||
78 | suffix (e.g. "_1", "_2", "_3" etc.) is added to the requested LED class | ||
79 | device name. | ||
80 | |||
81 | There might be still LED class drivers around using vendor or product name | ||
82 | for devicename, but this approach is now deprecated as it doesn't convey | ||
83 | any added value. Product information can be found in other places in sysfs | ||
84 | (see tools/leds/get_led_device_info.sh). | ||
85 | |||
86 | Examples of proper LED names: | ||
87 | |||
88 | - "red:disk" | ||
89 | - "white:flash" | ||
90 | - "red:indicator" | ||
91 | - "phy1:green:wlan" | ||
92 | - "phy3::wlan" | ||
93 | - ":kbd_backlight" | ||
94 | - "input5::kbd_backlight" | ||
95 | - "input3::numlock" | ||
96 | - "input3::scrolllock" | ||
97 | - "input3::capslock" | ||
98 | - "mmc1::status" | ||
99 | - "white:status" | ||
100 | |||
101 | get_led_device_info.sh script can be used for verifying if the LED name | ||
102 | meets the requirements pointed out here. It performs validation of the LED class | ||
103 | devicename sections and gives hints on expected value for a section in case | ||
104 | the validation fails for it. So far the script supports validation | ||
105 | of associations between LEDs and following types of devices: | ||
106 | |||
107 | - input devices | ||
108 | - ieee80211 compliant USB devices | ||
109 | |||
110 | The script is open to extensions. | ||
111 | |||
112 | There have been calls for LED properties such as color to be exported as | ||
49 | individual led class attributes. As a solution which doesn't incur as much | 113 | individual led class attributes. As a solution which doesn't incur as much |
50 | overhead, I suggest these become part of the device name. The naming scheme | 114 | overhead, I suggest these become part of the device name. The naming scheme |
51 | above leaves scope for further attributes should they be needed. If sections | 115 | above leaves scope for further attributes should they be needed. If sections |
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 242122f49333..508d6477d0b8 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c | |||
@@ -254,17 +254,31 @@ int led_classdev_register_ext(struct device *parent, | |||
254 | struct led_classdev *led_cdev, | 254 | struct led_classdev *led_cdev, |
255 | struct led_init_data *init_data) | 255 | struct led_init_data *init_data) |
256 | { | 256 | { |
257 | char name[LED_MAX_NAME_SIZE]; | 257 | char composed_name[LED_MAX_NAME_SIZE]; |
258 | char final_name[LED_MAX_NAME_SIZE]; | ||
259 | const char *proposed_name = composed_name; | ||
258 | int ret; | 260 | int ret; |
259 | 261 | ||
260 | ret = led_classdev_next_name(led_cdev->name, name, sizeof(name)); | 262 | if (init_data) { |
263 | if (init_data->devname_mandatory && !init_data->devicename) { | ||
264 | dev_err(parent, "Mandatory device name is missing"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | ret = led_compose_name(parent, init_data, composed_name); | ||
268 | if (ret < 0) | ||
269 | return ret; | ||
270 | } else { | ||
271 | proposed_name = led_cdev->name; | ||
272 | } | ||
273 | |||
274 | ret = led_classdev_next_name(proposed_name, final_name, sizeof(final_name)); | ||
261 | if (ret < 0) | 275 | if (ret < 0) |
262 | return ret; | 276 | return ret; |
263 | 277 | ||
264 | mutex_init(&led_cdev->led_access); | 278 | mutex_init(&led_cdev->led_access); |
265 | mutex_lock(&led_cdev->led_access); | 279 | mutex_lock(&led_cdev->led_access); |
266 | led_cdev->dev = device_create_with_groups(leds_class, parent, 0, | 280 | led_cdev->dev = device_create_with_groups(leds_class, parent, 0, |
267 | led_cdev, led_cdev->groups, "%s", name); | 281 | led_cdev, led_cdev->groups, "%s", final_name); |
268 | if (IS_ERR(led_cdev->dev)) { | 282 | if (IS_ERR(led_cdev->dev)) { |
269 | mutex_unlock(&led_cdev->led_access); | 283 | mutex_unlock(&led_cdev->led_access); |
270 | return PTR_ERR(led_cdev->dev); | 284 | return PTR_ERR(led_cdev->dev); |
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 7107cd7e87cf..f0c1c403f678 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c | |||
@@ -13,8 +13,10 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/mutex.h> | 14 | #include <linux/mutex.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/property.h> | ||
16 | #include <linux/rwsem.h> | 17 | #include <linux/rwsem.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <uapi/linux/uleds.h> | ||
18 | #include "leds.h" | 20 | #include "leds.h" |
19 | 21 | ||
20 | DECLARE_RWSEM(leds_list_lock); | 22 | DECLARE_RWSEM(leds_list_lock); |
@@ -23,6 +25,18 @@ EXPORT_SYMBOL_GPL(leds_list_lock); | |||
23 | LIST_HEAD(leds_list); | 25 | LIST_HEAD(leds_list); |
24 | EXPORT_SYMBOL_GPL(leds_list); | 26 | EXPORT_SYMBOL_GPL(leds_list); |
25 | 27 | ||
28 | const char * const led_colors[LED_COLOR_ID_MAX] = { | ||
29 | [LED_COLOR_ID_WHITE] = "white", | ||
30 | [LED_COLOR_ID_RED] = "red", | ||
31 | [LED_COLOR_ID_GREEN] = "green", | ||
32 | [LED_COLOR_ID_BLUE] = "blue", | ||
33 | [LED_COLOR_ID_AMBER] = "amber", | ||
34 | [LED_COLOR_ID_VIOLET] = "violet", | ||
35 | [LED_COLOR_ID_YELLOW] = "yellow", | ||
36 | [LED_COLOR_ID_IR] = "ir", | ||
37 | }; | ||
38 | EXPORT_SYMBOL_GPL(led_colors); | ||
39 | |||
26 | static int __led_set_brightness(struct led_classdev *led_cdev, | 40 | static int __led_set_brightness(struct led_classdev *led_cdev, |
27 | enum led_brightness value) | 41 | enum led_brightness value) |
28 | { | 42 | { |
@@ -353,3 +367,116 @@ void led_sysfs_enable(struct led_classdev *led_cdev) | |||
353 | led_cdev->flags &= ~LED_SYSFS_DISABLE; | 367 | led_cdev->flags &= ~LED_SYSFS_DISABLE; |
354 | } | 368 | } |
355 | EXPORT_SYMBOL_GPL(led_sysfs_enable); | 369 | EXPORT_SYMBOL_GPL(led_sysfs_enable); |
370 | |||
371 | static void led_parse_fwnode_props(struct device *dev, | ||
372 | struct fwnode_handle *fwnode, | ||
373 | struct led_properties *props) | ||
374 | { | ||
375 | int ret; | ||
376 | |||
377 | if (!fwnode) | ||
378 | return; | ||
379 | |||
380 | if (fwnode_property_present(fwnode, "label")) { | ||
381 | ret = fwnode_property_read_string(fwnode, "label", &props->label); | ||
382 | if (ret) | ||
383 | dev_err(dev, "Error parsing 'label' property (%d)\n", ret); | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | if (fwnode_property_present(fwnode, "color")) { | ||
388 | ret = fwnode_property_read_u32(fwnode, "color", &props->color); | ||
389 | if (ret) | ||
390 | dev_err(dev, "Error parsing 'color' property (%d)\n", ret); | ||
391 | else if (props->color >= LED_COLOR_ID_MAX) | ||
392 | dev_err(dev, "LED color identifier out of range\n"); | ||
393 | else | ||
394 | props->color_present = true; | ||
395 | } | ||
396 | |||
397 | |||
398 | if (!fwnode_property_present(fwnode, "function")) | ||
399 | return; | ||
400 | |||
401 | ret = fwnode_property_read_string(fwnode, "function", &props->function); | ||
402 | if (ret) { | ||
403 | dev_err(dev, | ||
404 | "Error parsing 'function' property (%d)\n", | ||
405 | ret); | ||
406 | } | ||
407 | |||
408 | if (!fwnode_property_present(fwnode, "function-enumerator")) | ||
409 | return; | ||
410 | |||
411 | ret = fwnode_property_read_u32(fwnode, "function-enumerator", | ||
412 | &props->func_enum); | ||
413 | if (ret) { | ||
414 | dev_err(dev, | ||
415 | "Error parsing 'function-enumerator' property (%d)\n", | ||
416 | ret); | ||
417 | } else { | ||
418 | props->func_enum_present = true; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | int led_compose_name(struct device *dev, struct led_init_data *init_data, | ||
423 | char *led_classdev_name) | ||
424 | { | ||
425 | struct led_properties props = {}; | ||
426 | struct fwnode_handle *fwnode = init_data->fwnode; | ||
427 | const char *devicename = init_data->devicename; | ||
428 | |||
429 | if (!led_classdev_name) | ||
430 | return -EINVAL; | ||
431 | |||
432 | led_parse_fwnode_props(dev, fwnode, &props); | ||
433 | |||
434 | if (props.label) { | ||
435 | /* | ||
436 | * If init_data.devicename is NULL, then it indicates that | ||
437 | * DT label should be used as-is for LED class device name. | ||
438 | * Otherwise the label is prepended with devicename to compose | ||
439 | * the final LED class device name. | ||
440 | */ | ||
441 | if (!devicename) { | ||
442 | strscpy(led_classdev_name, props.label, | ||
443 | LED_MAX_NAME_SIZE); | ||
444 | } else { | ||
445 | snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", | ||
446 | devicename, props.label); | ||
447 | } | ||
448 | } else if (props.function || props.color_present) { | ||
449 | char tmp_buf[LED_MAX_NAME_SIZE]; | ||
450 | |||
451 | if (props.func_enum_present) { | ||
452 | snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d", | ||
453 | props.color_present ? led_colors[props.color] : "", | ||
454 | props.function ?: "", props.func_enum); | ||
455 | } else { | ||
456 | snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s", | ||
457 | props.color_present ? led_colors[props.color] : "", | ||
458 | props.function ?: ""); | ||
459 | } | ||
460 | if (init_data->devname_mandatory) { | ||
461 | snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", | ||
462 | devicename, tmp_buf); | ||
463 | } else { | ||
464 | strscpy(led_classdev_name, tmp_buf, LED_MAX_NAME_SIZE); | ||
465 | |||
466 | } | ||
467 | } else if (init_data->default_label) { | ||
468 | if (!devicename) { | ||
469 | dev_err(dev, "Legacy LED naming requires devicename segment"); | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", | ||
473 | devicename, init_data->default_label); | ||
474 | } else if (is_of_node(fwnode)) { | ||
475 | strscpy(led_classdev_name, to_of_node(fwnode)->name, | ||
476 | LED_MAX_NAME_SIZE); | ||
477 | } else | ||
478 | return -EINVAL; | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | EXPORT_SYMBOL_GPL(led_compose_name); | ||
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 47b229469069..0b577cece8f7 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h | |||
@@ -27,5 +27,6 @@ void led_set_brightness_nosleep(struct led_classdev *led_cdev, | |||
27 | extern struct rw_semaphore leds_list_lock; | 27 | extern struct rw_semaphore leds_list_lock; |
28 | extern struct list_head leds_list; | 28 | extern struct list_head leds_list; |
29 | extern struct list_head trigger_list; | 29 | extern struct list_head trigger_list; |
30 | extern const char * const led_colors[LED_COLOR_ID_MAX]; | ||
30 | 31 | ||
31 | #endif /* __LEDS_H_INCLUDED */ | 32 | #endif /* __LEDS_H_INCLUDED */ |
diff --git a/include/linux/leds.h b/include/linux/leds.h index 2bbe8a38fe39..d101fd13e18e 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #ifndef __LINUX_LEDS_H_INCLUDED | 8 | #ifndef __LINUX_LEDS_H_INCLUDED |
9 | #define __LINUX_LEDS_H_INCLUDED | 9 | #define __LINUX_LEDS_H_INCLUDED |
10 | 10 | ||
11 | #include <dt-bindings/leds/common.h> | ||
11 | #include <linux/device.h> | 12 | #include <linux/device.h> |
12 | #include <linux/kernfs.h> | 13 | #include <linux/kernfs.h> |
13 | #include <linux/list.h> | 14 | #include <linux/list.h> |
@@ -33,6 +34,25 @@ enum led_brightness { | |||
33 | struct led_init_data { | 34 | struct led_init_data { |
34 | /* device fwnode handle */ | 35 | /* device fwnode handle */ |
35 | struct fwnode_handle *fwnode; | 36 | struct fwnode_handle *fwnode; |
37 | /* | ||
38 | * default <color:function> tuple, for backward compatibility | ||
39 | * with in-driver hard-coded LED names used as a fallback when | ||
40 | * DT "label" property is absent; it should be set to NULL | ||
41 | * in new LED class drivers. | ||
42 | */ | ||
43 | const char *default_label; | ||
44 | /* | ||
45 | * string to be used for devicename section of LED class device | ||
46 | * either for label based LED name composition path or for fwnode | ||
47 | * based when devname_mandatory is true | ||
48 | */ | ||
49 | const char *devicename; | ||
50 | /* | ||
51 | * indicates if LED name should always comprise devicename section; | ||
52 | * only LEDs exposed by drivers of hot-pluggable devices should | ||
53 | * set it to true | ||
54 | */ | ||
55 | bool devname_mandatory; | ||
36 | }; | 56 | }; |
37 | 57 | ||
38 | struct led_classdev { | 58 | struct led_classdev { |
@@ -258,6 +278,22 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev); | |||
258 | extern void led_sysfs_enable(struct led_classdev *led_cdev); | 278 | extern void led_sysfs_enable(struct led_classdev *led_cdev); |
259 | 279 | ||
260 | /** | 280 | /** |
281 | * led_compose_name - compose LED class device name | ||
282 | * @dev: LED controller device object | ||
283 | * @child: child fwnode_handle describing a LED or a group of synchronized LEDs; | ||
284 | * it must be provided only for fwnode based LEDs | ||
285 | * @led_classdev_name: composed LED class device name | ||
286 | * | ||
287 | * Create LED class device name basing on the provided init_data argument. | ||
288 | * The name can have <devicename:color:function> or <color:function>. | ||
289 | * form, depending on the init_data configuration. | ||
290 | * | ||
291 | * Returns: 0 on success or negative error value on failure | ||
292 | */ | ||
293 | extern int led_compose_name(struct device *dev, struct led_init_data *init_data, | ||
294 | char *led_classdev_name); | ||
295 | |||
296 | /** | ||
261 | * led_sysfs_is_disabled - check if LED sysfs interface is disabled | 297 | * led_sysfs_is_disabled - check if LED sysfs interface is disabled |
262 | * @led_cdev: the LED to query | 298 | * @led_cdev: the LED to query |
263 | * | 299 | * |
@@ -434,6 +470,15 @@ struct led_platform_data { | |||
434 | struct led_info *leds; | 470 | struct led_info *leds; |
435 | }; | 471 | }; |
436 | 472 | ||
473 | struct led_properties { | ||
474 | u32 color; | ||
475 | bool color_present; | ||
476 | const char *function; | ||
477 | u32 func_enum; | ||
478 | bool func_enum_present; | ||
479 | const char *label; | ||
480 | }; | ||
481 | |||
437 | struct gpio_desc; | 482 | struct gpio_desc; |
438 | typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state, | 483 | typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state, |
439 | unsigned long *delay_on, | 484 | unsigned long *delay_on, |
diff --git a/tools/leds/get_led_device_info.sh b/tools/leds/get_led_device_info.sh new file mode 100755 index 000000000000..ccfa442db5fe --- /dev/null +++ b/tools/leds/get_led_device_info.sh | |||
@@ -0,0 +1,201 @@ | |||
1 | #!/bin/sh | ||
2 | # SPDX-License-Identifier: GPL-2.0 | ||
3 | |||
4 | led_common_defs_path="include/dt-bindings/leds/common.h" | ||
5 | |||
6 | num_args=$# | ||
7 | if [ $num_args -eq 1 ]; then | ||
8 | linux_top=$(dirname `realpath $0` | awk -F/ \ | ||
9 | '{ \ | ||
10 | i=1; \ | ||
11 | while (i <= NF - 2) { \ | ||
12 | printf $i"/"; \ | ||
13 | i++; \ | ||
14 | }; \ | ||
15 | }') | ||
16 | led_defs_path=$linux_top/$led_common_defs_path | ||
17 | elif [ $num_args -eq 2 ]; then | ||
18 | led_defs_path=`realpath $2` | ||
19 | else | ||
20 | echo "Usage: get_led_device_info.sh LED_CDEV_PATH [LED_COMMON_DEFS_PATH]" | ||
21 | exit 1 | ||
22 | fi | ||
23 | |||
24 | if [ ! -f $led_defs_path ]; then | ||
25 | echo "$led_defs_path doesn't exist" | ||
26 | exit 1 | ||
27 | fi | ||
28 | |||
29 | led_cdev_path=`echo $1 | sed s'/\/$//'` | ||
30 | |||
31 | ls "$led_cdev_path/brightness" > /dev/null 2>&1 | ||
32 | if [ $? -ne 0 ]; then | ||
33 | echo "Device \"$led_cdev_path\" does not exist." | ||
34 | exit 1 | ||
35 | fi | ||
36 | |||
37 | bus=`readlink $led_cdev_path/device/subsystem | sed s'/.*\///'` | ||
38 | usb_subdev=`readlink $led_cdev_path | grep usb | sed s'/\(.*usb[0-9]*\/[0-9]*-[0-9]*\)\/.*/\1/'` | ||
39 | ls "$led_cdev_path/device/of_node/compatible" > /dev/null 2>&1 | ||
40 | of_node_missing=$? | ||
41 | |||
42 | if [ "$bus" = "input" ]; then | ||
43 | input_node=`readlink $led_cdev_path/device | sed s'/.*\///'` | ||
44 | if [ ! -z "$usb_subdev" ]; then | ||
45 | bus="usb" | ||
46 | fi | ||
47 | fi | ||
48 | |||
49 | if [ "$bus" = "usb" ]; then | ||
50 | usb_interface=`readlink $led_cdev_path | sed s'/.*\(usb[0-9]*\)/\1/' | cut -d\/ -f3` | ||
51 | cd $led_cdev_path/../$usb_subdev | ||
52 | driver=`readlink $usb_interface/driver | sed s'/.*\///'` | ||
53 | if [ -d "$usb_interface/ieee80211" ]; then | ||
54 | wifi_phy=`ls -l $usb_interface/ieee80211 | grep phy | awk '{print $9}'` | ||
55 | fi | ||
56 | idVendor=`cat idVendor` | ||
57 | idProduct=`cat idProduct` | ||
58 | manufacturer=`cat manufacturer` | ||
59 | product=`cat product` | ||
60 | elif [ "$bus" = "input" ]; then | ||
61 | cd $led_cdev_path | ||
62 | product=`cat device/name` | ||
63 | driver=`cat device/device/driver/description` | ||
64 | elif [ $of_node_missing -eq 0 ]; then | ||
65 | cd $led_cdev_path | ||
66 | compatible=`cat device/of_node/compatible` | ||
67 | if [ "$compatible" = "gpio-leds" ]; then | ||
68 | driver="leds-gpio" | ||
69 | elif [ "$compatible" = "pwm-leds" ]; then | ||
70 | driver="leds-pwm" | ||
71 | else | ||
72 | manufacturer=`echo $compatible | awk -F, '{print $1}'` | ||
73 | product=`echo $compatible | awk -F, '{print $2}'` | ||
74 | fi | ||
75 | else | ||
76 | echo "Unknown device type." | ||
77 | exit 1 | ||
78 | fi | ||
79 | |||
80 | printf "\n#####################################\n" | ||
81 | printf "# LED class device hardware details #\n" | ||
82 | printf "#####################################\n\n" | ||
83 | |||
84 | printf "bus:\t\t\t$bus\n" | ||
85 | |||
86 | if [ ! -z "$idVendor" ]; then | ||
87 | printf "idVendor:\t\t$idVendor\n" | ||
88 | fi | ||
89 | |||
90 | if [ ! -z "$idProduct" ]; then | ||
91 | printf "idProduct:\t\t$idProduct\n" | ||
92 | fi | ||
93 | |||
94 | if [ ! -z "$manufacturer" ]; then | ||
95 | printf "manufacturer:\t\t$manufacturer\n" | ||
96 | fi | ||
97 | |||
98 | if [ ! -z "$product" ]; then | ||
99 | printf "product:\t\t$product\n" | ||
100 | fi | ||
101 | |||
102 | if [ ! -z "$driver" ]; then | ||
103 | printf "driver:\t\t\t$driver\n" | ||
104 | fi | ||
105 | |||
106 | if [ ! -z "$input_node" ]; then | ||
107 | printf "associated input node:\t$input_node\n" | ||
108 | fi | ||
109 | |||
110 | printf "\n####################################\n" | ||
111 | printf "# LED class device name validation #\n" | ||
112 | printf "####################################\n\n" | ||
113 | |||
114 | led_name=`echo $led_cdev_path | sed s'/.*\///'` | ||
115 | |||
116 | num_sections=`echo $led_name | awk -F: '{print NF}'` | ||
117 | |||
118 | if [ $num_sections -eq 1 ]; then | ||
119 | printf "\":\" delimiter not detected.\t[ FAILED ]\n" | ||
120 | exit 1 | ||
121 | elif [ $num_sections -eq 2 ]; then | ||
122 | color=`echo $led_name | cut -d: -f1` | ||
123 | function=`echo $led_name | cut -d: -f2` | ||
124 | elif [ $num_sections -eq 3 ]; then | ||
125 | devicename=`echo $led_name | cut -d: -f1` | ||
126 | color=`echo $led_name | cut -d: -f2` | ||
127 | function=`echo $led_name | cut -d: -f3` | ||
128 | else | ||
129 | printf "Detected %d sections in the LED class device name - should the script be updated?\n" $num_sections | ||
130 | exit 1 | ||
131 | fi | ||
132 | |||
133 | S_DEV="devicename" | ||
134 | S_CLR="color " | ||
135 | S_FUN="function " | ||
136 | status_tab=20 | ||
137 | |||
138 | print_msg_ok() | ||
139 | { | ||
140 | local section_name="$1" | ||
141 | local section_val="$2" | ||
142 | local msg="$3" | ||
143 | printf "$section_name :\t%-${status_tab}.${status_tab}s %s %s\n" "$section_val" "[ OK ] " "$msg" | ||
144 | } | ||
145 | |||
146 | print_msg_failed() | ||
147 | { | ||
148 | local section_name="$1" | ||
149 | local section_val="$2" | ||
150 | local msg="$3" | ||
151 | printf "$section_name :\t%-${status_tab}.${status_tab}s %s %s\n" "$section_val" "[ FAILED ]" "$msg" | ||
152 | } | ||
153 | |||
154 | if [ ! -z "$input_node" ]; then | ||
155 | expected_devname=$input_node | ||
156 | elif [ ! -z "$wifi_phy" ]; then | ||
157 | expected_devname=$wifi_phy | ||
158 | fi | ||
159 | |||
160 | if [ ! -z "$devicename" ]; then | ||
161 | if [ ! -z "$expected_devname" ]; then | ||
162 | if [ "$devicename" = "$expected_devname" ]; then | ||
163 | print_msg_ok "$S_DEV" "$devicename" | ||
164 | else | ||
165 | print_msg_failed "$S_DEV" "$devicename" "Expected: $expected_devname" | ||
166 | fi | ||
167 | else | ||
168 | if [ "$devicename" = "$manufacturer" ]; then | ||
169 | print_msg_failed "$S_DEV" "$devicename" "Redundant: use of vendor name is discouraged" | ||
170 | elif [ "$devicename" = "$product" ]; then | ||
171 | print_msg_failed "$S_DEV" "$devicename" "Redundant: use of product name is discouraged" | ||
172 | else | ||
173 | print_msg_failed "$S_DEV" "$devicename" "Unknown devicename - should the script be updated?" | ||
174 | fi | ||
175 | fi | ||
176 | elif [ ! -z "$expected_devname" ]; then | ||
177 | print_msg_failed "$S_DEV" "blank" "Expected: $expected_devname" | ||
178 | fi | ||
179 | |||
180 | if [ ! -z "$color" ]; then | ||
181 | color_upper=`echo $color | tr [:lower:] [:upper:]` | ||
182 | color_id_definition=$(cat $led_defs_path | grep "_$color_upper\s" | awk '{print $2}') | ||
183 | if [ ! -z "$color_id_definition" ]; then | ||
184 | print_msg_ok "$S_CLR" "$color" "Matching definition: $color_id_definition" | ||
185 | else | ||
186 | print_msg_failed "$S_CLR" "$color" "Definition not found in $led_defs_path" | ||
187 | fi | ||
188 | |||
189 | fi | ||
190 | |||
191 | if [ ! -z "$function" ]; then | ||
192 | # strip optional enumerator | ||
193 | function=`echo $function | sed s'/\(.*\)-[0-9]*$/\1/'` | ||
194 | fun_definition=$(cat $led_defs_path | grep "\"$function\"" | awk '{print $2}') | ||
195 | if [ ! -z "$fun_definition" ]; then | ||
196 | print_msg_ok "$S_FUN" "$function" "Matching definition: $fun_definition" | ||
197 | else | ||
198 | print_msg_failed "$S_FUN" "$function" "Definition not found in $led_defs_path" | ||
199 | fi | ||
200 | |||
201 | fi | ||