blob: 80635756cdf16946a2edc48799a7318851523218 [file] [log] [blame]
Vishwanatha Subbanna4f43f5e2020-03-09 03:56:57 -05001#!/usr/bin/env python3
Vishwanatha Subbannaccbdf672017-01-23 14:39:06 +05302import argparse
Patrick Williams6d254ee2022-12-06 10:52:53 -06003import os
Alexander Hansen6fd9eea2025-01-14 12:04:29 +01004import re
5import sys
Patrick Williams6d254ee2022-12-06 10:52:53 -06006
7import yaml
Vishwanatha Subbanna32bb6f82017-03-27 18:15:52 +05308from inflection import underscore
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +05309
Alexander Hansen5a9f6512024-07-30 15:20:49 +020010
Alexander Hansen6fd9eea2025-01-14 12:04:29 +010011def is_dbus_safe(name: str) -> bool:
12 """
13 Check if a string is safe for use on D-Bus.
14
15 Args:
16 name (str): The input string.
17
18 Returns:
19 bool: True if the string is safe for D-Bus, False otherwise.
20 """
21 if not name:
22 return False # Empty names are not allowed
23
24 # Check for invalid characters
25 if not re.match(r"^[a-zA-Z0-9_]+$", name):
26 return False
27
28 # Check for leading or trailing dots/underscores
29 if name[0] in "._" or name[-1] in "._":
30 return False
31
32 # Check for consecutive dots or underscores
33 if ".." in name or "__" in name:
34 return False
35
36 # Check length restriction
37 if len(name) > 255:
38 return False
39
40 return True
41
42
43def convert_dbus_name_error(name: str) -> str:
44
45 if not is_dbus_safe(name):
46 print("WARNING: '" + name + "' is not dbus safe", file=sys.stderr)
47 raise ValueError("WARNING: '" + name + "' is not dbus safe")
48
49 return name
50
51
52def convert_dbus_name_warn(name: str) -> str:
53
54 if not is_dbus_safe(name):
55 print("WARNING: '" + name + "' is not dbus safe", file=sys.stderr)
56
57 result = underscore(name)
58
59 if name != result:
60 print(
61 "WARNING: converted '" + name + "' to '" + result + "'",
62 file=sys.stderr,
63 )
64
65 return result
66
67
Alexander Hansen638d1482024-08-21 17:39:57 +020068def config_error(ofile, led_name, group_name, message):
69 ofile.close()
70 os.remove(ofile.name)
71 raise ValueError(
72 "Invalid Configuration for LED ["
73 + led_name
74 + "] in Group ["
75 + group_name
76 + "]: "
77 + message
78 )
79
80
81def check_led_priority(led_name, group, value, priority_dict):
Alexander Hansen5a9f6512024-07-30 15:20:49 +020082
83 if led_name in priority_dict:
84 if value != priority_dict[led_name]:
85 # Priority for a particular LED needs to stay SAME
86 # across all groups
Alexander Hansen638d1482024-08-21 17:39:57 +020087 config_error(
88 ofile,
89 led_name,
90 group,
91 "Priority is NOT same across all groups",
Alexander Hansen5a9f6512024-07-30 15:20:49 +020092 )
93 else:
94 priority_dict[led_name] = value
95
96 return 0
97
98
Alexander Hansen638d1482024-08-21 17:39:57 +020099def led_action_literal(action):
100 if action == "":
101 return "std::nullopt"
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200102
Alexander Hansen638d1482024-08-21 17:39:57 +0200103 return "phosphor::led::Layout::Action::" + str(action)
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200104
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200105
Alexander Hansen638d1482024-08-21 17:39:57 +0200106def generate_file_single_led(
107 ifile, led_name, list_dict, priority_dict, ofile, has_group_priority, group
108):
109
110 has_led_priority = "Priority" in list_dict
111
112 if has_group_priority and has_led_priority:
113 config_error(
114 ofile,
115 led_name,
116 group,
117 "cannot mix group priority with led priority",
118 )
119
120 if (not has_group_priority) and (not has_led_priority):
121 config_error(
122 ofile, led_name, group, "no group priority or led priority defined"
123 )
124
125 led_priority = list_dict.get("Priority", "")
126
127 if has_led_priority:
128 check_led_priority(led_name, group, led_priority, priority_dict)
129
130 action = led_action_literal(list_dict.get("Action", "Off"))
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200131 dutyOn = str(list_dict.get("DutyOn", 50))
132 period = str(list_dict.get("Period", 0))
Alexander Hansen638d1482024-08-21 17:39:57 +0200133 priority = led_action_literal(led_priority)
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200134
Alexander Hansen6fd9eea2025-01-14 12:04:29 +0100135 ofile.write(' {"' + convert_dbus_name_warn(led_name) + '",')
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200136 ofile.write(action + ",")
137 ofile.write(dutyOn + ",")
138 ofile.write(period + ",")
139 ofile.write(priority + ",")
140
141 ofile.write("},\n")
142
143 return 0
144
145
146def generate_file_single_group(ifile, group, priority_dict, ofile):
147 # This section generates an std::unordered_map of LedGroupNames to
148 # std::set of LEDs containing the name and properties
149 led_dict = ifile[group]
150
151 group_priority = 0
Jason M. Billsf2669fa2024-09-05 13:29:16 -0700152 has_group_priority = led_dict and "Priority" in led_dict
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200153
154 if has_group_priority:
155 group_priority = led_dict["Priority"]
156 # we do not want to enumerate this as a led group
157 del led_dict["Priority"]
158
159 ofile.write(
160 ' {"'
161 + "/xyz/openbmc_project/led/groups/"
Alexander Hansen6fd9eea2025-01-14 12:04:29 +0100162 + convert_dbus_name_error(group)
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200163 + '"'
164 + ",{ "
165 + str(group_priority)
166 + ",\n"
167 + "{\n"
168 )
169
Jason M. Billsf2669fa2024-09-05 13:29:16 -0700170 # Some LED groups could be empty
171 if not led_dict:
172 led_dict = {}
173
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200174 for led_name, list_dict in list(led_dict.items()):
175 generate_file_single_led(
Alexander Hansen638d1482024-08-21 17:39:57 +0200176 ifile,
177 led_name,
178 list_dict,
179 priority_dict,
180 ofile,
181 has_group_priority,
182 group,
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200183 )
184
185 ofile.write(" }}},\n")
186
187 return 0
188
189
190def generate_file(ifile, ofile):
191 # Dictionary having [Name:Priority]
192 priority_dict = {}
193
194 ofile.write("/* !!! WARNING: This is a GENERATED Code..")
195 ofile.write("Please do NOT Edit !!! */\n\n")
196
197 ofile.write("static const phosphor::led::GroupMap")
198 ofile.write(" systemLedMap = {\n\n")
199
200 for group in list(ifile.keys()):
201 generate_file_single_group(ifile, group, priority_dict, ofile)
202 ofile.write("};\n")
203
204 return 0
205
206
Patrick Williamsfccfac92022-03-17 05:14:46 -0500207if __name__ == "__main__":
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530208 script_dir = os.path.dirname(os.path.realpath(__file__))
Vishwanatha Subbannaccbdf672017-01-23 14:39:06 +0530209 parser = argparse.ArgumentParser()
Brad Bishop9a6220c2017-02-08 13:21:31 -0500210 parser.add_argument(
Patrick Williamsfccfac92022-03-17 05:14:46 -0500211 "-f", "--filename", default="led.yaml", help="Input File Name"
212 )
Brad Bishop9a6220c2017-02-08 13:21:31 -0500213 parser.add_argument(
Alexander Hansen30b60d42024-07-31 09:45:05 +0200214 "-l",
215 "--output-filename",
216 dest="outputfilename",
217 default="led-gen.hpp",
218 help="Output File Name",
219 )
220 parser.add_argument(
Patrick Williamsfccfac92022-03-17 05:14:46 -0500221 "-i",
222 "--input-dir",
223 dest="inputdir",
Brad Bishop9a6220c2017-02-08 13:21:31 -0500224 default=script_dir,
Patrick Williamsfccfac92022-03-17 05:14:46 -0500225 help="Input directory",
226 )
Brad Bishop513f58e2017-02-08 13:25:17 -0500227 parser.add_argument(
Patrick Williamsfccfac92022-03-17 05:14:46 -0500228 "-o",
229 "--output-dir",
230 dest="outputdir",
231 default=".",
232 help="Output directory.",
233 )
Brad Bishop513f58e2017-02-08 13:25:17 -0500234
Vishwanatha Subbannaccbdf672017-01-23 14:39:06 +0530235 args = parser.parse_args()
236
237 # Default to the one that is in the current.
Brad Bishop9a6220c2017-02-08 13:21:31 -0500238 yaml_dir = script_dir
Patrick Williamsfccfac92022-03-17 05:14:46 -0500239 yaml_file = os.path.join(yaml_dir, "led.yaml")
Vishwanatha Subbannaccbdf672017-01-23 14:39:06 +0530240
Brad Bishop513f58e2017-02-08 13:25:17 -0500241 if args.inputdir:
242 yaml_dir = args.inputdir
Vishwanatha Subbannaccbdf672017-01-23 14:39:06 +0530243
244 if args.filename:
245 yaml_file = os.path.join(yaml_dir, args.filename)
246
Patrick Williamsfccfac92022-03-17 05:14:46 -0500247 with open(yaml_file, "r") as f:
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530248 ifile = yaml.safe_load(f)
249
Alexander Hansen30b60d42024-07-31 09:45:05 +0200250 with open(os.path.join(args.outputdir, args.outputfilename), "w") as ofile:
Alexander Hansen5a9f6512024-07-30 15:20:49 +0200251 generate_file(ifile, ofile)