forked from sysprog21/simrupt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkmldrv-user.c
155 lines (133 loc) · 4.05 KB
/
kmldrv-user.c
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <fcntl.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#include "game.h"
#define KMLDRV_STATUS_FILE "/sys/module/kmldrv/initstate"
#define KMLDRV_DEVICE_FILE "/dev/kmldrv"
#define KMLDRV_DEVICE_ATTR_FILE "/sys/class/kmldrv/kmldrv/kmldrv_state"
bool kmldrv_status_check(void)
{
FILE *fp = fopen(KMLDRV_STATUS_FILE, "r");
if (!fp) {
printf("kmldrv status : not loaded\n");
return false;
}
char read_buf[20];
fgets(read_buf, 20, fp);
read_buf[strcspn(read_buf, "\n")] = 0;
if (!strcmp("live", read_buf))
printf("kmldrv status : live\n");
else {
printf("kmldrv status : %s\n", read_buf);
fclose(fp);
return false;
}
fclose(fp);
return true;
}
static struct termios orig_termios;
static void disableRawMode(void)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
}
static void enableRawMode(void)
{
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(disableRawMode);
struct termios raw = orig_termios;
raw.c_lflag &= ~(ECHO | ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
static bool read_attr;
static bool end_attr;
static void listen_keyboard_handler(void)
{
int attr_fd = open(KMLDRV_DEVICE_ATTR_FILE, O_RDWR);
char input;
if (read(STDIN_FILENO, &input, 1) == 1) {
char buf[20];
switch (input) {
case 16:
read(attr_fd, buf, 6);
buf[0] = (buf[0] - '0') ? '0' : '1';
read_attr ^= 1;
write(attr_fd, buf, 6);
if (!read_attr)
printf("Stopping to display the chess board...\n");
break;
case 17:
read(attr_fd, buf, 6);
buf[4] = '1';
read_attr = false;
end_attr = true;
write(attr_fd, buf, 6);
printf("Stopping the kernel space tic-tac-toe game...\n");
break;
}
}
close(attr_fd);
}
int main(int argc, char *argv[])
{
int c;
while ((c = getopt(argc, argv, "d:s:ch")) != -1) {
switch (c) {
case 'h':
printf(
"kmldrv-user : A userspace tool which supports interactions "
"with kmldrv from user-level\n");
printf("Usage:\n\n");
printf("\t./kmldrv-user [arguments]\n\n");
printf("Arguments:\n\n");
printf("\t--start - start a tic-tac-toe game\n");
printf("\t--release - release kmldrv\n\n");
printf("Control Options:\n\n");
printf("\t Ctrl + P - Pause/Continue to show the game\n");
printf("\t Ctrl + Q - Stop the tic-tac-toe game\n");
return 0;
default:
printf("Invalid arguments\n");
break;
}
}
if (!kmldrv_status_check())
exit(1);
enableRawMode();
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
char display_buf[DRAWBUFFER_SIZE];
fd_set readset;
int device_fd = open(KMLDRV_DEVICE_FILE, O_RDONLY);
int max_fd = device_fd > STDIN_FILENO ? device_fd : STDIN_FILENO;
read_attr = true;
end_attr = false;
while (!end_attr) {
FD_ZERO(&readset);
FD_SET(STDIN_FILENO, &readset);
FD_SET(device_fd, &readset);
int result = select(max_fd + 1, &readset, NULL, NULL, NULL);
if (result < 0) {
printf("Error with select system call\n");
exit(1);
}
if (FD_ISSET(STDIN_FILENO, &readset)) {
FD_CLR(STDIN_FILENO, &readset);
listen_keyboard_handler();
} else if (read_attr && FD_ISSET(device_fd, &readset)) {
FD_CLR(device_fd, &readset);
printf("\033[H\033[J"); /* ASCII escape code to clear the screen */
read(device_fd, display_buf, DRAWBUFFER_SIZE);
printf("%s", display_buf);
}
}
disableRawMode();
fcntl(STDIN_FILENO, F_SETFL, flags);
close(device_fd);
return 0;
}