OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * configurable RSSI LED control daemon for OpenWrt |
||
3 | * (c) 2012 Allnet GmbH, Daniel Golle <dgolle@allnet.de> |
||
4 | * |
||
5 | * This program is free software; you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU General Public License as published by |
||
7 | * the Free Software Foundation; either version 2 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * |
||
10 | * This program is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
13 | * General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU General Public License |
||
16 | * along with this program; if not, write to the Free Software |
||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
18 | * |
||
19 | * The author may be reached as dgolle@allnet.de, or |
||
20 | * ALLNET GmbH |
||
21 | * Maistr. 2 |
||
22 | * D-82110 Germering |
||
23 | * Germany |
||
24 | * |
||
25 | */ |
||
26 | |||
27 | #include <stdio.h> |
||
28 | #include <stdlib.h> |
||
29 | #include <sys/stat.h> |
||
30 | #include <fcntl.h> |
||
31 | #include <signal.h> |
||
32 | #include <unistd.h> |
||
33 | #include <syslog.h> |
||
34 | |||
35 | #include "iwinfo.h" |
||
36 | |||
37 | #define RUN_DIR "/var/run" |
||
38 | #define LEDS_BASEPATH "/sys/class/leds/" |
||
39 | #define BACKEND_RETRY_DELAY 500000 |
||
40 | |||
41 | char *ifname; |
||
42 | int qual_max; |
||
43 | |||
44 | struct led { |
||
45 | char *sysfspath; |
||
46 | FILE *controlfd; |
||
47 | unsigned char state; |
||
48 | }; |
||
49 | |||
50 | typedef struct rule rule_t; |
||
51 | struct rule { |
||
52 | struct led *led; |
||
53 | int minq; |
||
54 | int maxq; |
||
55 | int boffset; |
||
56 | int bfactor; |
||
57 | rule_t *next; |
||
58 | }; |
||
59 | |||
60 | void log_rules(rule_t *rules) |
||
61 | { |
||
62 | rule_t *rule = rules; |
||
63 | while (rule) |
||
64 | { |
||
65 | syslog(LOG_INFO, " %s r: %d..%d, o: %d, f: %d\n", |
||
66 | rule->led->sysfspath, |
||
67 | rule->minq, rule->maxq, |
||
68 | rule->boffset, rule->bfactor); |
||
69 | rule = rule->next; |
||
70 | } |
||
71 | } |
||
72 | |||
73 | int set_led(struct led *led, unsigned char value) |
||
74 | { |
||
75 | char buf[8]; |
||
76 | |||
77 | if ( ! led ) |
||
78 | return -1; |
||
79 | |||
80 | if ( ! led->controlfd ) |
||
81 | return -1; |
||
82 | |||
83 | if ( led->state == value ) |
||
84 | return 0; |
||
85 | |||
86 | snprintf(buf, 8, "%d", value); |
||
87 | |||
88 | rewind(led->controlfd); |
||
89 | |||
90 | if ( ! fwrite(buf, sizeof(char), strlen(buf), led->controlfd) ) |
||
91 | return -2; |
||
92 | |||
93 | fflush(led->controlfd); |
||
94 | led->state=value; |
||
95 | |||
96 | return 0; |
||
97 | } |
||
98 | |||
99 | int init_led(struct led **led, char *ledname) |
||
100 | { |
||
101 | struct led *newled; |
||
102 | struct stat statbuffer; |
||
103 | int status; |
||
104 | char *bp; |
||
105 | FILE *bfp; |
||
106 | |||
107 | bp = calloc(sizeof(char), strlen(ledname) + strlen(LEDS_BASEPATH) + 12); |
||
108 | if ( ! bp ) |
||
109 | goto return_error; |
||
110 | |||
111 | sprintf(bp, "%s%s/brightness", LEDS_BASEPATH, ledname); |
||
112 | |||
113 | status = stat(bp, &statbuffer); |
||
114 | if ( status ) |
||
115 | goto cleanup_fname; |
||
116 | |||
117 | bfp = fopen( bp, "w" ); |
||
118 | if ( !bfp ) |
||
119 | goto cleanup_fname; |
||
120 | |||
121 | if ( ferror(bfp) ) |
||
122 | goto cleanup_fp; |
||
123 | |||
124 | /* sysfs path exists and, allocate LED struct */ |
||
125 | newled = calloc(sizeof(struct led),1); |
||
126 | if ( !newled ) |
||
127 | goto cleanup_fp; |
||
128 | |||
129 | newled->sysfspath = bp; |
||
130 | newled->controlfd = bfp; |
||
131 | |||
132 | *led = newled; |
||
133 | |||
134 | if ( set_led(newled, 255) ) |
||
135 | goto cleanup_fp; |
||
136 | |||
137 | if ( set_led(newled, 0) ) |
||
138 | goto cleanup_fp; |
||
139 | |||
140 | return 0; |
||
141 | |||
142 | cleanup_fp: |
||
143 | fclose(bfp); |
||
144 | cleanup_fname: |
||
145 | free(bp); |
||
146 | return_error: |
||
147 | syslog(LOG_CRIT, "can't open LED %s\n", ledname); |
||
148 | *led = NULL; |
||
149 | return -1; |
||
150 | } |
||
151 | |||
152 | void close_led(struct led **led) |
||
153 | { |
||
154 | fclose((*led)->controlfd); |
||
155 | free((*led)->sysfspath); |
||
156 | free((*led)); |
||
157 | (*led)=NULL; |
||
158 | } |
||
159 | |||
160 | |||
161 | int quality(const struct iwinfo_ops *iw, const char *ifname) |
||
162 | { |
||
163 | int qual; |
||
164 | |||
165 | if ( ! iw ) return -1; |
||
166 | |||
167 | if (qual_max < 1) |
||
168 | if (iw->quality_max(ifname, &qual_max)) |
||
169 | return -1; |
||
170 | |||
171 | if (iw->quality(ifname, &qual)) |
||
172 | return -1; |
||
173 | |||
174 | return ( qual * 100 ) / qual_max ; |
||
175 | } |
||
176 | |||
177 | int open_backend(const struct iwinfo_ops **iw, const char *ifname) |
||
178 | { |
||
179 | *iw = iwinfo_backend(ifname); |
||
180 | |||
181 | if (!(*iw)) |
||
182 | return 1; |
||
183 | |||
184 | return 0; |
||
185 | } |
||
186 | |||
187 | void update_leds(rule_t *rules, int q) |
||
188 | { |
||
189 | rule_t *rule = rules; |
||
190 | while (rule) |
||
191 | { |
||
192 | int b; |
||
193 | /* offset and factore correction according to rule */ |
||
194 | b = ( q + rule->boffset ) * rule->bfactor; |
||
195 | if ( b < 0 ) |
||
196 | b=0; |
||
197 | if ( b > 255 ) |
||
198 | b=255; |
||
199 | |||
200 | if ( q >= rule->minq && q <= rule->maxq ) |
||
201 | set_led(rule->led, (unsigned char)b); |
||
202 | else |
||
203 | set_led(rule->led, 0); |
||
204 | |||
205 | rule = rule->next; |
||
206 | } |
||
207 | } |
||
208 | |||
209 | int main(int argc, char **argv) |
||
210 | { |
||
211 | int i,q,q0,r,s; |
||
212 | const struct iwinfo_ops *iw = NULL; |
||
213 | rule_t *headrule = NULL, *currentrule = NULL; |
||
214 | |||
215 | if (argc < 9 || ( (argc-4) % 5 != 0 ) ) |
||
216 | { |
||
217 | printf("syntax: %s (ifname) (refresh) (threshold) (rule) [rule] ...\n", argv[0]); |
||
218 | printf(" rule: (sysfs-name) (minq) (maxq) (offset) (factore)\n"); |
||
219 | return 1; |
||
220 | } |
||
221 | |||
222 | ifname = argv[1]; |
||
223 | |||
224 | /* refresh interval */ |
||
225 | if ( sscanf(argv[2], "%d", &r) != 1 ) |
||
226 | return 1; |
||
227 | |||
228 | /* sustain threshold */ |
||
229 | if ( sscanf(argv[3], "%d", &s) != 1 ) |
||
230 | return 1; |
||
231 | |||
232 | openlog("rssileds", LOG_PID, LOG_DAEMON); |
||
233 | syslog(LOG_INFO, "monitoring %s, refresh rate %d, threshold %d\n", ifname, r, s); |
||
234 | |||
235 | currentrule = headrule; |
||
236 | for (i=4; i<argc; i=i+5) { |
||
237 | if (! currentrule) |
||
238 | { |
||
239 | /* first element in the list */ |
||
240 | currentrule = calloc(sizeof(rule_t),1); |
||
241 | headrule = currentrule; |
||
242 | } |
||
243 | else |
||
244 | { |
||
245 | /* follow-up element */ |
||
246 | currentrule->next = calloc(sizeof(rule_t),1); |
||
247 | currentrule = currentrule->next; |
||
248 | } |
||
249 | |||
250 | if ( init_led(&(currentrule->led), argv[i]) ) |
||
251 | return 1; |
||
252 | |||
253 | if ( sscanf(argv[i+1], "%d", &(currentrule->minq)) != 1 ) |
||
254 | return 1; |
||
255 | |||
256 | if ( sscanf(argv[i+2], "%d", &(currentrule->maxq)) != 1 ) |
||
257 | return 1; |
||
258 | |||
259 | if ( sscanf(argv[i+3], "%d", &(currentrule->boffset)) != 1 ) |
||
260 | return 1; |
||
261 | |||
262 | if ( sscanf(argv[i+4], "%d", &(currentrule->bfactor)) != 1 ) |
||
263 | return 1; |
||
264 | } |
||
265 | log_rules(headrule); |
||
266 | |||
267 | q0 = -1; |
||
268 | do { |
||
269 | q = quality(iw, ifname); |
||
270 | if ( q < q0 - s || q > q0 + s ) { |
||
271 | update_leds(headrule, q); |
||
272 | q0=q; |
||
273 | }; |
||
274 | // re-open backend... |
||
275 | if ( q == -1 && q0 == -1 ) { |
||
276 | if (iw) { |
||
277 | iwinfo_finish(); |
||
278 | iw=NULL; |
||
279 | usleep(BACKEND_RETRY_DELAY); |
||
280 | } |
||
281 | while (open_backend(&iw, ifname)) |
||
282 | usleep(BACKEND_RETRY_DELAY); |
||
283 | } |
||
284 | usleep(r); |
||
285 | } while(1); |
||
286 | |||
287 | iwinfo_finish(); |
||
288 | |||
289 | return 0; |
||
290 | } |