embox

Форк
0
158 строк · 3.0 Кб
1
/**
2
 * @file
3
 * @brief Keyboard driver
4
 *
5
 * @date 12.12.10
6
 * @author Anton Bondarev
7
 */
8

9
#include <errno.h>
10
#include <stdint.h>
11

12
#include <drivers/input/keymap.h>
13
#include <drivers/input/input_dev.h>
14
#include <drivers/ps_keyboard.h>
15

16
#include <kernel/irq.h>
17
#include <embox/unit.h>
18
#include <drivers/diag.h>
19
#include <drivers/tty.h>
20
#include <drivers/video_term.h>
21
#include <drivers/i8042.h>
22

23
EMBOX_UNIT_INIT(keyboard_init);
24

25
static void keyboard_send_cmd(uint8_t cmd) {
26
	unsigned int status;
27
	keyboard_wait_write(status);
28
	outb(cmd, I8042_CMD_PORT);
29
}
30

31
static unsigned char keyboard_get_mode(void) {
32
	unsigned char status;
33

34
	keyboard_send_cmd(I8042_CMD_READ_MODE);
35
	keyboard_wait_read(status);
36
	return inb(I8042_DATA_PORT);
37
}
38

39
static void keyboard_set_mode(unsigned char mode) {
40
	unsigned char status;
41

42
	keyboard_send_cmd(I8042_CMD_WRITE_MODE);
43
	keyboard_wait_write(status);
44
	outb(mode, I8042_DATA_PORT);
45
}
46

47
static int keyboard_get_input_event(struct input_dev *dev, struct input_event *event) {
48
	uint8_t scan_code, status;
49
	int ret = 0;
50

51
	irq_lock();
52
	{
53
		status = keyboard_read_stat();
54

55
		if (!(status & I8042_STS_OBF)) {
56
			ret = -EAGAIN;
57
			goto out;
58
		}
59

60
		scan_code = inb(I8042_DATA_PORT);
61

62
		if (scan_code == KEYBOARD_SCAN_CODE_EXT) {
63
			ret = -EAGAIN;
64
			goto out;
65
		}
66

67
		if (status & I8042_STS_AUXOBF) {
68
			ret = -EAGAIN;
69
			goto out;
70
		}
71

72
		keyboard_scan_code_to_event(scan_code, event);
73
	}
74
out:
75
	irq_unlock();
76
	return ret;
77
}
78

79
static int keyboard_start(struct input_dev *indev) {
80
	uint8_t mode;
81

82
	irq_lock();
83
	{
84
		/* If 0x64 returns 0xff, then we have no keyboard
85
		 * controller */
86
		if (inb(0x64) == 0xFF) {
87
			goto out;
88
		}
89

90
		keyboard_send_cmd(I8042_CMD_PORT_DIS);
91

92
		while (keyboard_havechar()) inb(I8042_DATA_PORT);
93

94
		/* Read the current mode */
95
		mode = keyboard_get_mode();
96
		/* Turn on scancode translate mode so that we can
97
		 use the scancode set 1 tables */
98
		mode |= I8042_MODE_XLATE;
99
		/* Enable keyboard. */
100
		mode &= ~I8042_MODE_DISABLE;
101
		/* Enable interrupt */
102
		mode |= I8042_MODE_INTERRUPT;
103
		/* Write the new mode */
104
		keyboard_set_mode(mode);
105

106
		keyboard_send_cmd(I8042_CMD_PORT_EN);
107

108
		i8042_wait_write();
109
		outb(I8042_KBD_RESET_ENABLE, I8042_DATA_PORT);
110
	}
111
out:
112
	irq_unlock();
113
	return 0;
114
}
115

116
static int keyboard_stop(struct input_dev *dev) {
117

118
	/* TODO */
119
	return 0;
120
}
121

122
static const struct input_dev_ops kbd_input_ops = {
123
		/*.start = keyboard_start,*/
124
		.stop = keyboard_stop,
125
};
126

127
static struct input_dev kbd_dev = {
128
		.ops = &kbd_input_ops,
129
		.name = "ps-keyboard",
130
		.type = INPUT_DEV_KBD,
131
};
132

133
static irq_return_t ps_kbd_irq_hnd(unsigned int irq_nr, void *data) {
134
	struct input_dev *dev = (struct input_dev *) data;
135
	struct input_event ev;
136
	int ret;
137

138
	ret = keyboard_get_input_event(dev, &ev);
139
	if (!ret) {
140
		input_dev_report_event(dev, &ev);
141
	}
142

143
	return IRQ_HANDLED;
144
}
145

146
static int keyboard_init(void) {
147
	int res;
148

149
	res = irq_attach(I8042_KBD_IRQ, ps_kbd_irq_hnd, 0,
150
					 &kbd_dev, "ps keyboard");
151
	if (res < 0) {
152
		return res;
153
	}
154

155
	keyboard_start(NULL);
156

157
	return input_dev_register(&kbd_dev);
158
}
159

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.