PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
mouse.c
Go to the documentation of this file.
2#include <kernel/fs/file.h>
3#include <kernel/fs/sysfs.h>
4#include <kernel/fs/vfs.h>
5#include <kernel/log/log.h>
8#include <kernel/sync/lock.h>
9
10#include <errno.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <sys/math.h>
14
16
17static atomic_uint64_t newId = ATOMIC_VAR_INIT(0);
18
20{
22
24 for (uint64_t i = 0; i < count / sizeof(mouse_event_t); i++)
25 {
26 LOCK_SCOPE(&mouse->lock);
27
28 if (WAIT_BLOCK_LOCK(&mouse->waitQueue, &mouse->lock, *offset != mouse->writeIndex) == ERR)
29 {
30 return i * sizeof(mouse_event_t);
31 }
32
33 ((mouse_event_t*)buffer)[i] = mouse->events[*offset];
34 *offset = (*offset + 1) % MOUSE_MAX_EVENT;
35 }
36
37 return count;
38}
39
41{
43 LOCK_SCOPE(&mouse->lock);
44 if (mouse->writeIndex != file->pos)
45 {
46 *revents |= POLLIN;
47 }
48 return &mouse->waitQueue;
49}
50
53 .poll = mouse_events_poll,
54};
55
57{
59 uint64_t nameLen = strlen(mouse->name);
60 if (*offset >= nameLen)
61 {
62 return 0;
63 }
64
65 return BUFFER_READ(buffer, count, offset, mouse->name, nameLen);
66}
67
70};
71
72static void mouse_dir_cleanup(inode_t* inode)
73{
74 mouse_t* mouse = inode->private;
75 wait_queue_deinit(&mouse->waitQueue);
76 free(mouse->name);
77 free(mouse);
78}
79
83
84mouse_t* mouse_new(const char* name)
85{
86 if (name == NULL)
87 {
88 errno = EINVAL;
89 return NULL;
90 }
91
92 if (mouseDir == NULL)
93 {
94 mouseDir = sysfs_dir_new(NULL, "mouse", NULL, NULL);
95 if (mouseDir == NULL)
96 {
97 return NULL;
98 }
99 }
100
101 mouse_t* mouse = calloc(1, sizeof(mouse_t));
102 if (mouse == NULL)
103 {
104 return NULL;
105 }
106 mouse->name = strdup(name);
107 if (mouse->name == NULL)
108 {
109 free(mouse);
110 return NULL;
111 }
112 mouse->writeIndex = 0;
113 wait_queue_init(&mouse->waitQueue);
114 lock_init(&mouse->lock);
115
116 char id[MAX_NAME];
117 if (snprintf(id, MAX_NAME, "%llu", atomic_fetch_add(&newId, 1)) < 0)
118 {
119 wait_queue_deinit(&mouse->waitQueue);
120 free(mouse->name);
121 free(mouse);
122 return NULL;
123 }
124
126 if (mouse->dir == NULL)
127 {
128 wait_queue_deinit(&mouse->waitQueue);
129 free(mouse->name);
130 free(mouse);
131 return NULL;
132 }
133 mouse->eventsFile = sysfs_file_new(mouse->dir, "events", NULL, &eventsOps, mouse);
134 if (mouse->eventsFile == NULL)
135 {
136 UNREF(mouse->dir); // mouse will be freed in mouse_dir_cleanup
137 return NULL;
138 }
139 mouse->nameFile = sysfs_file_new(mouse->dir, "name", NULL, &nameOps, mouse);
140 if (mouse->nameFile == NULL)
141 {
142 UNREF(mouse->dir);
143 UNREF(mouse->eventsFile);
144 return NULL;
145 }
146
147 return mouse;
148}
149
151{
152 UNREF(mouse->dir);
153 UNREF(mouse->eventsFile);
154 UNREF(mouse->nameFile);
155 // mouse will be freed in mouse_dir_cleanup
156}
157
158void mouse_push(mouse_t* mouse, mouse_buttons_t buttons, int64_t deltaX, int64_t deltaY)
159{
160 LOCK_SCOPE(&mouse->lock);
161 mouse->events[mouse->writeIndex] = (mouse_event_t){
162 .time = clock_uptime(),
163 .buttons = buttons,
164 .deltaX = deltaX,
165 .deltaY = deltaY,
166 };
167 mouse->writeIndex = (mouse->writeIndex + 1) % MOUSE_MAX_EVENT;
168 wait_unblock(&mouse->waitQueue, WAIT_ALL, EOK);
169}
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
static fd_t mouse
Definition dwm.c:24
mouse_t * mouse_new(const char *name)
Allocate and initialize a mouse structure.
Definition mouse.c:84
void mouse_free(mouse_t *mouse)
Free and deinitialize a mouse structure.
Definition mouse.c:150
void mouse_push(mouse_t *mouse, mouse_buttons_t buttons, int64_t deltaX, int64_t deltaY)
Push a new mouse event to the mouse event queue.
Definition mouse.c:158
#define MOUSE_MAX_EVENT
Maximum number of queued mouse events.
Definition mouse.h:24
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
#define ROUND_DOWN(number, multiple)
Definition math.h:21
mouse_buttons_t
Mouse buttons enum.
Definition mouse.h:31
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static dentry_t * file
Definition log_file.c:22
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static atomic_uint64_t newId
Definition mouse.c:17
static uint64_t mouse_events_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition mouse.c:19
static void mouse_dir_cleanup(inode_t *inode)
Definition mouse.c:72
static file_ops_t nameOps
Definition mouse.c:68
static wait_queue_t * mouse_events_poll(file_t *file, poll_events_t *revents)
Definition mouse.c:40
static inode_ops_t dirInodeOps
Definition mouse.c:80
static file_ops_t eventsOps
Definition mouse.c:51
static dentry_t * mouseDir
Definition mouse.c:15
static uint64_t mouse_name_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition mouse.c:56
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
__INT64_TYPE__ int64_t
Definition stdint.h:16
_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
Mouse event structure.
Definition mouse.h:45
Mouse structure.
Definition mouse.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