~vojtech-horky/helenos/numa

« back to all changes in this revision

Viewing changes to kernel/genarch/src/kbrd/kbrd_pl050.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009 Vineeth Pillai
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * - Redistributions of source code must retain the above copyright
 
10
 *   notice, this list of conditions and the following disclaimer.
 
11
 * - Redistributions in binary form must reproduce the above copyright
 
12
 *   notice, this list of conditions and the following disclaimer in the
 
13
 *   documentation and/or other materials provided with the distribution.
 
14
 * - The name of the author may not be used to endorse or promote products
 
15
 *   derived from this software without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
/** @addtogroup genarch
 
30
 * @{
 
31
 */
 
32
/**
 
33
 * @file
 
34
 * @brief pl050 Keyboard processing.
 
35
 */
 
36
 
 
37
#include <genarch/kbrd/kbrd.h>
 
38
#include <genarch/kbrd/scanc.h>
 
39
 
 
40
#include <genarch/kbrd/scanc_pl050.h>
 
41
 
 
42
#include <synch/spinlock.h>
 
43
#include <console/chardev.h>
 
44
#include <console/console.h>
 
45
#include <proc/thread.h>
 
46
#include <arch.h>
 
47
#include <macros.h>
 
48
 
 
49
#define PRESSED_SHIFT     (1 << 0)
 
50
#define PRESSED_CAPSLOCK  (1 << 1)
 
51
#define LOCKED_CAPSLOCK   (1 << 0)
 
52
 
 
53
#define PL050_KEY_RELEASE 0xF0
 
54
#define PL050_ESC_KEY   0xE0
 
55
#define PL050_CAPS_SCAN_CODE   0x58
 
56
#define PL050_NUM_SCAN_CODE   0x77
 
57
#define PL050_SCROLL_SCAN_CODE   0x7E
 
58
 
 
59
static bool is_lock_key(wchar_t);
 
60
 
 
61
static indev_operations_t kbrd_raw_ops = {
 
62
        .poll = NULL
 
63
};
 
64
 
 
65
/** Process release of key.
 
66
 *
 
67
 * @param sc Scancode of the key being released.
 
68
 */
 
69
static void key_released(kbrd_instance_t *instance, wchar_t sc)
 
70
{
 
71
        spinlock_lock(&instance->keylock);
 
72
        
 
73
        switch (sc) {
 
74
        case SC_LSHIFT:
 
75
        case SC_RSHIFT:
 
76
                instance->keyflags &= ~PRESSED_SHIFT;
 
77
                break;
 
78
        case SC_CAPSLOCK:
 
79
                instance->keyflags &= ~PRESSED_CAPSLOCK;
 
80
                if (instance->lockflags & LOCKED_CAPSLOCK)
 
81
                        instance->lockflags &= ~LOCKED_CAPSLOCK;
 
82
                else
 
83
                        instance->lockflags |= LOCKED_CAPSLOCK;
 
84
                break;
 
85
        default:
 
86
                break;
 
87
        }
 
88
        
 
89
        spinlock_unlock(&instance->keylock);
 
90
}
 
91
 
 
92
/** Process keypress.
 
93
 *
 
94
 * @param sc Scancode of the key being pressed.
 
95
 */
 
96
static void key_pressed(kbrd_instance_t *instance, wchar_t sc)
 
97
{
 
98
        bool letter;
 
99
        bool shift;
 
100
        bool capslock;
 
101
        
 
102
        spinlock_lock(&instance->keylock);
 
103
        
 
104
        switch (sc) {
 
105
        case SC_LSHIFT:
 
106
        case SC_RSHIFT:
 
107
                instance->keyflags |= PRESSED_SHIFT;
 
108
                break;
 
109
        case SC_CAPSLOCK:
 
110
                instance->keyflags |= PRESSED_CAPSLOCK;
 
111
                break;
 
112
        case SC_SCAN_ESCAPE:
 
113
                break;
 
114
        default:
 
115
                letter = islower(sc_primary_map[sc]);
 
116
                shift = instance->keyflags & PRESSED_SHIFT;
 
117
                capslock = (instance->keyflags & PRESSED_CAPSLOCK) ||
 
118
                    (instance->lockflags & LOCKED_CAPSLOCK);
 
119
                
 
120
                if ((letter) && (capslock))
 
121
                        shift = !shift;
 
122
                
 
123
                if (shift)
 
124
                        indev_push_character(instance->sink, sc_secondary_map[sc]);
 
125
                else
 
126
                        indev_push_character(instance->sink, sc_primary_map[sc]);
 
127
                break;
 
128
        }
 
129
        
 
130
        spinlock_unlock(&instance->keylock);
 
131
}
 
132
 
 
133
static void kkbrd(void *arg)
 
134
{
 
135
        static int key_released_flag = 0;
 
136
        static int is_locked = 0;
 
137
        kbrd_instance_t *instance = (kbrd_instance_t *) arg;
 
138
        
 
139
        while (true) {
 
140
                wchar_t sc = indev_pop_character(&instance->raw);
 
141
 
 
142
                if (sc == PL050_KEY_RELEASE) {
 
143
                        key_released_flag = 1;
 
144
                } else {
 
145
                        if (key_released_flag) {
 
146
                                key_released_flag = 0;
 
147
                                if (is_lock_key(sc)) {
 
148
                                        if (!is_locked) {
 
149
                                                is_locked = 1;
 
150
                                        } else {
 
151
                                                is_locked = 0;
 
152
                                                continue;
 
153
                                        }
 
154
                                }
 
155
                                key_released(instance, sc);
 
156
 
 
157
                        } else {
 
158
                                if (is_lock_key(sc) && is_locked)
 
159
                                        continue;
 
160
                                key_pressed(instance, sc);
 
161
                        }
 
162
                }
 
163
                
 
164
        }
 
165
}
 
166
 
 
167
kbrd_instance_t *kbrd_init(void)
 
168
{
 
169
        kbrd_instance_t *instance
 
170
            = malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC);
 
171
        if (instance) {
 
172
                instance->thread
 
173
                        = thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false);
 
174
                
 
175
                if (!instance->thread) {
 
176
                        free(instance);
 
177
                        return NULL;
 
178
                }
 
179
                
 
180
                instance->sink = NULL;
 
181
                indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops);
 
182
                
 
183
                spinlock_initialize(&instance->keylock, "instance_keylock");
 
184
                instance->keyflags = 0;
 
185
                instance->lockflags = 0;
 
186
        }
 
187
        
 
188
        return instance;
 
189
}
 
190
 
 
191
indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink)
 
192
{
 
193
        ASSERT(instance);
 
194
        ASSERT(sink);
 
195
        
 
196
        instance->sink = sink;
 
197
        thread_ready(instance->thread);
 
198
        
 
199
        return &instance->raw;
 
200
}
 
201
 
 
202
static bool is_lock_key(wchar_t sc)
 
203
{
 
204
        return ((sc == PL050_CAPS_SCAN_CODE) || (sc == PL050_NUM_SCAN_CODE) ||
 
205
                (sc == PL050_SCROLL_SCAN_CODE));
 
206
}
 
207
 
 
208
/** @}
 
209
 */