PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
kbd.c
Go to the documentation of this file.
2
4#include <kernel/fs/file.h>
5#include <kernel/fs/sysfs.h>
6#include <kernel/fs/vfs.h>
9#include <kernel/sync/lock.h>
10
11#include <errno.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <sys/io.h>
15#include <sys/math.h>
16#include <sys/proc.h>
17
19
20static atomic_uint64_t newId = ATOMIC_VAR_INIT(0);
21
23{
25
27 for (uint64_t i = 0; i < count / sizeof(kbd_event_t); i++)
28 {
29 LOCK_SCOPE(&kbd->lock);
30
31 if (WAIT_BLOCK_LOCK(&kbd->waitQueue, &kbd->lock, *offset != kbd->writeIndex) == ERR)
32 {
33 return i * sizeof(kbd_event_t);
34 }
35
36 ((kbd_event_t*)buffer)[i] = kbd->events[*offset];
37 *offset = (*offset + 1) % KBD_MAX_EVENT;
38 }
39
40 return count;
41}
42
44{
46 LOCK_SCOPE(&kbd->lock);
47 if (kbd->writeIndex != file->pos)
48 {
49 *revents |= POLLIN;
50 }
51 return &kbd->waitQueue;
52}
53
56 .poll = kbd_events_poll,
57};
58
60{
62 uint64_t nameLen = strlen(kbd->name);
63 if (*offset >= nameLen)
64 {
65 return 0;
66 }
67
68 return BUFFER_READ(buffer, count, offset, kbd->name, nameLen);
69}
70
73};
74
75static void kbd_dir_cleanup(inode_t* inode)
76{
77 kbd_t* kbd = inode->private;
78 wait_queue_deinit(&kbd->waitQueue);
79 free(kbd->name);
80 free(kbd);
81}
82
86
87kbd_t* kbd_new(const char* name)
88{
89 if (name == NULL)
90 {
91 errno = EINVAL;
92 return NULL;
93 }
94
95 if (kbdDir == NULL)
96 {
97 kbdDir = sysfs_dir_new(NULL, "kbd", NULL, NULL);
98 if (kbdDir == NULL)
99 {
100 return NULL;
101 }
102 }
103
104 kbd_t* kbd = calloc(1, sizeof(kbd_t));
105 if (kbd == NULL)
106 {
107 return NULL;
108 }
109 kbd->name = strdup(name);
110 if (kbd->name == NULL)
111 {
112 free(kbd);
113 return NULL;
114 }
115 kbd->writeIndex = 0;
116 kbd->mods = KBD_MOD_NONE;
117 wait_queue_init(&kbd->waitQueue);
118 lock_init(&kbd->lock);
119
120 char id[MAX_NAME];
121 if (snprintf(id, MAX_NAME, "%llu", atomic_fetch_add(&newId, 1)) < 0)
122 {
123 wait_queue_deinit(&kbd->waitQueue);
124 free(kbd->name);
125 free(kbd);
126 return NULL;
127 }
128
129 kbd->dir = sysfs_dir_new(kbdDir, id, &dirInodeOps, kbd);
130 if (kbd->dir == NULL)
131 {
132 wait_queue_deinit(&kbd->waitQueue);
133 free(kbd->name);
134 free(kbd);
135 return NULL;
136 }
137 kbd->eventsFile = sysfs_file_new(kbd->dir, "events", NULL, &eventsOps, kbd);
138 if (kbd->eventsFile == NULL)
139 {
140 UNREF(kbd->dir); // kbd will be freed in kbd_dir_cleanup
141 return NULL;
142 }
143 kbd->nameFile = sysfs_file_new(kbd->dir, "name", NULL, &nameOps, kbd);
144 if (kbd->nameFile == NULL)
145 {
146 UNREF(kbd->eventsFile);
147 UNREF(kbd->dir);
148 return NULL;
149 }
150
151 return kbd;
152}
153
155{
156 if (kbd == NULL)
157 {
158 return;
159 }
160
161 UNREF(kbd->dir);
162 UNREF(kbd->eventsFile);
163 UNREF(kbd->nameFile);
164 // kbd will be freed in kbd_dir_cleanup
165}
166
168{
169 if (type == KBD_PRESS)
170 {
171 kbd->mods |= mod;
172 }
173 else if (type == KBD_RELEASE)
174 {
175 kbd->mods &= ~mod;
176 }
177}
178
180{
181 LOCK_SCOPE(&kbd->lock);
182
183 switch (code)
184 {
185 case KBD_CAPS_LOCK:
187 break;
188 case KBD_LEFT_SHIFT:
189 case KBD_RIGHT_SHIFT:
191 break;
192 case KBD_LEFT_CTRL:
193 case KBD_RIGHT_CTRL:
195 break;
196 case KBD_LEFT_ALT:
197 case KBD_RIGHT_ALT:
199 break;
200 case KBD_LEFT_SUPER:
201 case KBD_RIGHT_SUPER:
203 break;
204 default:
205 break;
206 }
207
208 kbd->events[kbd->writeIndex] = (kbd_event_t){
209 .time = clock_uptime(),
210 .code = code,
211 .mods = kbd->mods,
212 .type = type,
213 };
214 kbd->writeIndex = (kbd->writeIndex + 1) % KBD_MAX_EVENT;
215 wait_unblock(&kbd->waitQueue, WAIT_ALL, EOK);
216}
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
static fd_t kbd
Definition dwm.c:23
#define KBD_MAX_EVENT
Maximum number of queued keyboard events.
Definition kbd.h:24
void kbd_push(kbd_t *kbd, kbd_event_type_t type, keycode_t code)
Push a keyboard event to the keyboard event queue.
Definition kbd.c:179
void kbd_free(kbd_t *kbd)
Free and deinitialize a keyboard structure.
Definition kbd.c:154
kbd_t * kbd_new(const char *name)
Allocate and initialize a keyboard structure.
Definition kbd.c:87
clock_t clock_uptime(void)
Retrieve the time in nanoseconds since boot.
Definition clock.c:99
uint64_t wait_unblock(wait_queue_t *queue, uint64_t amount, errno_t err)
Unblock threads waiting on a wait queue.
Definition wait.c:296
void wait_queue_deinit(wait_queue_t *queue)
Deinitialize wait queue.
Definition wait.c:44
#define WAIT_ALL
Used to indicate that the wait should unblock all waiting threads.
Definition wait.h:40
void wait_queue_init(wait_queue_t *queue)
Initialize wait queue.
Definition wait.c:38
#define WAIT_BLOCK_LOCK(queue, lock, condition)
Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock b...
Definition wait.h:106
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:86
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:57
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:80
#define BUFFER_READ(buffer, count, offset, src, size)
Helper macros for implementing file operations dealing with simple buffers.
Definition vfs.h:194
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#define EOK
No error.
Definition errno.h:32
poll_events_t
Poll events type.
Definition io.h:257
@ POLLIN
File descriptor is ready to read.
Definition io.h:259
keycode_t
Keyboard keycode type.
Definition kbd.h:27
kbd_mods_t
Keyboard modifiers type.
Definition kbd.h:297
kbd_event_type_t
Keyboard event type.
Definition kbd.h:286
@ KBD_RIGHT_SUPER
Right Super key.
Definition kbd.h:256
@ KBD_LEFT_ALT
Left Alt key.
Definition kbd.h:251
@ KBD_LEFT_SHIFT
Left Shift key.
Definition kbd.h:250
@ KBD_RIGHT_SHIFT
Right Shift key.
Definition kbd.h:254
@ KBD_LEFT_CTRL
Left Control key.
Definition kbd.h:249
@ KBD_RIGHT_ALT
Right Alt key.
Definition kbd.h:255
@ KBD_CAPS_LOCK
Caps Lock key.
Definition kbd.h:87
@ KBD_RIGHT_CTRL
Right Control key.
Definition kbd.h:253
@ KBD_LEFT_SUPER
Left Super key.
Definition kbd.h:252
@ KBD_MOD_SUPER
Super (Windows/Command) modifier.
Definition kbd.h:303
@ KBD_MOD_CAPS
Caps Lock modifier.
Definition kbd.h:299
@ KBD_MOD_NONE
No modifier.
Definition kbd.h:298
@ KBD_MOD_CTRL
Control modifier.
Definition kbd.h:301
@ KBD_MOD_ALT
Alt modifier.
Definition kbd.h:302
@ KBD_MOD_SHIFT
Shift modifier.
Definition kbd.h:300
@ KBD_RELEASE
Key release event.
Definition kbd.h:288
@ KBD_PRESS
Key press event.
Definition kbd.h:287
#define ROUND_DOWN(number, multiple)
Definition math.h:21
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static dentry_t * kbdDir
Definition kbd.c:18
static atomic_uint64_t newId
Definition kbd.c:20
static uint64_t kbd_name_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition kbd.c:59
static void kbd_dir_cleanup(inode_t *inode)
Definition kbd.c:75
static void kbd_update_mod(kbd_t *kbd, kbd_event_type_t type, kbd_mods_t mod)
Definition kbd.c:167
static wait_queue_t * kbd_events_poll(file_t *file, poll_events_t *revents)
Definition kbd.c:43
static file_ops_t nameOps
Definition kbd.c:71
static inode_ops_t dirInodeOps
Definition kbd.c:83
static file_ops_t eventsOps
Definition kbd.c:54
static uint64_t kbd_events_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition kbd.c:22
static dentry_t * file
Definition log_file.c:22
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static atomic_long count
Definition main.c:10
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
#define atomic_fetch_add(object, operand)
Definition stdatomic.h:283
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int snprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format,...)
Definition snprintf.c:3
_PUBLIC void * calloc(size_t nmemb, size_t size)
Definition calloc.c:6
_PUBLIC void free(void *ptr)
Definition free.c:11
char * strdup(const char *src)
Definition strdup.c:5
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
Directory entry structure.
Definition dentry.h:84
inode_t * inode
Will be NULL if the dentry is negative, once positive it will never be NULL.
Definition dentry.h:88
File operations structure.
Definition file.h:54
uint64_t(* read)(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition file.h:58
File structure.
Definition file.h:39
Inode operations structure.
Definition inode.h:82
void(* cleanup)(inode_t *inode)
Cleanup function called when the inode is being freed.
Definition inode.h:134
Inode structure.
Definition inode.h:56
void * private
Definition inode.h:68
Keyboard event structure.
Definition kbd.h:313
Keyboard structure.
Definition kbd.h:31
The primitive that threads block on.
Definition wait.h:182
dentry_t * sysfs_dir_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, void *private)
Create a new directory inside a mounted SysFS instance.
Definition sysfs.c:177
dentry_t * sysfs_file_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, const file_ops_t *fileOps, void *private)
Create a new file inside a mounted SysFS instance.
Definition sysfs.c:216