Skip to content

Commit 33d8dbd

Browse files
committed
Fix bug when resume to display game
Last version of implementation can't resume to display the chess board after we stop to display it. We introduce I/O multiplexing mechanism in order to listen to both STDIN_FILENO and device driver attribute file. This way we can continue to listen to keyboard event even when the kernel stops sendding data to user space.
1 parent 783f424 commit 33d8dbd

File tree

2 files changed

+63
-26
lines changed

2 files changed

+63
-26
lines changed

kmldrv-user.c

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <stdio.h>
55
#include <stdlib.h>
66
#include <string.h>
7+
#include <sys/select.h>
78
#include <termios.h>
89
#include <unistd.h>
910

@@ -51,6 +52,32 @@ static void enableRawMode(void)
5152
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
5253
}
5354

55+
static bool read_attr;
56+
57+
static void listen_keyboard_handler(void)
58+
{
59+
int attr_fd = open(KMLDRV_DEVICE_ATTR_FILE, O_RDWR);
60+
char input;
61+
62+
if (read(STDIN_FILENO, &input, 1) == 1) {
63+
char buf[20];
64+
switch (input) {
65+
case 16:
66+
read(attr_fd, buf, 6);
67+
buf[0] = (buf[0] - '0') ? '0' : '1';
68+
read_attr = !read_attr;
69+
write(attr_fd, buf, 6);
70+
break;
71+
case 17:
72+
read(attr_fd, buf, 6);
73+
buf[4] = '1';
74+
write(attr_fd, buf, 6);
75+
break;
76+
}
77+
}
78+
close(attr_fd);
79+
}
80+
5481
int main(int argc, char *argv[])
5582
{
5683
int c;
@@ -85,33 +112,38 @@ int main(int argc, char *argv[])
85112
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
86113
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
87114

88-
FILE *device_ptr = fopen(KMLDRV_DEVICE_FILE, "r");
89115
char display_buf[DRAWBUFFER_SIZE];
90116

91-
int attr_fd = open(KMLDRV_DEVICE_ATTR_FILE, O_WRONLY);
92-
char input;
93-
while (fgets(display_buf, DRAWBUFFER_SIZE, device_ptr)) {
94-
printf("%s", display_buf);
95-
96-
if (read(STDIN_FILENO, &input, 1) == 1) {
97-
switch (input) {
98-
case 16:
99-
char buf[20];
100-
read(attr_fd, buf, 5);
101-
buf[0] = (buf[0] - '0') ? '0' : '1';
102-
write(attr_fd, buf, 5);
103-
break;
104-
case 17:
105-
break;
106-
}
117+
fd_set readset;
118+
int device_fd = open(KMLDRV_DEVICE_FILE, O_RDONLY);
119+
int max_fd = device_fd > STDIN_FILENO ? device_fd : STDIN_FILENO;
120+
read_attr = true;
121+
122+
while (1) {
123+
FD_ZERO(&readset);
124+
FD_SET(STDIN_FILENO, &readset);
125+
FD_SET(device_fd, &readset);
126+
127+
int result = select(max_fd + 1, &readset, NULL, NULL, NULL);
128+
if (result < 0) {
129+
printf("Error with select system call\n");
130+
exit(1);
131+
}
132+
133+
if (FD_ISSET(STDIN_FILENO, &readset)) {
134+
FD_CLR(STDIN_FILENO, &readset);
135+
listen_keyboard_handler();
136+
} else if (read_attr && FD_ISSET(device_fd, &readset)) {
137+
FD_CLR(device_fd, &readset);
138+
read(device_fd, display_buf, DRAWBUFFER_SIZE);
139+
printf("%s", display_buf);
107140
}
108141
}
109142

110143
disableRawMode();
111144
fcntl(STDIN_FILENO, F_SETFL, flags);
112145

113-
fclose(device_ptr);
114-
close(attr_fd);
146+
close(device_fd);
115147

116148
return 0;
117149
}

simrupt.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static int delay = 100; /* time (in ms) to generate an event */
3737

3838
struct kmldrv_attr {
3939
char display;
40-
char restart;
40+
char resume;
4141
char end;
4242
rwlock_t lock;
4343
};
@@ -49,7 +49,7 @@ static ssize_t kmldrv_state_show(struct device *dev,
4949
char *buf)
5050
{
5151
read_lock(&attr_obj.lock);
52-
int ret = snprintf(buf, 6, "%c %c %c\n", attr_obj.display, attr_obj.restart,
52+
int ret = snprintf(buf, 6, "%c %c %c\n", attr_obj.display, attr_obj.resume,
5353
attr_obj.end);
5454
read_unlock(&attr_obj.lock);
5555
return ret;
@@ -61,7 +61,7 @@ static ssize_t kmldrv_state_store(struct device *dev,
6161
size_t count)
6262
{
6363
write_lock(&attr_obj.lock);
64-
sscanf(buf, "%c %c %c", &(attr_obj.display), &(attr_obj.restart),
64+
sscanf(buf, "%c %c %c", &(attr_obj.display), &(attr_obj.resume),
6565
&(attr_obj.end));
6666
write_unlock(&attr_obj.lock);
6767
return count;
@@ -342,6 +342,7 @@ static void timer_handler(struct timer_list *__timer)
342342

343343
if (win == ' ') {
344344
ai_game();
345+
mod_timer(&timer, jiffies + msecs_to_jiffies(delay));
345346
} else {
346347
read_lock(&attr_obj.lock);
347348
if (attr_obj.display == '1') {
@@ -360,10 +361,16 @@ static void timer_handler(struct timer_list *__timer)
360361

361362
wake_up_interruptible(&rx_wait);
362363
}
364+
365+
if (attr_obj.end == '0') {
366+
memset(table, ' ',
367+
N_GRIDS); /* Reset the table so the game restart */
368+
mod_timer(&timer, jiffies + msecs_to_jiffies(delay));
369+
}
370+
363371
read_unlock(&attr_obj.lock);
364372

365373
pr_info("kmldrv: %c win!!!\n", win);
366-
memset(table, ' ', N_GRIDS); /* Reset the table so the game restart */
367374
}
368375
tv_end = ktime_get();
369376

@@ -372,8 +379,6 @@ static void timer_handler(struct timer_list *__timer)
372379
pr_info("kmldrv: [CPU#%d] %s in_irq: %llu usec\n", smp_processor_id(),
373380
__func__, (unsigned long long) nsecs >> 10);
374381

375-
mod_timer(&timer, jiffies + msecs_to_jiffies(delay));
376-
377382
local_irq_enable();
378383
}
379384

@@ -515,7 +520,7 @@ static int __init kmldrv_init(void)
515520
finish = 1;
516521

517522
attr_obj.display = '1';
518-
attr_obj.restart = '0';
523+
attr_obj.resume = '1';
519524
attr_obj.end = '0';
520525
rwlock_init(&attr_obj.lock);
521526
/* Setup the timer */

0 commit comments

Comments
 (0)