00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <pwd.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <stdarg.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <unistd.h>
00041 #include <syslog.h>
00042 #include <string.h>
00043 #include <signal.h>
00044 #include <ctype.h>
00045 #include <sys/socket.h>
00046 #include <netdb.h>
00047
00048 #include "pigpio.h"
00049
00050
00051
00052
00053
00054 static unsigned bufferSizeMilliseconds = PI_DEFAULT_BUFFER_MILLIS;
00055 static unsigned clockMicros = PI_DEFAULT_CLK_MICROS;
00056 static unsigned clockPeripheral = PI_DEFAULT_CLK_PERIPHERAL;
00057 static unsigned ifFlags = PI_DEFAULT_IF_FLAGS;
00058 static int foreground = PI_DEFAULT_FOREGROUND;
00059 static unsigned DMAprimaryChannel = PI_DEFAULT_DMA_PRIMARY_CHANNEL;
00060 static unsigned DMAsecondaryChannel = PI_DEFAULT_DMA_SECONDARY_CHANNEL;
00061 static unsigned socketPort = PI_DEFAULT_SOCKET_PORT;
00062 static unsigned memAllocMode = PI_DEFAULT_MEM_ALLOC_MODE;
00063 static uint64_t updateMask = -1;
00064
00065 static uint32_t cfgInternals = PI_DEFAULT_CFG_INTERNALS;
00066
00067 static int updateMaskSet = 0;
00068
00069 static FILE * errFifo;
00070
00071 static uint32_t sockNetAddr[MAX_CONNECT_ADDRESSES];
00072
00073 static int numSockNetAddr = 0;
00074
00075 void fatal(char *fmt, ...)
00076 {
00077 char buf[128];
00078 va_list ap;
00079
00080 va_start(ap, fmt);
00081 vsnprintf(buf, sizeof(buf), fmt, ap);
00082 va_end(ap);
00083
00084 fprintf(stderr, "%s\n", buf);
00085
00086 fflush(stderr);
00087
00088 exit(EXIT_FAILURE);
00089 }
00090
00091 void usage()
00092 {
00093 fprintf(stderr, "\n" \
00094 "pigpio V%d\n" \
00095 "Usage: sudo pigpiod [OPTION] ...\n" \
00096 " -a value, DMA mode, 0=AUTO, 1=PMAP, 2=MBOX, default AUTO\n" \
00097 " -b value, sample buffer size in ms, default 120\n" \
00098 " -c value, library internal settings, default 0\n" \
00099 " -d value, primary DMA channel, 0-14, default 14\n" \
00100 " -e value, secondary DMA channel, 0-14, default 6\n" \
00101 " -f, disable fifo interface, default enabled\n" \
00102 " -g, run in foreground (do not fork), default disabled\n" \
00103 " -k, disable socket interface, default enabled\n" \
00104 " -l, localhost socket only default local+remote\n" \
00105 " -m, disable alerts default enabled\n" \
00106 " -n IP addr, allow address, name or dotted, default allow all\n" \
00107 " -p value, socket port, 1024-32000, default 8888\n" \
00108 " -s value, sample rate, 1, 2, 4, 5, 8, or 10, default 5\n" \
00109 " -t value, clock peripheral, 0=PWM 1=PCM, default PCM\n" \
00110 " -v, -V, display pigpio version and exit\n" \
00111 " -x mask, GPIO which may be updated, default board GPIO\n" \
00112 "EXAMPLE\n" \
00113 "sudo pigpiod -s 2 -b 200 -f\n" \
00114 " Set a sample rate of 2 microseconds with a 200 millisecond\n" \
00115 " buffer. Disable the fifo interface.\n" \
00116 "\n", PIGPIO_VERSION);
00117 }
00118
00119 static uint64_t getNum(char *str, int *err)
00120 {
00121 uint64_t val;
00122 char *endptr;
00123
00124 *err = 0;
00125 val = strtoll(str, &endptr, 0);
00126 if (*endptr) {*err = 1; val = -1;}
00127 return val;
00128 }
00129
00130 static uint32_t checkAddr(char *addrStr)
00131 {
00132 int err;
00133 struct addrinfo hints, *res;
00134 struct sockaddr_in *sin;
00135 const char *portStr;
00136 uint32_t addr;
00137
00138 portStr = getenv(PI_ENVPORT);
00139
00140 if (!portStr) portStr = PI_DEFAULT_SOCKET_PORT_STR;
00141
00142 memset (&hints, 0, sizeof (hints));
00143
00144 hints.ai_family = AF_INET;
00145 hints.ai_socktype = SOCK_STREAM;
00146 hints.ai_flags |= AI_CANONNAME;
00147
00148 err = getaddrinfo(addrStr, portStr, &hints, &res);
00149
00150 if (err) return 0;
00151
00152 sin = (struct sockaddr_in *)res->ai_addr;
00153 addr = sin->sin_addr.s_addr;
00154
00155 freeaddrinfo(res);
00156
00157 return addr;
00158 }
00159
00160 static void initOpts(int argc, char *argv[])
00161 {
00162 int opt, err, i;
00163 uint32_t addr;
00164 int64_t mask;
00165
00166 while ((opt = getopt(argc, argv, "a:b:c:d:e:fgkln:mp:s:t:x:vV")) != -1)
00167 {
00168 switch (opt)
00169 {
00170 case 'a':
00171 i = getNum(optarg, &err);
00172 if ((i >= PI_MEM_ALLOC_AUTO) && (i <= PI_MEM_ALLOC_MAILBOX))
00173 memAllocMode = i;
00174 else fatal("invalid -a option (%d)", i);
00175 break;
00176
00177 case 'b':
00178 i = getNum(optarg, &err);
00179 if ((i >= PI_BUF_MILLIS_MIN) && (i <= PI_BUF_MILLIS_MAX))
00180 bufferSizeMilliseconds = i;
00181 else fatal("invalid -b option (%d)", i);
00182 break;
00183
00184 case 'c':
00185 i = getNum(optarg, &err);
00186 if ((i >= 0) && (i < PI_CFG_ILLEGAL_VAL))
00187 cfgInternals = i;
00188 else fatal("invalid -c option (%x)", i);
00189 break;
00190
00191 case 'd':
00192 i = getNum(optarg, &err);
00193 if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_DMA_CHANNEL))
00194 DMAprimaryChannel = i;
00195 else fatal("invalid -d option (%d)", i);
00196 break;
00197
00198 case 'e':
00199 i = getNum(optarg, &err);
00200 if ((i >= PI_MIN_DMA_CHANNEL) && (i <= PI_MAX_DMA_CHANNEL))
00201 DMAsecondaryChannel = i;
00202 else fatal("invalid -e option (%d)", i);
00203 break;
00204
00205 case 'f':
00206 ifFlags |= PI_DISABLE_FIFO_IF;
00207 break;
00208
00209 case 'g':
00210 foreground = 1;
00211 break;
00212
00213 case 'k':
00214 ifFlags |= PI_DISABLE_SOCK_IF;
00215 break;
00216
00217 case 'l':
00218 ifFlags |= PI_LOCALHOST_SOCK_IF;
00219 break;
00220
00221 case 'm':
00222 ifFlags |= PI_DISABLE_ALERT;
00223 break;
00224
00225 case 'n':
00226 addr = checkAddr(optarg);
00227 if (addr && (numSockNetAddr<MAX_CONNECT_ADDRESSES))
00228 sockNetAddr[numSockNetAddr++] = addr;
00229 else fatal("invalid -n option (%s)", optarg);
00230 break;
00231
00232 case 'p':
00233 i = getNum(optarg, &err);
00234 if ((i >= PI_MIN_SOCKET_PORT) && (i <= PI_MAX_SOCKET_PORT))
00235 socketPort = i;
00236 else fatal("invalid -p option (%d)", i);
00237 break;
00238
00239 case 's':
00240 i = getNum(optarg, &err);
00241
00242 switch(i)
00243 {
00244 case 1:
00245 case 2:
00246 case 4:
00247 case 5:
00248 case 8:
00249 case 10:
00250 clockMicros = i;
00251 break;
00252
00253 default:
00254 fatal("invalid -s option (%d)", i);
00255 break;
00256 }
00257 break;
00258
00259 case 't':
00260 i = getNum(optarg, &err);
00261 if ((i >= PI_CLOCK_PWM) && (i <= PI_CLOCK_PCM))
00262 clockPeripheral = i;
00263 else fatal("invalid -t option (%d)", i);
00264 break;
00265
00266 case 'v':
00267 case 'V':
00268 printf("%d\n", PIGPIO_VERSION);
00269 exit(EXIT_SUCCESS);
00270 break;
00271
00272 case 'x':
00273 mask = getNum(optarg, &err);
00274 if (!err)
00275 {
00276 updateMask = mask;
00277 updateMaskSet = 1;
00278 }
00279 else fatal("invalid -x option (%s)", optarg);
00280 break;
00281
00282 default:
00283 usage();
00284 exit(EXIT_FAILURE);
00285 }
00286 }
00287 }
00288
00289 void terminate(int signum)
00290 {
00291
00292
00293 gpioTerminate();
00294
00295 fprintf(errFifo, "SIGHUP/SIGTERM received\n");
00296
00297 fflush(NULL);
00298
00299 fclose(errFifo);
00300
00301 unlink(PI_ERRFIFO);
00302
00303 exit(0);
00304 }
00305
00306
00307 int main(int argc, char **argv)
00308 {
00309 pid_t pid;
00310 int flags;
00311
00312
00313
00314 initOpts(argc, argv);
00315
00316 if (!foreground) {
00317
00318
00319 pid = fork();
00320
00321 if (pid < 0) { exit(EXIT_FAILURE); }
00322
00323
00324
00325 if (pid > 0) { exit(EXIT_SUCCESS); }
00326
00327
00328
00329 umask(0);
00330
00331
00332
00333
00334
00335
00336
00337 if (setsid() < 0) fatal("setsid failed (%m)");
00338
00339
00340
00341 if ((chdir("/")) < 0) fatal("chdir failed (%m)");
00342
00343
00344
00345 fclose(stdin);
00346 fclose(stdout);
00347 }
00348
00349
00350
00351 gpioCfgBufferSize(bufferSizeMilliseconds);
00352
00353 gpioCfgClock(clockMicros, clockPeripheral, 0);
00354
00355 gpioCfgInterfaces(ifFlags);
00356
00357 gpioCfgDMAchannels(DMAprimaryChannel, DMAsecondaryChannel);
00358
00359 gpioCfgSocketPort(socketPort);
00360
00361 gpioCfgMemAlloc(memAllocMode);
00362
00363 if (updateMaskSet) gpioCfgPermissions(updateMask);
00364
00365 gpioCfgNetAddr(numSockNetAddr, sockNetAddr);
00366
00367 gpioCfgSetInternals(cfgInternals);
00368
00369
00370
00371 if (gpioInitialise()< 0) fatal("Can't initialise pigpio library");
00372
00373
00374
00375 unlink(PI_ERRFIFO);
00376
00377 mkfifo(PI_ERRFIFO, 0664);
00378
00379 if (chmod(PI_ERRFIFO, 0664) < 0)
00380 fatal("chmod %s failed (%m)", PI_ERRFIFO);
00381
00382 errFifo = freopen(PI_ERRFIFO, "w+", stderr);
00383
00384 if (errFifo)
00385 {
00386
00387
00388 flags = fcntl(fileno(errFifo), F_GETFL, 0);
00389 fcntl(fileno(errFifo), F_SETFL, flags | O_NONBLOCK);
00390
00391
00392
00393 gpioSetSignalFunc(SIGHUP, terminate);
00394 gpioSetSignalFunc(SIGTERM, terminate);
00395
00396
00397
00398 while (1)
00399 {
00400
00401
00402 sleep(5);
00403
00404 fflush(errFifo);
00405 }
00406 }
00407 else
00408 {
00409 fprintf(stderr, "freopen failed (%m)");
00410
00411 gpioTerminate();
00412 }
00413
00414 return 0;
00415 }
00416
00417