blob: 27da69735b6a90129e2728ef48c839ab7fec0505 [file] [log] [blame]
Matt Spinler936a5042017-05-25 10:17:13 -05001/**
2 * Copyright © 2017 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
Matt Spinlere3b859c2017-05-25 11:15:43 -050017/**
18 * This program is a utility for accessing GPIOs.
19 * Actions:
20 * low: Set a GPIO low
21 * high: Set a GPIO high
22 * low_high: Set a GPIO low, delay if requested, set it high
23 * high_low: Set a GPIO high, delay if requested, set it low
24 */
25
Patrick Venturedace6802018-11-01 16:52:10 -070026#include "argument.hpp"
27#include "gpio.hpp"
28
Patrick Williams39084b42023-05-10 07:50:58 -050029#include <phosphor-logging/log.hpp>
30
Matt Spinlere3b859c2017-05-25 11:15:43 -050031#include <algorithm>
32#include <chrono>
33#include <iostream>
34#include <map>
Patrick Venturedace6802018-11-01 16:52:10 -070035#include <thread>
Matt Spinlere3b859c2017-05-25 11:15:43 -050036
37using namespace phosphor::gpio;
38using namespace phosphor::logging;
39
40typedef void (*gpioFunction)(GPIO&, unsigned int);
41using gpioFunctionMap = std::map<std::string, gpioFunction>;
42
43/**
44 * Sets a GPIO low
45 *
46 * @param[in] gpio - the GPIO object
47 * @param[in] delayInMS - Unused in this function
48 */
Brad Bishop0d686452019-10-21 12:11:09 -040049void low(GPIO& gpio, unsigned int)
Matt Spinlere3b859c2017-05-25 11:15:43 -050050{
51 gpio.set(GPIO::Value::low);
52}
53
Matt Spinlere3b859c2017-05-25 11:15:43 -050054/**
55 * Sets a GPIO high
56 *
57 * @param[in] gpio - the GPIO object
58 * @param[in] delayInMS - Unused in this function
59 */
Brad Bishop0d686452019-10-21 12:11:09 -040060void high(GPIO& gpio, unsigned int)
Matt Spinlere3b859c2017-05-25 11:15:43 -050061{
62 gpio.set(GPIO::Value::high);
63}
64
Matt Spinlere3b859c2017-05-25 11:15:43 -050065/**
66 * Sets a GPIO high, then delays, then sets it low
67 *
68 * @param[in] gpio - the GPIO object
69 * @param[in] delayInMS - The delay in between the sets
70 */
71void highLow(GPIO& gpio, unsigned int delayInMS)
72{
73 gpio.set(GPIO::Value::high);
74
75 std::chrono::milliseconds delay{delayInMS};
76 std::this_thread::sleep_for(delay);
77
78 gpio.set(GPIO::Value::low);
79}
80
Matt Spinlere3b859c2017-05-25 11:15:43 -050081/**
82 * Sets a GPIO low, then delays, then sets it high
83 *
84 * @param[in] gpio - the GPIO to write
85 * @param[in] delayInMS - The delay in between the sets
86 */
87void lowHigh(GPIO& gpio, unsigned int delayInMS)
88{
89 gpio.set(GPIO::Value::low);
90
91 std::chrono::milliseconds delay{delayInMS};
92 std::this_thread::sleep_for(delay);
93
94 gpio.set(GPIO::Value::high);
95}
96
Matt Spinlere3b859c2017-05-25 11:15:43 -050097/**
98 * The actions supported by this program
99 */
Patrick Venturedace6802018-11-01 16:52:10 -0700100static const gpioFunctionMap functions{
101 {"low", low}, {"high", high}, {"low_high", lowHigh}, {"high_low", highLow}};
Matt Spinlere3b859c2017-05-25 11:15:43 -0500102
103/**
104 * Prints usage and exits the program
105 *
106 * @param[in] err - the error message to print
107 * @param[in] argv - argv from main()
108 */
109void exitWithError(const char* err, char** argv)
110{
111 std::cerr << "ERROR: " << err << "\n";
112 ArgumentParser::usage(argv);
113 exit(EXIT_FAILURE);
114}
115
Matt Spinlere3b859c2017-05-25 11:15:43 -0500116/**
117 * Returns the number value of the argument passed in.
118 *
119 * @param[in] name - the argument name
120 * @param[in] parser - the argument parser
121 * @param[in] argv - arv from main()
122 */
Patrick Venturedace6802018-11-01 16:52:10 -0700123template <typename T>
124T getValueFromArg(const char* name, ArgumentParser& parser, char** argv)
Matt Spinlere3b859c2017-05-25 11:15:43 -0500125{
126 char* p = NULL;
127 auto val = strtol(parser[name].c_str(), &p, 10);
128
Patrick Venturedace6802018-11-01 16:52:10 -0700129 // strol sets p on error, also we don't allow negative values
Matt Spinlere3b859c2017-05-25 11:15:43 -0500130 if (*p || (val < 0))
131 {
132 using namespace std::string_literals;
133 std::string msg = "Invalid "s + name + " value passed in";
134 exitWithError(msg.c_str(), argv);
135 }
136 return static_cast<T>(val);
137}
138
Matt Spinler936a5042017-05-25 10:17:13 -0500139int main(int argc, char** argv)
140{
Matt Spinlere3b859c2017-05-25 11:15:43 -0500141 ArgumentParser args(argc, argv);
142
143 auto path = args["path"];
144 if (path == ArgumentParser::emptyString)
145 {
146 exitWithError("GPIO device path not specified", argv);
147 }
148
149 auto action = args["action"];
150 if (action == ArgumentParser::emptyString)
151 {
152 exitWithError("Action not specified", argv);
153 }
154
155 if (args["gpio"] == ArgumentParser::emptyString)
156 {
157 exitWithError("GPIO not specified", argv);
158 }
159
160 auto gpioNum = getValueFromArg<gpioNum_t>("gpio", args, argv);
161
Patrick Venturedace6802018-11-01 16:52:10 -0700162 // Not all actions require a delay, so not required
Matt Spinlere3b859c2017-05-25 11:15:43 -0500163 unsigned int delay = 0;
164 if (args["delay"] != ArgumentParser::emptyString)
165 {
166 delay = getValueFromArg<decltype(delay)>("delay", args, argv);
167 }
168
169 auto function = functions.find(action);
170 if (function == functions.end())
171 {
172 exitWithError("Invalid action value passed in", argv);
173 }
174
175 GPIO gpio{path, gpioNum, GPIO::Direction::output};
176
177 try
178 {
179 function->second(gpio, delay);
180 }
Patrick Williams67554142021-10-06 13:00:15 -0500181 catch (const std::runtime_error& e)
Matt Spinlere3b859c2017-05-25 11:15:43 -0500182 {
183 std::cerr << e.what();
184 return -1;
185 }
186
Matt Spinler936a5042017-05-25 10:17:13 -0500187 return 0;
188}