-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathxo-user.c
130 lines (110 loc) · 3.22 KB
/
xo-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
#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 XO_STATUS_FILE "/sys/module/kxo/initstate"
#define XO_DEVICE_FILE "/dev/kxo"
#define XO_DEVICE_ATTR_FILE "/sys/class/kxo/kxo/kxo_state"
static bool status_check(void)
{
FILE *fp = fopen(XO_STATUS_FILE, "r");
if (!fp) {
printf("kxo 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("kxo status : %s\n", read_buf);
fclose(fp);
return false;
}
fclose(fp);
return true;
}
static struct termios orig_termios;
static void raw_mode_disable(void)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
}
static void raw_mode_enable(void)
{
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(raw_mode_disable);
struct termios raw = orig_termios;
raw.c_iflag &= ~IXON;
raw.c_lflag &= ~(ECHO | ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
static bool read_attr, end_attr;
static void listen_keyboard_handler(void)
{
int attr_fd = open(XO_DEVICE_ATTR_FILE, O_RDWR);
char input;
if (read(STDIN_FILENO, &input, 1) == 1) {
char buf[20];
switch (input) {
case 16: /* Ctrl-P */
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: /* Ctrl-Q */
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[])
{
if (!status_check())
exit(1);
raw_mode_enable();
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(XO_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);
}
}
raw_mode_disable();
fcntl(STDIN_FILENO, F_SETFL, flags);
close(device_fd);
return 0;
}