blob: fb56e6665e080a53248ffb0fea6f9a12ad512c7b [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
26#include <algorithm>
27#include <chrono>
28#include <iostream>
29#include <map>
30#include <thread>
31#include <phosphor-logging/log.hpp>
32#include "argument.hpp"
33#include "gpio.hpp"
34
35using namespace phosphor::gpio;
36using namespace phosphor::logging;
37
38typedef void (*gpioFunction)(GPIO&, unsigned int);
39using gpioFunctionMap = std::map<std::string, gpioFunction>;
40
41/**
42 * Sets a GPIO low
43 *
44 * @param[in] gpio - the GPIO object
45 * @param[in] delayInMS - Unused in this function
46 */
47void low(GPIO& gpio, unsigned int delayInMS)
48{
49 gpio.set(GPIO::Value::low);
50}
51
52
53/**
54 * Sets a GPIO high
55 *
56 * @param[in] gpio - the GPIO object
57 * @param[in] delayInMS - Unused in this function
58 */
59void high(GPIO& gpio, unsigned int delayInMS)
60{
61 gpio.set(GPIO::Value::high);
62}
63
64
65/**
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
81
82/**
83 * Sets a GPIO low, then delays, then sets it high
84 *
85 * @param[in] gpio - the GPIO to write
86 * @param[in] delayInMS - The delay in between the sets
87 */
88void lowHigh(GPIO& gpio, unsigned int delayInMS)
89{
90 gpio.set(GPIO::Value::low);
91
92 std::chrono::milliseconds delay{delayInMS};
93 std::this_thread::sleep_for(delay);
94
95 gpio.set(GPIO::Value::high);
96}
97
98
99/**
100 * The actions supported by this program
101 */
102static const gpioFunctionMap functions
103{
104 {"low", low},
105 {"high", high},
106 {"low_high", lowHigh},
107 {"high_low", highLow}
108};
109
110
111/**
112 * Prints usage and exits the program
113 *
114 * @param[in] err - the error message to print
115 * @param[in] argv - argv from main()
116 */
117void exitWithError(const char* err, char** argv)
118{
119 std::cerr << "ERROR: " << err << "\n";
120 ArgumentParser::usage(argv);
121 exit(EXIT_FAILURE);
122}
123
124
125/**
126 * Returns the number value of the argument passed in.
127 *
128 * @param[in] name - the argument name
129 * @param[in] parser - the argument parser
130 * @param[in] argv - arv from main()
131 */
132template<typename T>
133T getValueFromArg(const char* name,
134 ArgumentParser& parser,
135 char** argv)
136{
137 char* p = NULL;
138 auto val = strtol(parser[name].c_str(), &p, 10);
139
140 //strol sets p on error, also we don't allow negative values
141 if (*p || (val < 0))
142 {
143 using namespace std::string_literals;
144 std::string msg = "Invalid "s + name + " value passed in";
145 exitWithError(msg.c_str(), argv);
146 }
147 return static_cast<T>(val);
148}
149
150
Matt Spinler936a5042017-05-25 10:17:13 -0500151int main(int argc, char** argv)
152{
Matt Spinlere3b859c2017-05-25 11:15:43 -0500153 ArgumentParser args(argc, argv);
154
155 auto path = args["path"];
156 if (path == ArgumentParser::emptyString)
157 {
158 exitWithError("GPIO device path not specified", argv);
159 }
160
161 auto action = args["action"];
162 if (action == ArgumentParser::emptyString)
163 {
164 exitWithError("Action not specified", argv);
165 }
166
167 if (args["gpio"] == ArgumentParser::emptyString)
168 {
169 exitWithError("GPIO not specified", argv);
170 }
171
172 auto gpioNum = getValueFromArg<gpioNum_t>("gpio", args, argv);
173
174 //Not all actions require a delay, so not required
175 unsigned int delay = 0;
176 if (args["delay"] != ArgumentParser::emptyString)
177 {
178 delay = getValueFromArg<decltype(delay)>("delay", args, argv);
179 }
180
181 auto function = functions.find(action);
182 if (function == functions.end())
183 {
184 exitWithError("Invalid action value passed in", argv);
185 }
186
187 GPIO gpio{path, gpioNum, GPIO::Direction::output};
188
189 try
190 {
191 function->second(gpio, delay);
192 }
193 catch (std::runtime_error& e)
194 {
195 std::cerr << e.what();
196 return -1;
197 }
198
Matt Spinler936a5042017-05-25 10:17:13 -0500199 return 0;
200}