aboutsummaryrefslogtreecommitdiffstats
path: root/tmk_core/common/backlight.c
blob: c9e8fd3fd2ddbe3fce3afd0096f13f3cfab1f2c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
Copyright 2013 Mathias Andersson <wraul@dbox.se>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "backlight.h"
#include "eeconfig.h"
#include "debug.h"

backlight_config_t backlight_config;

void backlight_init(void)
{
    /* check signature */
    if (!eeconfig_is_enabled()) {
        eeconfig_init();
    }
    backlight_config.raw = eeconfig_read_backlight();
    backlight_set(backlight_config.enable ? backlight_config.level : 0);
}

void backlight_increase(void)
{
    if(backlight_config.level < BACKLIGHT_LEVELS)
    {
        backlight_config.level++;
        backlight_config.enable = 1;
        eeconfig_update_backlight(backlight_config.raw);
    }
    dprintf("backlight increase: %u\n", backlight_config.level);
    backlight_set(backlight_config.level);
}

void backlight_decrease(void)
{
    if(backlight_config.level > 0)
    {
        backlight_config.level--;
        backlight_config.enable = !!backlight_config.level;
        eeconfig_update_backlight(backlight_config.raw);
    }
    dprintf("backlight decrease: %u\n", backlight_config.level);
    backlight_set(backlight_config.level);
}

void backlight_toggle(void)
{
    backlight_config.enable ^= 1;
    eeconfig_update_backlight(backlight_config.raw);
    dprintf("backlight toggle: %u\n", backlight_config.enable);
    backlight_set(backlight_config.enable ? backlight_config.level : 0);
}

void backlight_step(void)
{
    backlight_config.level++;
    if(backlight_config.level > BACKLIGHT_LEVELS)
    {
        backlight_config.level = 0;
    }
    backlight_config.enable = !!backlight_config.level;
    eeconfig_update_backlight(backlight_config.raw);
    dprintf("backlight step: %u\n", backlight_config.level);
    backlight_set(backlight_config.level);
}

void backlight_level(uint8_t level)
{
    backlight_config.level ^= level;
    backlight_config.enable = !!backlight_config.level;
    eeconfig_update_backlight(backlight_config.raw);
    backlight_set(backlight_config.level);
}

uint8_t get_backlight_level(void)
{
    return backlight_config.level;
}
<os.h> #include <hypervisor.h> #include <time.h> #include <mm.h> #include <types.h> #include <lib.h> #include <xmalloc.h> #include <list.h> #include <sched.h> #include <semaphore.h> #ifdef SCHED_DEBUG #define DEBUG(_f, _a...) \ printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a) #else #define DEBUG(_f, _a...) ((void)0) #endif struct thread *idle_thread = NULL; MINIOS_LIST_HEAD(exited_threads); static int threads_started; struct thread *main_thread; void inline print_runqueue(void) { struct minios_list_head *it; struct thread *th; minios_list_for_each(it, &idle_thread->thread_list) { th = minios_list_entry(it, struct thread, thread_list); printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th)); } printk("\n"); } void schedule(void) { struct thread *prev, *next, *thread; struct minios_list_head *iterator, *next_iterator; unsigned long flags; prev = current; local_irq_save(flags); if (in_callback) { printk("Must not call schedule() from a callback\n"); BUG(); } if (flags) { printk("Must not call schedule() with IRQs disabled\n"); BUG(); } do { /* Examine all threads. Find a runnable thread, but also wake up expired ones and find the time when the next timeout expires, else use 10 seconds. */ s_time_t now = NOW(); s_time_t min_wakeup_time = now + SECONDS(10); next = NULL; minios_list_for_each_safe(iterator, next_iterator, &idle_thread->thread_list) { thread = minios_list_entry(iterator, struct thread, thread_list); if (!is_runnable(thread) && thread->wakeup_time != 0LL) { if (thread->wakeup_time <= now) wake(thread); else if (thread->wakeup_time < min_wakeup_time) min_wakeup_time = thread->wakeup_time; } if(is_runnable(thread)) { next = thread; /* Put this thread on the end of the list */ minios_list_del(&thread->thread_list); minios_list_add_tail(&thread->thread_list, &idle_thread->thread_list); break; } } if (next) break; /* block until the next timeout expires, or for 10 secs, whichever comes first */ block_domain(min_wakeup_time); /* handle pending events if any */ force_evtchn_callback(); } while(1); local_irq_restore(flags); /* Interrupting the switch is equivalent to having the next thread inturrupted at the return instruction. And therefore at safe point. */ if(prev != next) switch_threads(prev, next); minios_list_for_each_safe(iterator, next_iterator, &exited_threads) { thread = minios_list_entry(iterator, struct thread, thread_list); if(thread != prev) { minios_list_del(&thread->thread_list); free_pages(thread->stack, STACK_SIZE_PAGE_ORDER); xfree(thread); } } } struct thread* create_thread(char *name, void (*function)(void *), void *data) { struct thread *thread; unsigned long flags; /* Call architecture specific setup. */ thread = arch_create_thread(name, function, data); /* Not runable, not exited, not sleeping */ thread->flags = 0; thread->wakeup_time = 0LL; #ifdef HAVE_LIBC _REENT_INIT_PTR((&thread->reent)) #endif set_runnable(thread); local_irq_save(flags); if(idle_thread != NULL) { minios_list_add_tail(&thread->thread_list, &idle_thread->thread_list); } else if(function != idle_thread_fn) { printk("BUG: Not allowed to create thread before initialising scheduler.\n"); BUG(); } local_irq_restore(flags); return thread; } #ifdef HAVE_LIBC static struct _reent callback_reent; struct _reent *__getreent(void) { struct _reent *_reent; if (!threads_started) _reent = _impure_ptr; else if (in_callback) _reent = &callback_reent; else _reent = &get_current()->reent; #ifndef NDEBUG #if defined(__x86_64__) || defined(__x86__) { #ifdef __x86_64__ register unsigned long sp asm ("rsp"); #else register unsigned long sp asm ("esp"); #endif if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) { static int overflowing; if (!overflowing) { overflowing = 1; printk("stack overflow\n"); BUG(); } } } #endif #endif return _reent; } #endif void exit_thread(void) { unsigned long flags; struct thread *thread = current; printk("Thread \"%s\" exited.\n", thread->name); local_irq_save(flags); /* Remove from the thread list */ minios_list_del(&thread->thread_list); clear_runnable(thread); /* Put onto exited list */ minios_list_add(&thread->thread_list, &exited_threads); local_irq_restore(flags); /* Schedule will free the resources */ while(1) { schedule(); printk("schedule() returned! Trying again\n"); } } void block(struct thread *thread) { thread->wakeup_time = 0LL; clear_runnable(thread); } void msleep(u32 millisecs) { struct thread *thread = get_current(); thread->wakeup_time = NOW() + MILLISECS(millisecs); clear_runnable(thread); schedule(); } void wake(struct thread *thread) { thread->wakeup_time = 0LL; set_runnable(thread); } void idle_thread_fn(void *unused) { threads_started = 1; while (1) { block(current); schedule(); } } DECLARE_MUTEX(mutex); void th_f1(void *data) { struct timeval tv1, tv2; for(;;) { down(&mutex); printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, is_runnable(current)); schedule(); printk("Thread \"%s\" releases the semaphore\n", current->name); up(&mutex); gettimeofday(&tv1, NULL); for(;;) { gettimeofday(&tv2, NULL); if(tv2.tv_sec - tv1.tv_sec > 2) break; } schedule(); } } void th_f2(void *data) { for(;;) { printk("Thread OTHER executing, data 0x%lx\n", data); schedule(); } } void init_sched(void) { printk("Initialising scheduler\n"); #ifdef HAVE_LIBC _REENT_INIT_PTR((&callback_reent)) #endif idle_thread = create_thread("Idle", idle_thread_fn, NULL); MINIOS_INIT_LIST_HEAD(&idle_thread->thread_list); }