Attempt to count descramblers used properly
[oscam.git] / module-led.c
blobc5354aa2fc45d94cf1b997bbee497ce3fe61c180
1 #define MODULE_LOG_PREFIX "led"
3 #include "globals.h"
5 #ifdef LEDSUPPORT
7 #include "module-led.h"
8 #include "oscam-string.h"
9 #include "oscam-time.h"
11 #if defined(__arm__)
12 struct s_arm_led
14 int32_t led;
15 int32_t action;
16 time_t start_time;
19 static pthread_t arm_led_thread;
20 static LLIST *arm_led_actions;
22 #define ARM_LED_TYPES 3
23 #define ARM_LED_FILES 4
25 struct arm_leds
27 char *machine;
28 struct led_file
30 uint8_t id;
31 char *file;
32 } leds[ARM_LED_FILES];
35 static const struct arm_leds arm_leds[ARM_LED_TYPES] =
38 "nslu2", {
39 { LED1A, "red:status" },
40 { LED1B, "green:ready" },
41 { LED2, "green:disk-1" },
42 { LED3, "green:disk-2" }
46 "dockstar", {
47 { LED1A, "orange:misc" },
48 { LED1B, "green:health" },
49 { LED2, "green:health" },
50 { LED3, "orange:misc" }
54 "wrt350nv2", {
55 { LED1A, "orange:power" },
56 { LED1B, "green:power" },
57 { LED2, "green:wireless" },
58 { LED3, "green:security" }
63 static int32_t arm_init_led_file(uint8_t led_type, uint8_t led_no, char *buf, int32_t buflen)
65 uint8_t i;
66 if(led_type >= ARM_LED_TYPES) { return 0; }
67 if(led_no >= ARM_LED_FILES) { return 0; }
68 for(i = 0; i < ARM_LED_FILES; i++)
70 if(arm_leds[led_type].leds[i].id == led_no)
72 return snprintf(buf, buflen, "/sys/class/leds/%s:%s/brightness",
73 arm_leds[led_type].machine, arm_leds[led_type].leds[i].file);
76 return 0;
79 #define LED_TYPE_UNKNOWN 0xff
80 static uint8_t arm_led_type = LED_TYPE_UNKNOWN;
82 static void arm_detect_led_type(void)
84 uint8_t i;
85 char led_file[256];
86 for(i = 0; i < ARM_LED_TYPES; i++)
88 if(!arm_init_led_file(i, 0, led_file, sizeof(led_file)))
89 { break; }
90 if(access(led_file, W_OK) == 0)
92 arm_led_type = i;
93 cs_log("LED support for %s is activated.", arm_leds[arm_led_type].machine);
94 break;
97 if(arm_led_type == LED_TYPE_UNKNOWN)
98 { cs_log("LED support is not active. Can't detect machine type."); }
101 static void arm_switch_led_from_thread(int32_t led, int32_t action)
103 if(action < 2) // only LED_ON and LED_OFF
105 char led_file[256];
106 if(!arm_init_led_file(arm_led_type, led, led_file, sizeof(led_file)))
107 { return; }
108 FILE *f = fopen(led_file, "w");
109 if(!f)
110 { return; }
111 fprintf(f, "%d", action);
112 fclose(f);
114 else // LED Macros
116 switch(action)
118 case LED_DEFAULT:
119 arm_switch_led_from_thread(LED1A, LED_OFF);
120 arm_switch_led_from_thread(LED1B, LED_OFF);
121 arm_switch_led_from_thread(LED2, LED_ON);
122 arm_switch_led_from_thread(LED3, LED_OFF);
123 break;
124 case LED_BLINK_OFF:
125 arm_switch_led_from_thread(led, LED_OFF);
126 cs_sleepms(100);
127 arm_switch_led_from_thread(led, LED_ON);
128 break;
129 case LED_BLINK_ON:
130 arm_switch_led_from_thread(led, LED_ON);
131 cs_sleepms(300);
132 arm_switch_led_from_thread(led, LED_OFF);
133 break;
138 static void *arm_led_thread_main(void *UNUSED(thread_data))
140 uint8_t running = 1;
141 set_thread_name(__func__);
142 while(running)
144 LL_ITER iter = ll_iter_create(arm_led_actions);
145 struct s_arm_led *arm_led;
146 while((arm_led = ll_iter_next(&iter)))
148 int32_t led, action;
149 time_t now, start;
150 led = arm_led->led;
151 action = arm_led->action;
152 now = time((time_t)0);
153 start = arm_led->start_time;
154 ll_iter_remove_data(&iter);
155 if(action == LED_STOP_THREAD)
157 running = 0;
158 break;
160 if(now - start < ARM_LED_TIMEOUT)
162 arm_switch_led_from_thread(led, action);
165 if(running)
167 sleep(60);
170 ll_clear_data(arm_led_actions);
171 pthread_exit(NULL);
172 return NULL;
175 static void arm_led_start_thread(void)
177 arm_detect_led_type();
178 if(!cfg.enableled || arm_led_type == LED_TYPE_UNKNOWN)
179 { return; }
180 // call this after signal handling is done
181 if(!arm_led_actions)
183 arm_led_actions = ll_create("arm_led_actions");
186 start_thread("arm led", arm_led_thread_main, NULL, &arm_led_thread, 1, 1);
189 static void arm_led(int32_t led, int32_t action)
191 struct s_arm_led *data;
192 if(!cfg.enableled || arm_led_type == LED_TYPE_UNKNOWN)
193 { return; }
194 if(!arm_led_actions)
196 arm_led_actions = ll_create("arm_led_actions");
198 if(cs_malloc(&data, sizeof(struct s_arm_led)))
200 data->start_time = time((time_t)0);
201 data->led = led;
202 data->action = action;
203 ll_append(arm_led_actions, (void *)data);
205 if(arm_led_thread)
207 // arm_led_thread_main is not started at oscam startup
208 // when first arm_led calls happen
209 pthread_kill(arm_led_thread, OSCAM_SIGNAL_WAKEUP);
213 static void arm_led_stop_thread(void)
215 if(!cfg.enableled || arm_led_type == LED_TYPE_UNKNOWN)
216 { return; }
217 arm_led(0, LED_STOP_THREAD);
219 #else
220 static inline void arm_led_start_thread(void) { }
221 static inline void arm_led_stop_thread(void) { }
222 static inline void arm_led(int32_t UNUSED(led), int32_t UNUSED(action)) { }
223 #endif
226 #ifdef QBOXHD
227 static void qboxhd_led_blink(int32_t color, int32_t duration)
229 int32_t f;
230 if(cfg.enableled != 2)
231 { return; }
232 // try QboxHD-MINI first
233 if((f = open(QBOXHDMINI_LED_DEVICE, O_RDWR | O_NONBLOCK)) > -1)
235 qboxhdmini_led_color_struct qbminiled;
236 uint32_t qboxhdmini_color = 0x000000;
237 if(color != QBOXHD_LED_COLOR_OFF)
239 switch(color)
241 case QBOXHD_LED_COLOR_RED:
242 qboxhdmini_color = QBOXHDMINI_LED_COLOR_RED;
243 break;
244 case QBOXHD_LED_COLOR_GREEN:
245 qboxhdmini_color = QBOXHDMINI_LED_COLOR_GREEN;
246 break;
247 case QBOXHD_LED_COLOR_BLUE:
248 qboxhdmini_color = QBOXHDMINI_LED_COLOR_BLUE;
249 break;
250 case QBOXHD_LED_COLOR_YELLOW:
251 qboxhdmini_color = QBOXHDMINI_LED_COLOR_YELLOW;
252 break;
253 case QBOXHD_LED_COLOR_MAGENTA:
254 qboxhdmini_color = QBOXHDMINI_LED_COLOR_MAGENTA;
255 break;
257 // set LED on with color
258 qbminiled.red = (uint8_t)((qboxhdmini_color & 0xFF0000) >> 16); // R
259 qbminiled.green = (uint8_t)((qboxhdmini_color & 0x00FF00) >> 8); // G
260 qbminiled.blue = (uint8_t)(qboxhdmini_color & 0x0000FF); // B
261 ioctl(f, QBOXHDMINI_IOSET_RGB, &qbminiled);
262 cs_sleepms(duration);
264 // set LED off
265 qbminiled.red = 0;
266 qbminiled.green = 0;
267 qbminiled.blue = 0;
268 ioctl(f, QBOXHDMINI_IOSET_RGB, &qbminiled);
269 close(f);
271 else if((f = open(QBOXHD_LED_DEVICE, O_RDWR | O_NONBLOCK)) > -1)
273 qboxhd_led_color_struct qbled;
274 if(color != QBOXHD_LED_COLOR_OFF)
276 // set LED on with color
277 qbled.H = color;
278 qbled.S = 99;
279 qbled.V = 99;
280 ioctl(f, QBOXHD_SET_LED_ALL_PANEL_COLOR, &qbled);
281 cs_sleepms(duration);
283 // set LED off
284 qbled.H = 0;
285 qbled.S = 0;
286 qbled.V = 0;
287 ioctl(f, QBOXHD_SET_LED_ALL_PANEL_COLOR, &qbled);
288 close(f);
291 #else
292 static inline void qboxhd_led_blink(int32_t UNUSED(color), int32_t UNUSED(duration)) { }
293 #endif
295 void led_status_stopping(void)
297 if(cfg.enableled == 1)
299 arm_led(LED1B, LED_OFF);
300 arm_led(LED2, LED_OFF);
301 arm_led(LED3, LED_OFF);
302 arm_led(LED1A, LED_ON);
304 if(cfg.enableled == 2)
306 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW, QBOXHD_LED_BLINK_FAST);
307 qboxhd_led_blink(QBOXHD_LED_COLOR_RED, QBOXHD_LED_BLINK_FAST);
308 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_FAST);
309 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE, QBOXHD_LED_BLINK_FAST);
310 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA, QBOXHD_LED_BLINK_FAST);
314 void led_status_cw_not_found(ECM_REQUEST *er)
316 if(!er->rc)
317 { arm_led(LED2, LED_BLINK_OFF); }
318 if(er->rc < E_NOTFOUND)
320 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_MEDIUM);
322 else if(er->rc <= E_STOPPED)
324 qboxhd_led_blink(QBOXHD_LED_COLOR_RED, QBOXHD_LED_BLINK_MEDIUM);
328 void led_status_default(void)
330 arm_led(LED1A, LED_DEFAULT);
331 arm_led(LED1A, LED_ON);
334 void led_status_starting(void)
336 arm_led(LED1A, LED_OFF);
337 arm_led(LED1B, LED_ON);
338 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW, QBOXHD_LED_BLINK_FAST);
339 qboxhd_led_blink(QBOXHD_LED_COLOR_RED, QBOXHD_LED_BLINK_FAST);
340 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_FAST);
341 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE, QBOXHD_LED_BLINK_FAST);
342 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA, QBOXHD_LED_BLINK_FAST);
345 void led_status_card_activation_error(void)
347 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA, QBOXHD_LED_BLINK_MEDIUM);
350 void led_status_found_cardsystem(void)
352 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW, QBOXHD_LED_BLINK_MEDIUM);
353 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_MEDIUM);
354 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW, QBOXHD_LED_BLINK_MEDIUM);
355 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_MEDIUM);
358 void led_status_unsupported_card_system(void)
360 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA, QBOXHD_LED_BLINK_MEDIUM);
363 void led_status_card_detected(void)
365 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW, QBOXHD_LED_BLINK_SLOW);
368 void led_status_card_ejected(void)
370 qboxhd_led_blink(QBOXHD_LED_COLOR_RED, QBOXHD_LED_BLINK_SLOW);
373 void led_status_emm_ok(void)
375 arm_led(LED3, LED_BLINK_ON);
376 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE, QBOXHD_LED_BLINK_MEDIUM);
379 void led_init(void)
381 arm_led_start_thread();
384 void led_stop(void)
386 arm_led_stop_thread();
389 #endif