blob: 11527b87de3e8826c74b952bd4fb3d975df824ec [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080020#include "i2c_interface.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050021#include "pmbus_utils.hpp"
22
23#include <exception>
24#include <fstream>
25#include <optional>
26#include <utility>
27
28using json = nlohmann::json;
29
30namespace phosphor::power::regulators::config_file_parser
31{
32
33std::tuple<std::vector<std::unique_ptr<Rule>>,
34 std::vector<std::unique_ptr<Chassis>>>
35 parse(const std::filesystem::path& pathName)
36{
37 try
38 {
39 // Use standard JSON parser to create tree of JSON elements
40 std::ifstream file{pathName};
41 json rootElement = json::parse(file);
42
43 // Parse tree of JSON elements and return corresponding C++ objects
44 return internal::parseRoot(rootElement);
45 }
46 catch (const std::exception& e)
47 {
48 throw ConfigFileParserError{pathName, e.what()};
49 }
50}
51
52namespace internal
53{
54
55std::unique_ptr<Action> parseAction(const json& element)
56{
57 verifyIsObject(element);
58 unsigned int propertyCount{0};
59
60 // Optional comments property; value not stored
61 if (element.contains("comments"))
62 {
63 ++propertyCount;
64 }
65
66 // Required action type property; there must be exactly one specified
67 std::unique_ptr<Action> action{};
68 if (element.contains("and"))
69 {
Bob King3a787542020-04-14 13:45:01 +080070 action = parseAnd(element["and"]);
71 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050072 }
73 else if (element.contains("compare_presence"))
74 {
Bob Kingb267b7e2020-04-22 14:42:39 +080075 action = parseComparePresence(element["compare_presence"]);
76 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050077 }
78 else if (element.contains("compare_vpd"))
79 {
Bob Kingf2134322020-04-27 14:14:56 +080080 action = parseCompareVPD(element["compare_vpd"]);
81 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050082 }
83 else if (element.contains("i2c_compare_bit"))
84 {
Bob Kingf09bfe02020-04-13 17:21:15 +080085 action = parseI2CCompareBit(element["i2c_compare_bit"]);
86 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050087 }
88 else if (element.contains("i2c_compare_byte"))
89 {
Bob Kingf09bfe02020-04-13 17:21:15 +080090 action = parseI2CCompareByte(element["i2c_compare_byte"]);
91 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050092 }
93 else if (element.contains("i2c_compare_bytes"))
94 {
Bob Kingf09bfe02020-04-13 17:21:15 +080095 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
96 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050097 }
98 else if (element.contains("i2c_write_bit"))
99 {
Bob Kingf617f892020-03-30 19:03:35 +0800100 action = parseI2CWriteBit(element["i2c_write_bit"]);
101 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500102 }
103 else if (element.contains("i2c_write_byte"))
104 {
Bob King87ff9d72020-03-31 14:02:55 +0800105 action = parseI2CWriteByte(element["i2c_write_byte"]);
106 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500107 }
108 else if (element.contains("i2c_write_bytes"))
109 {
Bob Kingbafcb862020-03-31 16:39:00 +0800110 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
111 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500112 }
113 else if (element.contains("if"))
114 {
Bob King93a89d72020-04-15 15:11:11 +0800115 action = parseIf(element["if"]);
116 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500117 }
118 else if (element.contains("not"))
119 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800120 action = parseNot(element["not"]);
121 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500122 }
123 else if (element.contains("or"))
124 {
Bob King0b51a9b2020-04-15 13:24:18 +0800125 action = parseOr(element["or"]);
126 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500127 }
128 else if (element.contains("pmbus_read_sensor"))
129 {
130 // TODO: Not implemented yet
131 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
132 // ++propertyCount;
133 }
134 else if (element.contains("pmbus_write_vout_command"))
135 {
136 action =
137 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
138 ++propertyCount;
139 }
140 else if (element.contains("run_rule"))
141 {
Bob King315b0b62020-04-03 21:47:58 +0800142 action = parseRunRule(element["run_rule"]);
143 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500144 }
145 else if (element.contains("set_device"))
146 {
Bob King18a68502020-04-17 14:19:56 +0800147 action = parseSetDevice(element["set_device"]);
148 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500149 }
150 else
151 {
152 throw std::invalid_argument{"Required action type property missing"};
153 }
154
155 // Verify no invalid properties exist
156 verifyPropertyCount(element, propertyCount);
157
158 return action;
159}
160
161std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
162{
163 verifyIsArray(element);
164 std::vector<std::unique_ptr<Action>> actions;
165 for (auto& actionElement : element)
166 {
167 actions.emplace_back(parseAction(actionElement));
168 }
169 return actions;
170}
171
Bob King3a787542020-04-14 13:45:01 +0800172std::unique_ptr<AndAction> parseAnd(const json& element)
173{
174 verifyIsArray(element);
175
176 // Verify if array size less than 2
177 if (element.size() < 2)
178 {
179 throw std::invalid_argument{"Array must contain two or more actions"};
180 }
181 // Array of two or more actions
182 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
183
184 return std::make_unique<AndAction>(std::move(actions));
185}
186
Bob King0e701132020-04-03 21:50:31 +0800187std::unique_ptr<Chassis> parseChassis(const json& element)
188{
189 verifyIsObject(element);
190 unsigned int propertyCount{0};
191
192 // Optional comments property; value not stored
193 if (element.contains("comments"))
194 {
195 ++propertyCount;
196 }
197
198 // Required number property
199 const json& numberElement = getRequiredProperty(element, "number");
200 unsigned int number = parseUnsignedInteger(numberElement);
201 if (number < 1)
202 {
203 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
204 }
205 ++propertyCount;
206
207 // Optional devices property
208 std::vector<std::unique_ptr<Device>> devices{};
209 auto devicesIt = element.find("devices");
210 if (devicesIt != element.end())
211 {
212 devices = parseDeviceArray(*devicesIt);
213 ++propertyCount;
214 }
215
216 // Verify no invalid properties exist
217 verifyPropertyCount(element, propertyCount);
218
219 return std::make_unique<Chassis>(number, std::move(devices));
220}
221
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500222std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
223{
224 verifyIsArray(element);
225 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800226 for (auto& chassisElement : element)
227 {
228 chassis.emplace_back(parseChassis(chassisElement));
229 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500230 return chassis;
231}
232
Bob Kingb267b7e2020-04-22 14:42:39 +0800233std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
234{
235 verifyIsObject(element);
236 unsigned int propertyCount{0};
237
238 // Required fru property
239 const json& fruElement = getRequiredProperty(element, "fru");
240 std::string fru = parseString(fruElement);
241 ++propertyCount;
242
243 // Required value property
244 const json& valueElement = getRequiredProperty(element, "value");
245 bool value = parseBoolean(valueElement);
246 ++propertyCount;
247
248 // Verify no invalid properties exist
249 verifyPropertyCount(element, propertyCount);
250
251 return std::make_unique<ComparePresenceAction>(fru, value);
252}
253
Bob Kingf2134322020-04-27 14:14:56 +0800254std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element)
255{
256 verifyIsObject(element);
257 unsigned int propertyCount{0};
258
259 // Required fru property
260 const json& fruElement = getRequiredProperty(element, "fru");
261 std::string fru = parseString(fruElement);
262 ++propertyCount;
263
264 // Required keyword property
265 const json& keywordElement = getRequiredProperty(element, "keyword");
266 std::string keyword = parseString(keywordElement);
267 ++propertyCount;
268
269 // Required value property
270 const json& valueElement = getRequiredProperty(element, "value");
271 std::string value = parseString(valueElement);
272 ++propertyCount;
273
274 // Verify no invalid properties exist
275 verifyPropertyCount(element, propertyCount);
276
277 return std::make_unique<CompareVPDAction>(fru, keyword, value);
278}
279
Bob King33e7eaa2020-04-01 18:09:34 +0800280std::unique_ptr<Configuration> parseConfiguration(const json& element)
281{
282 verifyIsObject(element);
283 unsigned int propertyCount{0};
284
285 // Optional comments property; value not stored
286 if (element.contains("comments"))
287 {
288 ++propertyCount;
289 }
290
291 // Optional volts property
292 std::optional<double> volts{};
293 auto voltsIt = element.find("volts");
294 if (voltsIt != element.end())
295 {
296 volts = parseDouble(*voltsIt);
297 ++propertyCount;
298 }
299
300 // Required rule_id or actions property
301 std::vector<std::unique_ptr<Action>> actions{};
302 actions = parseRuleIDOrActionsProperty(element);
303 ++propertyCount;
304
305 // Verify no invalid properties exist
306 verifyPropertyCount(element, propertyCount);
307
308 return std::make_unique<Configuration>(volts, std::move(actions));
309}
310
Bob King9c36c5f2020-04-06 11:34:09 +0800311std::unique_ptr<Device> parseDevice(const json& element)
312{
313 verifyIsObject(element);
314 unsigned int propertyCount{0};
315
316 // Optional comments property; value not stored
317 if (element.contains("comments"))
318 {
319 ++propertyCount;
320 }
321
322 // Required id property
323 const json& idElement = getRequiredProperty(element, "id");
324 std::string id = parseString(idElement);
325 ++propertyCount;
326
327 // Required is_regulator property
328 const json& isRegulatorElement =
329 getRequiredProperty(element, "is_regulator");
330 bool isRegulator = parseBoolean(isRegulatorElement);
331 ++propertyCount;
332
333 // Required fru property
334 const json& fruElement = getRequiredProperty(element, "fru");
335 std::string fru = parseString(fruElement);
336 ++propertyCount;
337
338 // Required i2c_interface property
339 const json& i2cInterfaceElement =
340 getRequiredProperty(element, "i2c_interface");
341 std::unique_ptr<i2c::I2CInterface> i2cInterface =
342 parseI2CInterface(i2cInterfaceElement);
343 ++propertyCount;
344
345 // Optional presence_detection property
Bob King9c36c5f2020-04-06 11:34:09 +0800346 std::unique_ptr<PresenceDetection> presenceDetection{};
Bob King2aafb1c2020-04-16 15:24:32 +0800347 auto presenceDetectionIt = element.find("presence_detection");
348 if (presenceDetectionIt != element.end())
349 {
350 presenceDetection = parsePresenceDetection(*presenceDetectionIt);
351 ++propertyCount;
352 }
Bob King9c36c5f2020-04-06 11:34:09 +0800353
354 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800355 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800356 auto configurationIt = element.find("configuration");
357 if (configurationIt != element.end())
358 {
359 configuration = parseConfiguration(*configurationIt);
360 ++propertyCount;
361 }
Bob King9c36c5f2020-04-06 11:34:09 +0800362
363 // Optional rails property
364 std::vector<std::unique_ptr<Rail>> rails{};
365 auto railsIt = element.find("rails");
366 if (railsIt != element.end())
367 {
368 if (!isRegulator)
369 {
370 throw std::invalid_argument{
371 "Invalid rails property when is_regulator is false"};
372 }
373 rails = parseRailArray(*railsIt);
374 ++propertyCount;
375 }
376
377 // Verify no invalid properties exist
378 verifyPropertyCount(element, propertyCount);
379
380 return std::make_unique<Device>(id, isRegulator, fru,
381 std::move(i2cInterface),
382 std::move(presenceDetection),
383 std::move(configuration), std::move(rails));
384}
385
Bob King0e701132020-04-03 21:50:31 +0800386std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
387{
388 verifyIsArray(element);
389 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800390 for (auto& deviceElement : element)
391 {
392 devices.emplace_back(parseDevice(deviceElement));
393 }
Bob King0e701132020-04-03 21:50:31 +0800394 return devices;
395}
396
Bob Kingbafcb862020-03-31 16:39:00 +0800397std::vector<uint8_t> parseHexByteArray(const json& element)
398{
399 verifyIsArray(element);
400 std::vector<uint8_t> values;
401 for (auto& valueElement : element)
402 {
403 values.emplace_back(parseHexByte(valueElement));
404 }
405 return values;
406}
407
Bob Kingf09bfe02020-04-13 17:21:15 +0800408std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
409{
410 verifyIsObject(element);
411 unsigned int propertyCount{0};
412
413 // Required register property
414 const json& regElement = getRequiredProperty(element, "register");
415 uint8_t reg = parseHexByte(regElement);
416 ++propertyCount;
417
418 // Required position property
419 const json& positionElement = getRequiredProperty(element, "position");
420 uint8_t position = parseBitPosition(positionElement);
421 ++propertyCount;
422
423 // Required value property
424 const json& valueElement = getRequiredProperty(element, "value");
425 uint8_t value = parseBitValue(valueElement);
426 ++propertyCount;
427
428 // Verify no invalid properties exist
429 verifyPropertyCount(element, propertyCount);
430
431 return std::make_unique<I2CCompareBitAction>(reg, position, value);
432}
433
434std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
435{
436 verifyIsObject(element);
437 unsigned int propertyCount{0};
438
439 // Required register property
440 const json& regElement = getRequiredProperty(element, "register");
441 uint8_t reg = parseHexByte(regElement);
442 ++propertyCount;
443
444 // Required value property
445 const json& valueElement = getRequiredProperty(element, "value");
446 uint8_t value = parseHexByte(valueElement);
447 ++propertyCount;
448
449 // Optional mask property
450 uint8_t mask = 0xff;
451 auto maskIt = element.find("mask");
452 if (maskIt != element.end())
453 {
454 mask = parseHexByte(*maskIt);
455 ++propertyCount;
456 }
457
458 // Verify no invalid properties exist
459 verifyPropertyCount(element, propertyCount);
460
461 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
462}
463
464std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
465{
466 verifyIsObject(element);
467 unsigned int propertyCount{0};
468
469 // Required register property
470 const json& regElement = getRequiredProperty(element, "register");
471 uint8_t reg = parseHexByte(regElement);
472 ++propertyCount;
473
474 // Required values property
475 const json& valueElement = getRequiredProperty(element, "values");
476 std::vector<uint8_t> values = parseHexByteArray(valueElement);
477 ++propertyCount;
478
479 // Optional masks property
480 std::vector<uint8_t> masks{};
481 auto masksIt = element.find("masks");
482 if (masksIt != element.end())
483 {
484 masks = parseHexByteArray(*masksIt);
485 ++propertyCount;
486 }
487
488 // Verify masks array (if specified) was same size as values array
489 if ((!masks.empty()) && (masks.size() != values.size()))
490 {
491 throw std::invalid_argument{"Invalid number of elements in masks"};
492 }
493
494 // Verify no invalid properties exist
495 verifyPropertyCount(element, propertyCount);
496
497 if (masks.empty())
498 {
499 return std::make_unique<I2CCompareBytesAction>(reg, values);
500 }
501 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
502}
503
Bob King9c36c5f2020-04-06 11:34:09 +0800504std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
505{
506 verifyIsObject(element);
507 unsigned int propertyCount{0};
508
509 // Required bus property
510 const json& busElement = getRequiredProperty(element, "bus");
511 uint8_t bus = parseUint8(busElement);
512 ++propertyCount;
513
514 // Required address property
515 const json& addressElement = getRequiredProperty(element, "address");
516 uint8_t address = parseHexByte(addressElement);
517 ++propertyCount;
518
519 verifyPropertyCount(element, propertyCount);
520 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
521}
522
Bob Kingf617f892020-03-30 19:03:35 +0800523std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
524{
525 verifyIsObject(element);
526 unsigned int propertyCount{0};
527
528 // Required register property
529 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800530 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800531 ++propertyCount;
532
533 // Required position property
534 const json& positionElement = getRequiredProperty(element, "position");
535 uint8_t position = parseBitPosition(positionElement);
536 ++propertyCount;
537
538 // Required value property
539 const json& valueElement = getRequiredProperty(element, "value");
540 uint8_t value = parseBitValue(valueElement);
541 ++propertyCount;
542
543 // Verify no invalid properties exist
544 verifyPropertyCount(element, propertyCount);
545
546 return std::make_unique<I2CWriteBitAction>(reg, position, value);
547}
548
Bob King87ff9d72020-03-31 14:02:55 +0800549std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
550{
551 verifyIsObject(element);
552 unsigned int propertyCount{0};
553
554 // Required register property
555 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800556 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800557 ++propertyCount;
558
559 // Required value property
560 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800561 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800562 ++propertyCount;
563
564 // Optional mask property
565 uint8_t mask = 0xff;
566 auto maskIt = element.find("mask");
567 if (maskIt != element.end())
568 {
Bob Kingbafcb862020-03-31 16:39:00 +0800569 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800570 ++propertyCount;
571 }
572
573 // Verify no invalid properties exist
574 verifyPropertyCount(element, propertyCount);
575
576 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
577}
578
Bob Kingbafcb862020-03-31 16:39:00 +0800579std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
580{
581 verifyIsObject(element);
582 unsigned int propertyCount{0};
583
584 // Required register property
585 const json& regElement = getRequiredProperty(element, "register");
586 uint8_t reg = parseHexByte(regElement);
587 ++propertyCount;
588
589 // Required values property
590 const json& valueElement = getRequiredProperty(element, "values");
591 std::vector<uint8_t> values = parseHexByteArray(valueElement);
592 ++propertyCount;
593
594 // Optional masks property
595 std::vector<uint8_t> masks{};
596 auto masksIt = element.find("masks");
597 if (masksIt != element.end())
598 {
599 masks = parseHexByteArray(*masksIt);
600 ++propertyCount;
601 }
602
603 // Verify masks array (if specified) was same size as values array
604 if ((!masks.empty()) && (masks.size() != values.size()))
605 {
606 throw std::invalid_argument{"Invalid number of elements in masks"};
607 }
608
609 // Verify no invalid properties exist
610 verifyPropertyCount(element, propertyCount);
611
612 if (masks.empty())
613 {
614 return std::make_unique<I2CWriteBytesAction>(reg, values);
615 }
616 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
617}
618
Bob King93a89d72020-04-15 15:11:11 +0800619std::unique_ptr<IfAction> parseIf(const json& element)
620{
621 verifyIsObject(element);
622 unsigned int propertyCount{0};
623
624 // Required condition property
625 const json& conditionElement = getRequiredProperty(element, "condition");
626 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
627 ++propertyCount;
628
629 // Required then property
630 const json& thenElement = getRequiredProperty(element, "then");
631 std::vector<std::unique_ptr<Action>> thenActions =
632 parseActionArray(thenElement);
633 ++propertyCount;
634
635 // Optional else property
636 std::vector<std::unique_ptr<Action>> elseActions{};
637 auto elseIt = element.find("else");
638 if (elseIt != element.end())
639 {
640 elseActions = parseActionArray(*elseIt);
641 ++propertyCount;
642 }
643
644 // Verify no invalid properties exist
645 verifyPropertyCount(element, propertyCount);
646
647 return std::make_unique<IfAction>(std::move(conditionAction),
648 std::move(thenActions),
649 std::move(elseActions));
650}
651
Bob Kingf1b58dc2020-04-14 14:53:10 +0800652std::unique_ptr<NotAction> parseNot(const json& element)
653{
654 // Required action to execute
655 std::unique_ptr<Action> action = parseAction(element);
656
657 return std::make_unique<NotAction>(std::move(action));
658}
659
Bob King0b51a9b2020-04-15 13:24:18 +0800660std::unique_ptr<OrAction> parseOr(const json& element)
661{
662 verifyIsArray(element);
663
664 // Verify if array size less than 2
665 if (element.size() < 2)
666 {
667 throw std::invalid_argument{"Array must contain two or more actions"};
668 }
669 // Array of two or more actions
670 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
671
672 return std::make_unique<OrAction>(std::move(actions));
673}
674
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500675std::unique_ptr<PMBusWriteVoutCommandAction>
676 parsePMBusWriteVoutCommand(const json& element)
677{
678 verifyIsObject(element);
679 unsigned int propertyCount{0};
680
681 // Optional volts property
682 std::optional<double> volts{};
683 auto voltsIt = element.find("volts");
684 if (voltsIt != element.end())
685 {
686 volts = parseDouble(*voltsIt);
687 ++propertyCount;
688 }
689
690 // Required format property
691 const json& formatElement = getRequiredProperty(element, "format");
692 std::string formatString = parseString(formatElement);
693 if (formatString != "linear")
694 {
695 throw std::invalid_argument{"Invalid format value: " + formatString};
696 }
697 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
698 ++propertyCount;
699
700 // Optional exponent property
701 std::optional<int8_t> exponent{};
702 auto exponentIt = element.find("exponent");
703 if (exponentIt != element.end())
704 {
705 exponent = parseInt8(*exponentIt);
706 ++propertyCount;
707 }
708
709 // Optional is_verified property
710 bool isVerified = false;
711 auto isVerifiedIt = element.find("is_verified");
712 if (isVerifiedIt != element.end())
713 {
714 isVerified = parseBoolean(*isVerifiedIt);
715 ++propertyCount;
716 }
717
718 // Verify no invalid properties exist
719 verifyPropertyCount(element, propertyCount);
720
721 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
722 exponent, isVerified);
723}
724
Bob King2aafb1c2020-04-16 15:24:32 +0800725std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
726{
727 verifyIsObject(element);
728 unsigned int propertyCount{0};
729
730 // Optional comments property; value not stored
731 if (element.contains("comments"))
732 {
733 ++propertyCount;
734 }
735
736 // Required rule_id or actions property
737 std::vector<std::unique_ptr<Action>> actions{};
738 actions = parseRuleIDOrActionsProperty(element);
739 ++propertyCount;
740
741 // Verify no invalid properties exist
742 verifyPropertyCount(element, propertyCount);
743
744 return std::make_unique<PresenceDetection>(std::move(actions));
745}
746
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800747std::unique_ptr<Rail> parseRail(const json& element)
748{
749 verifyIsObject(element);
750 unsigned int propertyCount{0};
751
752 // Optional comments property; value not stored
753 if (element.contains("comments"))
754 {
755 ++propertyCount;
756 }
757
758 // Required id property
759 const json& idElement = getRequiredProperty(element, "id");
760 std::string id = parseString(idElement);
761 ++propertyCount;
762
763 // Optional configuration property
764 std::unique_ptr<Configuration> configuration{};
765 auto configurationIt = element.find("configuration");
766 if (configurationIt != element.end())
767 {
768 configuration = parseConfiguration(*configurationIt);
769 ++propertyCount;
770 }
771
772 // Optional sensor_monitoring property
773 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
774 auto sensorMonitoringIt = element.find("sensor_monitoring");
775 if (sensorMonitoringIt != element.end())
776 {
777 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
778 ++propertyCount;
779 }
780
781 // Verify no invalid properties exist
782 verifyPropertyCount(element, propertyCount);
783
784 return std::make_unique<Rail>(id, std::move(configuration),
785 std::move(sensorMonitoring));
786}
787
Bob King9c36c5f2020-04-06 11:34:09 +0800788std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
789{
790 verifyIsArray(element);
791 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800792 for (auto& railElement : element)
793 {
794 rails.emplace_back(parseRail(railElement));
795 }
Bob King9c36c5f2020-04-06 11:34:09 +0800796 return rails;
797}
798
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500799std::tuple<std::vector<std::unique_ptr<Rule>>,
800 std::vector<std::unique_ptr<Chassis>>>
801 parseRoot(const json& element)
802{
803 verifyIsObject(element);
804 unsigned int propertyCount{0};
805
806 // Optional comments property; value not stored
807 if (element.contains("comments"))
808 {
809 ++propertyCount;
810 }
811
812 // Optional rules property
813 std::vector<std::unique_ptr<Rule>> rules{};
814 auto rulesIt = element.find("rules");
815 if (rulesIt != element.end())
816 {
817 rules = parseRuleArray(*rulesIt);
818 ++propertyCount;
819 }
820
821 // Required chassis property
822 const json& chassisElement = getRequiredProperty(element, "chassis");
823 std::vector<std::unique_ptr<Chassis>> chassis =
824 parseChassisArray(chassisElement);
825 ++propertyCount;
826
827 // Verify no invalid properties exist
828 verifyPropertyCount(element, propertyCount);
829
830 return std::make_tuple(std::move(rules), std::move(chassis));
831}
832
833std::unique_ptr<Rule> parseRule(const json& element)
834{
835 verifyIsObject(element);
836 unsigned int propertyCount{0};
837
838 // Optional comments property; value not stored
839 if (element.contains("comments"))
840 {
841 ++propertyCount;
842 }
843
844 // Required id property
845 const json& idElement = getRequiredProperty(element, "id");
846 std::string id = parseString(idElement);
847 ++propertyCount;
848
849 // Required actions property
850 const json& actionsElement = getRequiredProperty(element, "actions");
851 std::vector<std::unique_ptr<Action>> actions =
852 parseActionArray(actionsElement);
853 ++propertyCount;
854
855 // Verify no invalid properties exist
856 verifyPropertyCount(element, propertyCount);
857
858 return std::make_unique<Rule>(id, std::move(actions));
859}
860
861std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
862{
863 verifyIsArray(element);
864 std::vector<std::unique_ptr<Rule>> rules;
865 for (auto& ruleElement : element)
866 {
867 rules.emplace_back(parseRule(ruleElement));
868 }
869 return rules;
870}
871
Bob King33e7eaa2020-04-01 18:09:34 +0800872std::vector<std::unique_ptr<Action>>
873 parseRuleIDOrActionsProperty(const json& element)
874{
875 verifyIsObject(element);
876 // Required rule_id or actions property
877 std::vector<std::unique_ptr<Action>> actions{};
878 auto ruleIDIt = element.find("rule_id");
879 auto actionsIt = element.find("actions");
880 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
881 {
882 std::string ruleID = parseString(*ruleIDIt);
883 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
884 }
885 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
886 {
887 actions = parseActionArray(*actionsIt);
888 }
889 else
890 {
891 throw std::invalid_argument{"Invalid property combination: Must "
892 "contain either rule_id or actions"};
893 }
894
895 return actions;
896}
897
Bob King315b0b62020-04-03 21:47:58 +0800898std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
899{
900 // String ruleID
901 std::string ruleID = parseString(element);
902
903 return std::make_unique<RunRuleAction>(ruleID);
904}
905
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800906std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
907{
908 verifyIsObject(element);
909 unsigned int propertyCount{0};
910
911 // Optional comments property; value not stored
912 if (element.contains("comments"))
913 {
914 ++propertyCount;
915 }
916
917 // Required rule_id or actions property
918 std::vector<std::unique_ptr<Action>> actions{};
919 actions = parseRuleIDOrActionsProperty(element);
920 ++propertyCount;
921
922 // Verify no invalid properties exist
923 verifyPropertyCount(element, propertyCount);
924
925 return std::make_unique<SensorMonitoring>(std::move(actions));
926}
927
Bob King18a68502020-04-17 14:19:56 +0800928std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
929{
930 // String deviceID
931 std::string deviceID = parseString(element);
932
933 return std::make_unique<SetDeviceAction>(deviceID);
934}
935
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500936} // namespace internal
937
938} // namespace phosphor::power::regulators::config_file_parser