1 /**
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 "i2c_write_bytes_action.hpp"
18 
19 #include "action_error.hpp"
20 #include "i2c_interface.hpp"
21 
22 #include <exception>
23 #include <ios>
24 #include <sstream>
25 
26 namespace phosphor::power::regulators
27 {
28 
execute(ActionEnvironment & environment)29 bool I2CWriteBytesAction::execute(ActionEnvironment& environment)
30 {
31     try
32     {
33         i2c::I2CInterface& interface = getI2CInterface(environment);
34         uint8_t valuesToWrite[UINT8_MAX];
35         if (masks.size() == 0)
36         {
37             for (unsigned int i = 0; i < values.size(); ++i)
38             {
39                 valuesToWrite[i] = values[i];
40             }
41         }
42         else
43         {
44             // Read current device register values.  Use I2C mode where the
45             // number of bytes to read is explicitly specified.
46             uint8_t size = values.size();
47             uint8_t currentValues[UINT8_MAX];
48             interface.read(reg, size, currentValues,
49                            i2c::I2CInterface::Mode::I2C);
50 
51             // Combine values to write with current values
52             for (unsigned int i = 0; i < values.size(); ++i)
53             {
54                 valuesToWrite[i] = (values[i] & masks[i]) |
55                                    (currentValues[i] & (~masks[i]));
56             }
57         }
58 
59         // Write values to device register
60         interface.write(reg, values.size(), valuesToWrite,
61                         i2c::I2CInterface::Mode::I2C);
62     }
63     catch (const i2c::I2CException& e)
64     {
65         // Nest I2CException within an ActionError so caller will have both the
66         // low level I2C error information and the action information
67         std::throw_with_nested(ActionError(*this));
68     }
69     return true;
70 }
71 
toString() const72 std::string I2CWriteBytesAction::toString() const
73 {
74     std::ostringstream ss;
75     ss << "i2c_write_bytes: { register: 0x" << std::hex << std::uppercase
76        << static_cast<uint16_t>(reg) << ", values: [ ";
77     for (unsigned int i = 0; i < values.size(); ++i)
78     {
79         ss << ((i > 0) ? ", " : "") << "0x" << static_cast<uint16_t>(values[i]);
80     }
81     ss << " ], masks: [ ";
82     for (unsigned int i = 0; i < masks.size(); ++i)
83     {
84         ss << ((i > 0) ? ", " : "") << "0x" << static_cast<uint16_t>(masks[i]);
85     }
86     ss << " ] }";
87     return ss.str();
88 }
89 
90 } // namespace phosphor::power::regulators
91