2 * configurable RSSI LED control daemon for OpenWrt
3 * (c) 2012 Allnet GmbH, Daniel Golle <dgolle@allnet.de>
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.
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.
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
19 * The author may be reached as dgolle@allnet.de, or
37 #define RUN_DIR "/var/run"
38 #define LEDS_BASEPATH "/sys/class/leds/"
39 #define BACKEND_RETRY_DELAY 500000
50 typedef struct rule rule_t
;
60 void log_rules(rule_t
*rules
)
65 syslog(LOG_INFO
, " %s r: %d..%d, o: %d, f: %d\n",
67 rule
->minq
, rule
->maxq
,
68 rule
->boffset
, rule
->bfactor
);
73 int init_led(struct led
**led
, char *ledname
)
76 struct stat statbuffer
;
81 bp
= calloc(sizeof(char), strlen(ledname
) + strlen(LEDS_BASEPATH
) + 12);
85 sprintf(bp
, "%s%s/brightness", LEDS_BASEPATH
, ledname
);
87 status
= stat(bp
, &statbuffer
);
91 bfp
= fopen( bp
, "w" );
98 /* sysfs path exists and, allocate LED struct */
99 newled
= calloc(sizeof(struct led
),1);
103 newled
->sysfspath
= bp
;
104 newled
->controlfd
= bfp
;
114 syslog(LOG_CRIT
, "can't open LED %s\n", ledname
);
119 void close_led(struct led
**led
)
121 fclose((*led
)->controlfd
);
122 free((*led
)->sysfspath
);
127 int set_led(struct led
*led
, unsigned char value
)
134 if ( ! led
->controlfd
)
137 snprintf(buf
, 8, "%d", value
);
139 rewind(led
->controlfd
);
141 if ( ! fwrite(buf
, sizeof(char), strlen(buf
), led
->controlfd
) )
144 fflush(led
->controlfd
);
151 int quality(const struct iwinfo_ops
*iw
, const char *ifname
)
155 if ( ! iw
) return -1;
158 if (iw
->quality_max(ifname
, &qual_max
))
161 if (iw
->quality(ifname
, &qual
))
164 return ( qual
* 100 ) / qual_max
;
167 int open_backend(const struct iwinfo_ops
**iw
, const char *ifname
)
169 *iw
= iwinfo_backend(ifname
);
177 void update_leds(rule_t
*rules
, int q
)
179 rule_t
*rule
= rules
;
183 /* offset and factore correction according to rule */
184 b
= ( q
+ rule
->boffset
) * rule
->bfactor
;
190 if ( q
>= rule
->minq
&& q
<= rule
->maxq
)
191 set_led(rule
->led
, (unsigned char)b
);
193 set_led(rule
->led
, 0);
199 int main(int argc
, char **argv
)
202 const struct iwinfo_ops
*iw
= NULL
;
203 rule_t
*headrule
= NULL
, *currentrule
= NULL
;
205 if (argc
< 9 || ( (argc
-4) % 5 != 0 ) )
207 printf("syntax: %s (ifname) (refresh) (threshold) (rule) [rule] ...\n", argv
[0]);
208 printf(" rule: (sysfs-name) (minq) (maxq) (offset) (factore)\n");
214 /* refresh interval */
215 if ( sscanf(argv
[2], "%d", &r
) != 1 )
218 /* sustain threshold */
219 if ( sscanf(argv
[3], "%d", &s
) != 1 )
222 openlog("rssileds", LOG_PID
, LOG_DAEMON
);
223 syslog(LOG_INFO
, "monitoring %s, refresh rate %d, threshold %d\n", ifname
, r
, s
);
225 currentrule
= headrule
;
226 for (i
=4; i
<argc
; i
=i
+5) {
229 /* first element in the list */
230 currentrule
= calloc(sizeof(rule_t
),1);
231 headrule
= currentrule
;
235 /* follow-up element */
236 currentrule
->next
= calloc(sizeof(rule_t
),1);
237 currentrule
= currentrule
->next
;
240 if ( init_led(&(currentrule
->led
), argv
[i
]) )
243 if ( sscanf(argv
[i
+1], "%d", &(currentrule
->minq
)) != 1 )
246 if ( sscanf(argv
[i
+2], "%d", &(currentrule
->maxq
)) != 1 )
249 if ( sscanf(argv
[i
+3], "%d", &(currentrule
->boffset
)) != 1 )
252 if ( sscanf(argv
[i
+4], "%d", &(currentrule
->bfactor
)) != 1 )
259 q
= quality(iw
, ifname
);
260 if ( q
< q0
- s
|| q
> q0
+ s
) {
261 update_leds(headrule
, q
);
264 // re-open backend...
265 if ( q
== -1 && q0
== -1 ) {
269 usleep(BACKEND_RETRY_DELAY
);
271 while (open_backend(&iw
, ifname
))
272 usleep(BACKEND_RETRY_DELAY
);