1#!/usr/bin/env python3
2import argparse
3import os
4
5import yaml
6from inflection import underscore
7
8
9def config_error(ofile, led_name, group_name, message):
10    ofile.close()
11    os.remove(ofile.name)
12    raise ValueError(
13        "Invalid Configuration for LED ["
14        + led_name
15        + "] in Group ["
16        + group_name
17        + "]: "
18        + message
19    )
20
21
22def check_led_priority(led_name, group, value, priority_dict):
23
24    if led_name in priority_dict:
25        if value != priority_dict[led_name]:
26            # Priority for a particular LED needs to stay SAME
27            # across all groups
28            config_error(
29                ofile,
30                led_name,
31                group,
32                "Priority is NOT same across all groups",
33            )
34    else:
35        priority_dict[led_name] = value
36
37    return 0
38
39
40def led_action_literal(action):
41    if action == "":
42        return "std::nullopt"
43
44    return "phosphor::led::Layout::Action::" + str(action)
45
46
47def generate_file_single_led(
48    ifile, led_name, list_dict, priority_dict, ofile, has_group_priority, group
49):
50
51    has_led_priority = "Priority" in list_dict
52
53    if has_group_priority and has_led_priority:
54        config_error(
55            ofile,
56            led_name,
57            group,
58            "cannot mix group priority with led priority",
59        )
60
61    if (not has_group_priority) and (not has_led_priority):
62        config_error(
63            ofile, led_name, group, "no group priority or led priority defined"
64        )
65
66    led_priority = list_dict.get("Priority", "")
67
68    if has_led_priority:
69        check_led_priority(led_name, group, led_priority, priority_dict)
70
71    action = led_action_literal(list_dict.get("Action", "Off"))
72    dutyOn = str(list_dict.get("DutyOn", 50))
73    period = str(list_dict.get("Period", 0))
74    priority = led_action_literal(led_priority)
75
76    ofile.write('        {"' + underscore(led_name) + '",')
77    ofile.write(action + ",")
78    ofile.write(dutyOn + ",")
79    ofile.write(period + ",")
80    ofile.write(priority + ",")
81
82    ofile.write("},\n")
83
84    return 0
85
86
87def generate_file_single_group(ifile, group, priority_dict, ofile):
88    # This section generates an std::unordered_map of LedGroupNames to
89    # std::set of LEDs containing the name and properties
90    led_dict = ifile[group]
91
92    group_priority = 0
93    has_group_priority = "Priority" in led_dict
94
95    if has_group_priority:
96        group_priority = led_dict["Priority"]
97        # we do not want to enumerate this as a led group
98        del led_dict["Priority"]
99
100    ofile.write(
101        '   {"'
102        + "/xyz/openbmc_project/led/groups/"
103        + underscore(group)
104        + '"'
105        + ",{ "
106        + str(group_priority)
107        + ",\n"
108        + "{\n"
109    )
110
111    for led_name, list_dict in list(led_dict.items()):
112        generate_file_single_led(
113            ifile,
114            led_name,
115            list_dict,
116            priority_dict,
117            ofile,
118            has_group_priority,
119            group,
120        )
121
122    ofile.write("   }}},\n")
123
124    return 0
125
126
127def generate_file(ifile, ofile):
128    # Dictionary having [Name:Priority]
129    priority_dict = {}
130
131    ofile.write("/* !!! WARNING: This is a GENERATED Code..")
132    ofile.write("Please do NOT Edit !!! */\n\n")
133
134    ofile.write("static const phosphor::led::GroupMap")
135    ofile.write(" systemLedMap = {\n\n")
136
137    for group in list(ifile.keys()):
138        generate_file_single_group(ifile, group, priority_dict, ofile)
139    ofile.write("};\n")
140
141    return 0
142
143
144if __name__ == "__main__":
145    script_dir = os.path.dirname(os.path.realpath(__file__))
146    parser = argparse.ArgumentParser()
147    parser.add_argument(
148        "-f", "--filename", default="led.yaml", help="Input File Name"
149    )
150    parser.add_argument(
151        "-l",
152        "--output-filename",
153        dest="outputfilename",
154        default="led-gen.hpp",
155        help="Output File Name",
156    )
157    parser.add_argument(
158        "-i",
159        "--input-dir",
160        dest="inputdir",
161        default=script_dir,
162        help="Input directory",
163    )
164    parser.add_argument(
165        "-o",
166        "--output-dir",
167        dest="outputdir",
168        default=".",
169        help="Output directory.",
170    )
171
172    args = parser.parse_args()
173
174    # Default to the one that is in the current.
175    yaml_dir = script_dir
176    yaml_file = os.path.join(yaml_dir, "led.yaml")
177
178    if args.inputdir:
179        yaml_dir = args.inputdir
180
181    if args.filename:
182        yaml_file = os.path.join(yaml_dir, args.filename)
183
184    with open(yaml_file, "r") as f:
185        ifile = yaml.safe_load(f)
186
187    with open(os.path.join(args.outputdir, args.outputfilename), "w") as ofile:
188        generate_file(ifile, ofile)
189