-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
153 lines (129 loc) · 4.42 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* gpiokey - Main Program - Monitors GPIO inputs and turns them into fake
keyboard events.
Copyright (c) 2019 by Stefan Vorkoetter
This file is part of gpiokey.
gpiokey is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
gpiokey is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
gpiokey. If not, see <http://www.gnu.org/licenses/>. */
#define _BSD_SOURCE // To enable daemon and usleep functions.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <unistd.h>
#include "gpio.h"
#include "x11.h"
static void usage( FILE *fp )
{
/* Print usage information and exit. */
fprintf(fp,"Usage: gpiokey [-b min] [-i key] [-n] [-h] { gpioPin [~] [+|-] keySym }\n\n");
fprintf(fp,"-b min\t- blank screen after this many minutes of idle time (1 to 10000)\n");
fprintf(fp,"-i key\t- send the specified key for GPIO events occurring when idle\n");
fprintf(fp,"-n\t- do not become a daemon, remain in the foreground\n");
fprintf(fp,"-h\t- display this help\n\n");
fprintf(fp,"gpioPin\t- BCM GPIO pin number (not physical or WiringPi) to scan for input\n");
fprintf(fp,"~\t- indicates input is negative logic (active-low)\n");
fprintf(fp,"+ or -\t- activates internal pull-up or -down resistor\n");
fprintf(fp,"keySym\t- specifies X11 key symbol associated with the pin\n");
if( fp == stderr )
exit(1);
}
int main( int argc, char **argv )
{
const char *msg;
/* Process command line options. */
bool optDaemonize = true;
int c, optTimeout = 0;
while( (c = getopt(argc,argv,"b:i:nh")) != -1 ) {
switch( c ) {
case 'b':
if( (optTimeout = atoi(optarg)) < 1 || optTimeout > 10000 )
usage(stderr);
optTimeout *= 60000;
break;
case 'i':
if( !ConfigureIdleKey(optarg,&msg) ) {
fprintf(stderr,"gpiokey: %s\n",msg);
return( 1 );
}
break;
case 'n':
optDaemonize = false;
break;
case 'h':
usage(stdout);
return( 0 );
default:
usage(stderr);
}
}
/* Build up list of GPIO ports to process. */
while( optind < argc ) {
int pin = atoi(argv[optind++]);
/* Input is active-low logic? */
bool neg;
if( neg = (optind < argc && strcmp(argv[optind],"~") == 0) )
++optind;
/* Activate pull-up or pull-down resistor? */
int res = 0;
if( optind < argc && strcmp(argv[optind],"+") == 0 ) {
res = 1;
++optind;
}
else if( optind < argc && strcmp(argv[optind],"-") == 0 ) {
res = -1;
++optind;
}
if( optind >= argc ) {
fprintf(stderr,"gpiokey: key symbol expected for GPIO pin %d\n",pin);
return( 1 );
}
/* Convert disambiguating keySymbols ++, --, and ~~ into their single
character equivalents. */
const char *keyStr = argv[optind++];
if( strcmp(keyStr,"++") == 0 || strcmp(keyStr,"--") == 0 || strcmp(keyStr,"~~") == 0 )
++keyStr;
if( !ConfigureInputPin(pin,neg,res,keyStr,&msg) ) {
fprintf(stderr,"gpiokey: GPIO error with pin %d: %s\n",pin,msg);
return( 1 );
}
}
/* Do what it takes to become a daemon. */
if( optDaemonize && daemon(0,0) != 0 ) {
fprintf(stderr,"gpiokey: failed to become a daemon: %s\n",strerror(errno));
return( 1 );
}
/* Ensure screen is in a known state initially. */
system("vcgencmd display_power 1");
bool screenOn = true;
for( ;; ) {
/* Scan GPIO inputs, generating key-down and key-up events. */
ScanInputPins(screenOn);
/* Blank screen after idle timeout. Unblank when no longer idle. */
if( optTimeout != 0 ) {
int idle = IdleTime();
if( screenOn && idle >= optTimeout ) {
system("vcgencmd display_power 0");
screenOn = false;
}
else if( !screenOn && idle < optTimeout ) {
system("vcgencmd display_power 1");
screenOn = true;
}
}
/* Sleep for approximately 20ms between scans to minimize CPU usage and
provide debouncing, yet still give sufficiently fast response. */
usleep(20000);
}
return( 0 );
}