Annotation of embedtools/src/butz.c, revision 1.2.2.1
1.2 misho 1: #include "global.h"
2:
3:
4: cfg_root_t cfg;
5: sched_root_task_t *root;
6: int Kill, gpio, flg, maxpins, defact, resbut, led = -1;
7: extern char compiled[], compiledby[], compilehost[];
8: char szCfgName[PATH_MAX] = BUTZ_CFG;
9: char szDevName[PATH_MAX] = _PATH_DEVGPIOC"0";
10:
11: static void
12: Usage()
13: {
14: printf( " -= Butz =- Service for board buttons management\n"
15: "=== %s === %s@%s ===\n\n"
16: " Syntax: butz [options] [set_value]\n"
17: "\n"
18: "\t-c <cfgfile>\tConfig file [default: /etc/butz.conf]\n"
19: "\t-d <devname>\tGPIO control device [default: /dev/gpioc]\n"
20: "\n", compiled, compiledby, compilehost);
21: }
22:
23: static int
24: prepareGPIO()
25: {
26: const char *str;
27: struct gpio_pin pin;
28: struct gpio_req req;
29:
30: str = cfg_getAttribute(&cfg, "reset", "default_after");
31: if (str)
32: defact = strtol(str, NULL, 0);
33: str = cfg_getAttribute(&cfg, "reset", "gpio_led_ping");
34: if (str)
35: led = strtol(str, NULL, 0);
36: str = cfg_getAttribute(&cfg, "reset", "gpio_pin");
37: if (!str || maxpins < (resbut = strtol(str, NULL, 0))) {
38: EERROR(EINVAL, "Reset button pin not defined or wrong number!");
39: return -1;
40: }
41:
42: /* switch button pin into input state */
43: pin.gp_pin = resbut;
44: pin.gp_flags = GPIO_PIN_INPUT;
45: if (ioctl(gpio, GPIOSETCONFIG, &pin) == -1)
46: return -1;
47: /* toggle led pin */
48: if (led != -1) {
49: req.gp_pin = led;
50: if (ioctl(gpio, GPIOTOGGLE, &req) == -1) {
51: ESYSERR(0);
52: return -1;
53: }
54: }
55:
56: return 0;
57: }
58:
59: static void *
60: sigHandler(sched_task_t *task)
61: {
62: switch (TASK_VAL(task)) {
63: case SIGHUP:
64: cfgUnloadConfig(&cfg);
65: if (cfgLoadConfig(szCfgName, &cfg)) {
66: ELIBERR(cfg);
67: Kill++;
68: }
69: if (prepareGPIO())
70: Kill++;
71: break;
72: case SIGTERM:
73: Kill++;
74: break;
75: default:
76: EERROR(EINVAL, "Undefined signal %lu!", TASK_VAL(task));
77: break;
78: }
1.2.2.1 ! misho 79:
! 80: schedSignalSelf(task);
1.2 misho 81: taskExit(task, NULL);
82: }
83:
84: static void *
85: execReset(sched_task_t *task)
86: {
87: pid_t pid;
88: const char *str;
89:
90: str = cfg_getAttribute(&cfg, "reset", "click");
91: if (!str)
92: taskExit(task, NULL);
93:
94: if ((pid = fork()) == -1)
95: ESYSERR(0);
96: else if (!pid) {
97: execl(str, str, "click", NULL);
98: ESYSERR(0);
99: _exit(127);
100: }
101:
102: flg ^= flg;
103: taskExit(task, NULL);
104: }
105:
106: static void *
107: execDefault(sched_task_t *task)
108: {
109: pid_t pid;
110: const char *str;
111:
112: str = cfg_getAttribute(&cfg, "reset", "default");
113: if (!str)
114: taskExit(task, NULL);
115:
116: if ((pid = fork()) == -1)
117: ESYSERR(0);
118: else if (!pid) {
119: execl(str, str, "default", NULL);
120: ESYSERR(0);
121: _exit(127);
122: }
123:
124: flg ^= flg;
125: taskExit(task, NULL);
126: }
127:
128: static void *
129: butReset(sched_task_t *task)
130: {
131: struct timespec ts = { 1, 0 };
132: struct gpio_req req;
133:
134: /* check reset button */
135: req.gp_pin = resbut;
136: if (ioctl(gpio, GPIOGET, &req) == -1) {
137: ESYSERR(0);
138: goto end;
139: }
140: /* switch on */
141: if (flg != -1 && !req.gp_value)
142: if (++flg == 1)
143: schedSuspend(TASK_ROOT(task), execReset, NULL, flg, NULL, 0);
144: if (defact && flg >= defact) {
145: schedCancelby(TASK_ROOT(task), taskSUSPEND, CRITERIA_CALL, execReset, NULL);
146: schedEvent(TASK_ROOT(task), execDefault, NULL, flg, NULL, 0);
147: flg = -1;
148: goto end;
149: }
150: if (flg > 0 && req.gp_value)
151: schedResumeby(TASK_ROOT(task), CRITERIA_ID, (void*) 1);
152:
153: /* toggle led pin */
154: if (flg != -1 && led != -1) {
155: req.gp_pin = led;
156: if (ioctl(gpio, GPIOTOGGLE, &req) == -1)
157: ESYSERR(0);
158: }
159: end:
160: schedTimer(TASK_ROOT(task), TASK_FUNC(task), TASK_ARG(task),
161: ts, TASK_DATA(task), TASK_DATLEN(task));
162: taskExit(task, NULL);
163: }
164:
165:
166: int
167: main(int argc, char **argv)
168: {
169: char ch;
170: pid_t pid;
171: struct timespec ts = { 1, 0 };
172:
173: while ((ch = getopt(argc, argv, "hc:d:")) != -1)
174: switch (ch) {
175: case 'd':
176: strlcpy(szDevName, optarg, sizeof szDevName);
177: break;
178: case 'c':
179: strlcpy(szCfgName, optarg, sizeof szCfgName);
180: break;
181: case 'h':
182: default:
183: Usage();
184: return 1;
185: }
186: argc -= optind;
187: argv += optind;
188:
189: switch ((pid = fork())) {
190: case -1:
191: printf("Error:: failed fork() #%d - %s\n", errno, strerror(errno));
192: return 1;
193: case 0:
194: setsid();
195: chdir("/");
196:
197: gpio = open(_PATH_DEVNULL, O_RDWR);
198: if (gpio > 2) {
199: dup2(gpio, STDIN_FILENO);
200: dup2(gpio, STDOUT_FILENO);
201: dup2(gpio, STDERR_FILENO);
202: close(gpio);
203: }
204: break;
205: default:
206: return 0;
207: }
208:
209: openlog("butz", LOG_PID | LOG_CONS, LOG_DAEMON);
210: gpio = open(szDevName, O_RDONLY);
211: if (gpio == -1) {
212: ESYSERR(0);
213: return 1;
214: }
215: if (ioctl(gpio, GPIOMAXPIN, &maxpins) == -1) {
216: ESYSERR(0);
217: return 1;
218: }
219:
220: if (cfgLoadConfig(szCfgName, &cfg)) {
221: ELIBERR(cfg);
222: close(gpio);
223: return 1;
224: }
225: if (prepareGPIO()) {
226: close(gpio);
227: return 1;
228: }
229: root = schedBegin();
230: if (!root) {
231: ELIBERR(sched);
232: close(gpio);
233: return 1;
234: }
235:
236: schedSignal(root, sigHandler, NULL, SIGHUP, NULL, 0);
237: schedSignal(root, sigHandler, NULL, SIGTERM, NULL, 0);
238: schedTimer(root, butReset, NULL, ts, NULL, 0);
239:
240: schedRun(root, &Kill);
241: schedEnd(&root);
242: cfgUnloadConfig(&cfg);
243: close(gpio);
244: closelog();
245: return 0;
246: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>