-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pc-tty: add PS/2 mouse support and kbd/mouse vdevs
Adds PS/2 mouse support. Because PS/2 keyboard and mouse share the same I/O port, this required some heavy refactoring of ttypc_kbd driver. It also adds /dev/kbd and /dev/mouse virtual devices, which can be used for input event capturing by applications, for instance by an X server, as part of RTOS-864. Mouse support is optional and can be enabled by exporting HAS_MOUSE=y in a compatible target. JIRA: RTOS-896
- Loading branch information
1 parent
3d18d6b
commit 8bb3c00
Showing
9 changed files
with
841 additions
and
213 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#include <errno.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <fcntl.h> | ||
#include <sys/threads.h> | ||
|
||
#include "event_queue.h" | ||
|
||
|
||
#define min(a, b) ({ \ | ||
__typeof__(a) _a = (a); \ | ||
__typeof__(b) _b = (b); \ | ||
_a > _b ? _b : _a; \ | ||
}) | ||
|
||
|
||
struct _event_queue_t { | ||
unsigned char *buf; | ||
unsigned int count; | ||
unsigned int r; | ||
unsigned int w; | ||
unsigned int sz; | ||
handle_t mutex; | ||
handle_t waitq; | ||
}; | ||
|
||
|
||
int event_queue_init(event_queue_t **res, unsigned int sz) | ||
{ | ||
int err; | ||
event_queue_t *eq; | ||
|
||
if (sz == 0) | ||
return EINVAL; | ||
|
||
eq = malloc(sizeof(event_queue_t)); | ||
if (eq == NULL) { | ||
return -1; | ||
} | ||
|
||
memset(eq, 0, sizeof(event_queue_t)); | ||
|
||
eq->buf = malloc(sizeof(unsigned char) * sz); | ||
if (eq->buf == NULL) { | ||
return -1; | ||
} | ||
|
||
eq->sz = sz; | ||
|
||
if ((err = mutexCreate(&eq->mutex)) < 0 || (err = condCreate(&eq->waitq)) < 0) { | ||
free(eq->buf); | ||
free(eq); | ||
return err; | ||
} | ||
|
||
*res = eq; | ||
|
||
return EOK; | ||
} | ||
|
||
|
||
void event_queue_put(event_queue_t *eq, unsigned char event, unsigned int min_size, unsigned int flags) | ||
{ | ||
if (!eq) | ||
return; | ||
|
||
mutexLock(eq->mutex); | ||
if (eq->count < eq->sz) { | ||
eq->buf[eq->w] = event; | ||
eq->w = (eq->w + 1) % eq->sz; | ||
eq->count++; | ||
if (eq->count >= min_size) | ||
condSignal(eq->waitq); | ||
} // else: discard | ||
mutexUnlock(eq->mutex); | ||
} | ||
|
||
|
||
int event_queue_get(event_queue_t *eq, void *dest, unsigned int size, unsigned int flags) | ||
{ | ||
int err; | ||
unsigned int bytes; | ||
|
||
if (!eq || !dest) | ||
return -1; | ||
|
||
if (size == 0) | ||
return 0; | ||
|
||
mutexLock(eq->mutex); | ||
do { | ||
if (flags & O_NONBLOCK && eq->count < size) { | ||
err = -EWOULDBLOCK; | ||
break; | ||
} | ||
|
||
while (eq->count < size) | ||
condWait(eq->waitq, eq->mutex, 0); | ||
|
||
if (eq->w < eq->r) | ||
memcpy(dest, eq->buf + eq->r, bytes = min(eq->count, eq->w - eq->r)); | ||
else { | ||
memcpy(dest, eq->buf + eq->r, bytes = min(size, eq->sz - eq->r)); | ||
|
||
if (bytes < size) { | ||
size -= bytes; | ||
memcpy(dest + bytes, eq->buf, min(size, eq->w)); | ||
bytes += min(size, eq->w); | ||
} | ||
} | ||
|
||
eq->r = (eq->r + bytes) % eq->sz; | ||
eq->count -= bytes; | ||
|
||
err = bytes; | ||
} while (0); | ||
mutexUnlock(eq->mutex); | ||
|
||
return err; | ||
} | ||
|
||
|
||
int event_queue_count(event_queue_t *eq) | ||
{ | ||
int res; | ||
|
||
if (!eq) | ||
return -1; | ||
|
||
mutexLock(eq->mutex); | ||
res = eq->count; | ||
mutexUnlock(eq->mutex); | ||
|
||
return res; | ||
} | ||
|
||
|
||
void event_queue_destroy(event_queue_t *eq) | ||
{ | ||
if (!eq) | ||
return; | ||
|
||
resourceDestroy(eq->mutex); | ||
resourceDestroy(eq->waitq); | ||
free(eq->buf); | ||
free(eq); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Phoenix-RTOS | ||
* | ||
* Simple circular buffer for enqueueing PS/2 events | ||
* | ||
* Copyright 2024 Phoenix Systems | ||
* Author: Adam Greloch | ||
* | ||
* This file is part of Phoenix-RTOS. | ||
* | ||
* %LICENSE% | ||
*/ | ||
|
||
|
||
#ifndef _EVENT_QUEUE_H_ | ||
#define _EVENT_QUEUE_H_ | ||
|
||
|
||
typedef struct _event_queue_t event_queue_t; | ||
|
||
|
||
/* Initializes event queue */ | ||
extern int event_queue_init(event_queue_t **res, unsigned int sz); | ||
|
||
|
||
/* Puts a byte to event queue. If queue has more than min_size bytes, wake readers. If queue is full, does nothing */ | ||
extern void event_queue_put(event_queue_t *eq, unsigned char event, unsigned int min_size, unsigned int flags); | ||
|
||
|
||
/* Reads data from event queue */ | ||
extern int event_queue_get(event_queue_t *eq, void *dest, unsigned int size, unsigned int flags); | ||
|
||
|
||
/* Retrieves number of bytes stored in event queue */ | ||
extern int event_queue_count(event_queue_t *eq); | ||
|
||
|
||
/* Destroys event queue */ | ||
extern void event_queue_destroy(event_queue_t *eq); | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.