/* * Monitor the presence of a charger and perform critical frequent steps * such as running the battery voltage filter. */ static inline void power_thread_step(void) { /* If the power off timeout expires, the main thread has failed to shut down the system, and we need to force a power off */ if (shutdown_timeout) { shutdown_timeout -= POWER_THREAD_STEP_TICKS; if (shutdown_timeout <= 0) power_off(); } #ifdef HAVE_RTC_ALARM power_thread_rtc_process(); #endif /* * Do a digital exponential filter. We don't sample the battery if * the disk is spinning unless we are in USB mode (the disk will most * likely always be spinning in USB mode) or charging. */ if (!storage_disk_is_active() || usb_inserted() #if CONFIG_CHARGING >= CHARGING_MONITOR || charger_input_state == CHARGER #endif ) { avgbat += battery_adc_voltage() - avgbat / BATT_AVE_SAMPLES; /* * battery_millivolts is the millivolt-scaled filtered battery value. */ battery_millivolts = avgbat / BATT_AVE_SAMPLES; /* update battery status every time an update is available */ battery_status_update(); } else if (battery_percent < 8) { /* * If battery is low, observe voltage during disk activity. * Shut down if voltage drops below shutoff level and we are not * using NiMH or Alkaline batteries. */ battery_millivolts = (battery_adc_voltage() + battery_millivolts + 1) / 2; /* update battery status every time an update is available */ battery_status_update(); if (!shutdown_timeout && query_force_shutdown()) { sys_poweroff(); } else { avgbat += battery_millivolts - avgbat / BATT_AVE_SAMPLES; } } } /* power_thread_step */
void buffering_thread(void) { bool filling = false; struct queue_event ev; while (true) { if (!filling) { cancel_cpu_boost(); } queue_wait_w_tmo(&buffering_queue, &ev, filling ? 5 : HZ/2); switch (ev.id) { case Q_START_FILL: LOGFQUEUE("buffering < Q_START_FILL %d", (int)ev.data); /* Call buffer callbacks here because this is one of two ways * to begin a full buffer fill */ send_event(BUFFER_EVENT_BUFFER_LOW, 0); shrink_buffer(); queue_reply(&buffering_queue, 1); filling |= buffer_handle((int)ev.data); break; case Q_BUFFER_HANDLE: LOGFQUEUE("buffering < Q_BUFFER_HANDLE %d", (int)ev.data); queue_reply(&buffering_queue, 1); buffer_handle((int)ev.data); break; case Q_RESET_HANDLE: LOGFQUEUE("buffering < Q_RESET_HANDLE %d", (int)ev.data); queue_reply(&buffering_queue, 1); reset_handle((int)ev.data); break; case Q_CLOSE_HANDLE: LOGFQUEUE("buffering < Q_CLOSE_HANDLE %d", (int)ev.data); queue_reply(&buffering_queue, close_handle((int)ev.data)); break; case Q_HANDLE_ADDED: LOGFQUEUE("buffering < Q_HANDLE_ADDED %d", (int)ev.data); /* A handle was added: the disk is spinning, so we can fill */ filling = true; break; case Q_BASE_HANDLE: LOGFQUEUE("buffering < Q_BASE_HANDLE %d", (int)ev.data); base_handle_id = (int)ev.data; break; #ifndef SIMULATOR case SYS_USB_CONNECTED: LOGFQUEUE("buffering < SYS_USB_CONNECTED"); usb_acknowledge(SYS_USB_CONNECTED_ACK); usb_wait_for_disconnect(&buffering_queue); break; #endif case SYS_TIMEOUT: LOGFQUEUE_SYS_TIMEOUT("buffering < SYS_TIMEOUT"); break; } update_data_counters(); /* If the buffer is low, call the callbacks to get new data */ if (num_handles > 0 && data_counters.useful <= conf_watermark) send_event(BUFFER_EVENT_BUFFER_LOW, 0); #if 0 /* TODO: This needs to be fixed to use the idle callback, disable it * for simplicity until its done right */ #if MEM > 8 /* If the disk is spinning, take advantage by filling the buffer */ else if (storage_disk_is_active() && queue_empty(&buffering_queue)) { if (num_handles > 0 && data_counters.useful <= high_watermark) send_event(BUFFER_EVENT_BUFFER_LOW, 0); if (data_counters.remaining > 0 && BUF_USED <= high_watermark) { /* This is a new fill, shrink the buffer up first */ if (!filling) shrink_buffer(); filling = fill_buffer(); update_data_counters(); } } #endif #endif if (queue_empty(&buffering_queue)) { if (filling) { if (data_counters.remaining > 0 && BUF_USED < buffer_len) filling = fill_buffer(); else if (data_counters.remaining == 0) filling = false; } else if (ev.id == SYS_TIMEOUT) { if (data_counters.remaining > 0 && data_counters.useful <= conf_watermark) { shrink_buffer(); filling = fill_buffer(); } } } } }