gpio  1.4.2
General Purpose I/O Package
gpioexport.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: gpio
4 //
5 // Program: gpioexport
6 //
7 // File: gpioexport.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-04-08 17:22:10 -0600 (Wed, 08 Apr 2015) $
12  * $Rev: 3913 $
13  *
14  * \brief Create GPIO exported interface.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  *
18  * \copyright
19  * \h_copy 2015-2017. RoadNarrows LLC.\n
20  * http://www.roadnarrows.com\n
21  * All Rights Reserved
22  */
23 /*
24  * @EulaBegin@
25  * @EulaEnd@
26  */
27 ////////////////////////////////////////////////////////////////////////////////
28 
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <unistd.h>
35 
36 #include <string>
37 
38 #include "rnr/rnrconfig.h"
39 #include "rnr/log.h"
40 #include "rnr/opts.h"
41 #include "rnr/pkg.h"
42 
43 #include "rnr/gpio.h"
44 
45 #include "version.h"
46 
47 using namespace std;
48 
49 /*!
50  * \ingroup cmds
51  * \defgroup gpioexport gpioexport
52  * \{
53  */
54 
55 #define APP_EC_OK 0 ///< success exit code
56 #define APP_EC_ARGS 2 ///< command-line options/arguments error exit code
57 #define APP_EC_EXEC 4 ///< execution exit code
58 
59 static char *Argv0; ///< the command
60 static char *OptsMode = NULL; ///< permissions
61 
62 #define NO_ARG -1 ///< no argument
63 
64 static int ArgsGpioNum; ///< gpio number
65 static int ArgsGpioDir; ///< gpio direction
66 static int ArgsGpioEdge; ///< gpio edge trigger type
67 static mode_t Permissions; ///< gpio permissions
68 
69 /*!
70  * \brief Program information.
71  */
72 static OptsPgmInfo_T PgmInfo =
73 {
74  // usage_args
75  "<gpio> [{in|out} [{none|rising|falling|both}]]",
76 
77  // synopsis
78  "Create GPIO exported interface.",
79 
80  // long_desc =
81  "The %P command creates a GPIO exported interface for the specified GPIO "
82  "number. Optionally, the direction and edge of the GPIO can also be "
83  "specified.\n\n"
84  "Arguments:\n"
85  " <gpio> Exported GPIO number.\n"
86  " <direction> GPIO direction. One of: in out.\n"
87  " Default: System defined.\n"
88  " <edge> Input GPIO trigger. One of: none rising falling both.\n"
89  " Default: System defined. N/A for output GPIO."
90  "\n\n"
91  "NOTE: This command requires root privileges.",
92 
93  // diagnostics
94  NULL
95 };
96 
97 /*!
98  * \brief Command line options information.
99  */
100 static OptsInfo_T OptsInfo[] =
101 {
102  // -m, --mode
103  {
104  "mode", // long_opt
105  'm', // short_opt
106  required_argument, // has_arg
107  false, // has_default
108  &OptsMode, // opt_addr
109  OptsCvtArgStr, // fn_cvt
110  OptsFmtStr, // fn_fmt
111  "<MODE>", // arg_name
112  // opt desc
113  "Change GPIO exported interface permissions. "
114  "Format: 0[0-7]+ for user,group,other."
115  },
116 
117  {NULL, }
118 };
119 
120 /*!
121  * \brief Exit program on bad command-line values.
122  */
123 static void badCmdExit()
124 {
125  fprintf(stderr, "Try '%s --help' for more information.\n", Argv0);
126  exit(APP_EC_ARGS);
127 }
128 
129 /*!
130  * \brief Convert string to integer.
131  */
132 static int strToInt(const string &str, int &val)
133 {
134  long long int val1; // must use 64-bit for arm 32-bit compilers
135 
136  if( sscanf(str.c_str(), "%lli", &val1) != 1 )
137  {
138  return RC_ERROR;
139  }
140 
141  val = (int)val1;
142 
143  return OK;
144 }
145 
146 /*!
147  * \brief Convert string to file permissions.
148  */
149 static int strToMode(const string &str, mode_t &mode)
150 {
151  int val;
152 
153  mode = 0;
154 
155  if( strToInt(str, val) < 0 )
156  {
157  return RC_ERROR;
158  }
159 
160  // negative
161  if( val < 0 )
162  {
163  return RC_ERROR;
164  }
165  // [0-7]
166  else if( val <= 7 )
167  {
168  mode = (mode_t)((val << 6) & S_IRWXU);
169  }
170  // [0-7][0-7]
171  else if( val <= 077 )
172  {
173  mode = (mode_t)((val << 3) & (S_IRWXU|S_IRWXG));
174  }
175  // [0-7][0-7][0-7]
176  else if( val <= 0777 )
177  {
178  mode = (mode_t)(val & (S_IRWXU|S_IRWXG|S_IRWXO));
179  }
180  // out-of-range error
181  else
182  {
183  return RC_ERROR;
184  }
185 
186  return OK;
187 }
188 
189 /*!
190  * \brief Main initialization.
191  *
192  * \param argc Command-line argument count.
193  * \param argv Command-line argument list.
194  *
195  * \par Exits:
196  * Program terminates on conversion error.
197  *
198  * \return
199  * Exit code.
200  */
201 static void mainInit(int argc, char *argv[])
202 {
203  // name of this process
204  Argv0 = basename(argv[0]);
205 
206  // parse input options
207  argv = OptsGet(Argv0, &PkgInfo, &PgmInfo, OptsInfo, true, &argc, argv);
208 
209  if( OptsMode != NULL )
210  {
211  if( strToMode(OptsMode, Permissions) < 0 )
212  {
213  fprintf(stderr, "%s: '%s': Bad permissions mode.\n", Argv0, OptsMode);
214  badCmdExit();
215  }
216  }
217 
218  if( argc == 0 )
219  {
220  fprintf(stderr, "%s: No GPIO pin number <gpio> specified.\n", Argv0);
221  badCmdExit();
222  }
223 
224  else if( strToInt(argv[0], ArgsGpioNum) < 0 )
225  {
226  fprintf(stderr, "%s: '%s': Bad GPIO number.\n", Argv0, argv[0]);
227  badCmdExit();
228  }
229 
230  if( argc >= 2 )
231  {
232  if( !strcasecmp(argv[1], GPIO_DIR_IN_STR) )
233  {
235  }
236  else if( !strcasecmp(argv[1], GPIO_DIR_OUT_STR) )
237  {
239  }
240  else
241  {
242  fprintf(stderr, "%s: '%s': Bad GPIO direction.\n", Argv0, argv[1]);
243  badCmdExit();
244  }
245  }
246  else
247  {
249  }
250 
251  if( argc >= 3 )
252  {
253  if( !strcasecmp(argv[2], GPIO_EDGE_NONE_STR) )
254  {
256  }
257  else if( !strcasecmp(argv[2], GPIO_EDGE_RISING_STR) )
258  {
260  }
261  else if( !strcasecmp(argv[2], GPIO_EDGE_FALLING_STR) )
262  {
264  }
265  else if( !strcasecmp(argv[2], GPIO_EDGE_BOTH_STR) )
266  {
268  }
269  else
270  {
271  fprintf(stderr, "%s: '%s': Bad GPIO edge.\n", Argv0, argv[2]);
272  badCmdExit();
273  }
274  }
275  else
276  {
278  }
279 
280  if( argc >= 4 )
281  {
282  fprintf(stderr, "%s: '%s...': What is this?.\n", Argv0, argv[3]);
283  badCmdExit();
284  }
285 }
286 
287 /*!
288  * \brief Main.
289  *
290  * \param argc Command-line argument count.
291  * \param argv Command-line argument list.
292  *
293  * \return Returns 0 on succes, non-zero on failure.
294  */
295 int main(int argc, char* argv[])
296 {
297  mainInit(argc, argv);
298 
299  if( gpioExport(ArgsGpioNum) < 0 )
300  {
301  return APP_EC_EXEC;
302  }
303 
304  if( ArgsGpioDir != NO_ARG )
305  {
307  {
308  return APP_EC_EXEC;
309  }
310  }
311 
312  if( ArgsGpioEdge != NO_ARG )
313  {
315  {
316  return APP_EC_EXEC;
317  }
318  }
319 
320  if( OptsMode != NULL )
321  {
322  char gpioPath[MAX_PATH];
323  char path[MAX_PATH];
324 
325  gpioMakeDirname(ArgsGpioNum, gpioPath, sizeof(gpioPath));
326 
327  sprintf(path, "%s/%s", gpioPath, "value");
328 
329  if( chmod(path, Permissions) < 0 )
330  {
331  LOGSYSERROR("chmod(%s, %o)", path, Permissions);
332  return APP_EC_EXEC;
333  }
334  }
335 
336  return APP_EC_OK;
337 }
338 
339 /*!
340  * \}
341  */
static void badCmdExit()
Exit program on bad command-line values.
Definition: gpioexport.cxx:123
#define GPIO_EDGE_FALLING
falling edge
Definition: gpio.h:78
static int strToMode(const string &str, mode_t &mode)
Convert string to file permissions.
Definition: gpioexport.cxx:149
#define NO_ARG
no argument
Definition: gpioexport.cxx:62
GPIO interface declarations and defines.
static int ArgsGpioDir
gpio direction
Definition: gpioexport.cxx:65
#define GPIO_EDGE_BOTH
both edges
Definition: gpio.h:79
#define GPIO_EDGE_FALLING_STR
falling edge string
Definition: gpio.h:82
#define GPIO_DIR_IN
input
Definition: gpio.h:68
static char * Argv0
the command
Definition: gpioexport.cxx:59
static int ArgsGpioNum
gpio number
Definition: gpioexport.cxx:64
#define GPIO_DIR_OUT_STR
output string
Definition: gpio.h:71
int gpioSetEdge(int gpio, int edge)
Set GPIO edge trigger type.
Definition: gpio.c:292
static OptsInfo_T OptsInfo[]
Command line options information.
Definition: gpioexport.cxx:100
static int ArgsGpioEdge
gpio edge trigger type
Definition: gpioexport.cxx:66
static OptsPgmInfo_T PgmInfo
Program information.
Definition: gpioexport.cxx:72
#define GPIO_EDGE_BOTH_STR
both edges string
Definition: gpio.h:83
#define GPIO_EDGE_NONE_STR
no edge string
Definition: gpio.h:80
#define GPIO_DIR_OUT
output
Definition: gpio.h:69
static const PkgInfo_T PkgInfo
Definition: version.h:45
#define GPIO_DIR_IN_STR
input string
Definition: gpio.h:70
#define GPIO_EDGE_NONE
no edge
Definition: gpio.h:76
int main(int argc, char *argv[])
Main.
Definition: gpioexport.cxx:295
#define APP_EC_EXEC
execution exit code
Definition: gpioexport.cxx:57
Package version information.
static mode_t Permissions
gpio permissions
Definition: gpioexport.cxx:67
#define GPIO_EDGE_RISING_STR
rising edge string
Definition: gpio.h:81
static void mainInit(int argc, char *argv[])
Main initialization.
Definition: gpioexport.cxx:201
int gpioSetDirection(int gpio, int dir)
Set GPIO signal direction.
Definition: gpio.c:250
void gpioMakeDirname(int gpio, char buf[], size_t size)
Make GPIO directory name.
Definition: gpio.c:587
#define GPIO_EDGE_RISING
rising edge
Definition: gpio.h:77
#define APP_EC_ARGS
command-line options/arguments error exit code
Definition: gpioexport.cxx:56
static char * OptsMode
permissions
Definition: gpioexport.cxx:60
static int strToInt(const string &str, int &val)
Convert string to integer.
Definition: gpioexport.cxx:132
#define APP_EC_OK
success exit code
Definition: gpioexport.cxx:55
int gpioExport(int gpio)
Export (create) a GPIO interface.
Definition: gpio.c:192