Skip to content

Commit

Permalink
pc-tty: add PS/2 mouse support and kbd/mouse vdevs
Browse files Browse the repository at this point in the history
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 and virtual devices are opt-in and can be enabled
via board_config.h.

JIRA: RTOS-896
  • Loading branch information
adamgreloch committed Aug 26, 2024
1 parent 159684b commit 41e575c
Show file tree
Hide file tree
Showing 8 changed files with 816 additions and 71 deletions.
132 changes: 132 additions & 0 deletions tty/pc-tty/event_queue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* 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%
*/


#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/threads.h>
#include <sys/minmax.h>

#include "event_queue.h"


int event_queue_init(event_queue_t *eq)
{
int err;

if (eq == NULL)
return EINVAL;

memset(eq, 0, sizeof(event_queue_t));

err = mutexCreate(&eq->mutex);
if (err < 0) {
return err;
}

err = condCreate(&eq->waitq);
if (err < 0) {
resourceDestroy(eq->mutex);
return err;
}

return EOK;
}


void event_queue_put(event_queue_t *eq, unsigned char event, unsigned int min_size, unsigned int flags)
{
if (eq == NULL)
return;

mutexLock(eq->mutex);
if (eq->count < TTYPC_EQBUF_SIZE) {
eq->buf[eq->w] = event;
eq->w = (eq->w + 1) % TTYPC_EQBUF_SIZE;
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) != 0 && 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, TTYPC_EQBUF_SIZE - 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) % TTYPC_EQBUF_SIZE;
eq->count -= bytes;

err = bytes;
} while (0);
mutexUnlock(eq->mutex);

return err;
}


int event_queue_count(event_queue_t *eq)
{
int res;

if (eq == NULL)
return -1;

mutexLock(eq->mutex);
res = eq->count;
mutexUnlock(eq->mutex);

return res;
}


void event_queue_destroy(event_queue_t *eq)
{
if (eq == NULL)
return;

resourceDestroy(eq->waitq);
resourceDestroy(eq->mutex);
}
52 changes: 52 additions & 0 deletions tty/pc-tty/event_queue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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_

#include <sys/threads.h>

#define TTYPC_EQBUF_SIZE 256

typedef struct _event_queue_t {
unsigned char buf[TTYPC_EQBUF_SIZE];
unsigned int count;
unsigned int r;
unsigned int w;
handle_t mutex;
handle_t waitq;
} event_queue_t;


/* Initializes event queue */
extern int event_queue_init(event_queue_t *eq);


/* 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
32 changes: 27 additions & 5 deletions tty/pc-tty/ttypc.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <sys/types.h>

#include "ttypc_vt.h"
#include "board_config.h"
#include "event_queue.h"


/* Number of virtual terminals */
Expand Down Expand Up @@ -45,7 +47,6 @@ enum {
KB_EXT = 0x0400
};


struct _ttypc_t {
unsigned int port; /* Driver port */

Expand All @@ -59,10 +60,31 @@ struct _ttypc_t {
unsigned char ktype; /* Keyboard type */
unsigned char lockst; /* Lock keys state */
unsigned char shiftst; /* Shift keys state */
unsigned int kirq; /* Interrupt number */
handle_t klock; /* Interrupt mutex */
handle_t kcond; /* Interrupt condition variable */
handle_t kinth; /* Interrupt handle */
handle_t kmcond; /* Kbd/mouse interrupt condition variable */

unsigned int kirq; /* Kbd interrupt number */
handle_t klock; /* Kbd interrupt mutex */
handle_t kinth; /* Kbd interrupt handle */

#if PC_TTY_ENABLE_MOUSE
unsigned int mirq; /* Mouse interrupt number */
handle_t minth; /* Mouse interrupt handle */
#endif

#if PC_TTY_CREATE_PS2_VDEVS
event_queue_t keq; /* Kbd event buffer */
unsigned int kport; /* Kbd device port */

/* Kbd pool thread stack */
char kpstack[1024] __attribute__((aligned(8)));
#if PC_TTY_ENABLE_MOUSE
event_queue_t meq; /* Mouse event buffer */
unsigned int mport; /* Mouse device port */

/* Mouse pool thread stack */
char mpstack[1024] __attribute__((aligned(8)));
#endif
#endif

/* Virtual terminals */
ttypc_vt_t *vt; /* Active virtual terminal */
Expand Down
Loading

0 comments on commit 41e575c

Please sign in to comment.