commit 61d67952bb7d89f33f258407967f721c83a3bdb6 from: Onana Onana Xavier Manuel date: Mon Aug 10 04:12:15 2026 UTC Initial import commit - /dev/null commit + 61d67952bb7d89f33f258407967f721c83a3bdb6 blob - /dev/null blob + 3fe7ac0b03427301f6a7db54eee5351014c539d2 (mode 644) --- /dev/null +++ README @@ -0,0 +1,11 @@ +This directory contains the source code for the ria +graphics system that can be built and run on OpenBSD +when drm is turned off. + +prot.h Protocol used by libria +ria/ The server +libria/ Interface to comunicate with ria + +The goal of this system is to have a simple graphics +system that can be easily understood with very little +code. blob - /dev/null blob + 865ecbcdaae71fb7e4353f4dca931f34451adcca (mode 644) --- /dev/null +++ TODO @@ -0,0 +1,7 @@ +- Emulate Plan9 by making the window system both a + a shell and an image. Look at openpty(3) and + pty(4). This will allow nested instances. + +- Define a proper and well documented protocol :^). + +- Make a couple of demo programs using the protocol. blob - /dev/null blob + 20d4bcef726a4cbf96ffbb605738e9ba4a899377 (mode 644) --- /dev/null +++ libria/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2026 Onana Onana Xavier Manuel + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. blob - /dev/null blob + 4588c35f26e9400c256ab1d9c2e6c8ddc5724074 (mode 644) --- /dev/null +++ libria/Makefile @@ -0,0 +1,31 @@ +CC=cc +LIB=libria +SRCS=\ + draw.c +OBJS=${SRCS:.c=.o} +PREFIX=/usr/local +CFLAGS=-O0 -Wall -Werror -I ../ +HDRS=\ + draw.h\ + event.h\ + ../prot.h + +${LIB}: ${OBJS} ${HDRS} + ar rc ${LIB}.a ${OBJS} + +install: ${LIB} + install -d ${PREFIX} ${PREFIX}/include/ria + install -m 644 ${HDRS} ${PREFIX}/include/ria + install -m 644 ${LIB}.a ${PREFIX}/lib + +uninstall: + rm -rf ${PREFIX}/include/ria + rm -rf ${PREFIX}/lib/${LIB}.a + +.c.o: + ${CC} -c $< -o $@ ${CFLAGS} + +clean: + rm -rf ${OBJS} ${LIB}.a + +.PHONY: clean blob - /dev/null blob + 09011e6ee5930249e0cd4db1af20daad61e3695e (mode 644) --- /dev/null +++ libria/draw.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "prot.h" +#include "draw.h" + +static int _connect(void); + +struct ria_display *ria_display; + +int +ria_init() +{ + if (_connect() == -1) + return -1; + + return 0; +} + +int +ria_draw() +{ + struct msg dmsg; + + dmsg.type = MSG_TYPE_DRAW; + dmsg.len = sizeof(dmsg); + + if (send(ria_display->fd, &dmsg, dmsg.len, 0) == -1) + return -1; + + return 0; +} + +static int +_connect() +{ + struct sockaddr_un addr; + + if (ria_display != NULL) { + errno = EPERM; + return -1; + } + + if ((ria_display = calloc(1, sizeof(*ria_display))) == NULL) + return -1; + + if ((ria_display->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return -1; + } + + addr.sun_family = AF_UNIX; + memset(addr.sun_path, 0, sizeof(addr.sun_path)); + strncpy(addr.sun_path, RIA_SOCK_PATH, sizeof(addr.sun_path)); + + if (connect(ria_display->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + close(ria_display->fd); + free(ria_display); + return -1; + } + + return 0; +} blob - /dev/null blob + 5d22f9421f0836d35b1a637f27a0a0fe548798b6 (mode 644) --- /dev/null +++ libria/draw.h @@ -0,0 +1,17 @@ +#ifndef _RIA_DRAW_H_ +#define _RIA_DRAW_H_ + +struct ria_display { + int fd; +}; + +int ria_init(void); +int ria_draw(void); + + +/* + * Global variables + */ +extern struct ria_display *ria_display; + +#endif blob - /dev/null blob + 4237e2d1848d82bf9e16ede9fffe9efa49dfd5d5 (mode 644) --- /dev/null +++ libria/event.h @@ -0,0 +1,4 @@ +#ifndef _RIA_EVENT_H_ +#define _RIA_EVENT_H_ + +#endif blob - /dev/null blob + 19b99122f4a2cc2cc6a0bf3110a20d08e92dfb6c (mode 644) --- /dev/null +++ prot.h @@ -0,0 +1,10 @@ +#define RIA_SOCK_PATH "/tmp/ria.sock" + +enum msg_type { + MSG_TYPE_DRAW, +}; + +struct msg { + enum msg_type type; + uint32_t len; +}; blob - /dev/null blob + 20d4bcef726a4cbf96ffbb605738e9ba4a899377 (mode 644) --- /dev/null +++ ria/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2026 Onana Onana Xavier Manuel + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. blob - /dev/null blob + 0c3d3f212aa575bf622fffd69b5eb30525e9bf0a (mode 644) --- /dev/null +++ ria/Makefile @@ -0,0 +1,27 @@ +CC=cc +BIN=ria +SRCS=\ + ria.c\ + cursor.c\ + event.c\ + kmap.c\ + wsctl.c\ + fb.c + +OBJS=${SRCS:.c=.o} +CFLAGS=-O0 -Wall -Werror -I ../ +HDRS=\ + fb.h\ + wsctl.h\ + event.h + +${BIN}: ${OBJS} ${HDRS} + ${CC} ${OBJS} -o ${BIN} + +.c.o: + ${CC} -fPIE -c $< -o $@ ${CFLAGS} + +clean: + rm -rf ${BIN} ${BIN}.core ${OBJS} + +.PHONY: clean blob - /dev/null blob + 34f28370755e3f1e3a70108a7d6750d82667d3e8 (mode 644) --- /dev/null +++ ria/README @@ -0,0 +1,31 @@ +This is intended to run on OpenBSD. + +Features: + +- No drm + +- No web browser + +- Plenty of screen tearing + +- No ttf/otf + +- US encoding only + +- usb keyboard device only supported + +- and more + +- No keybinding because i18n sucks + +- also, its kinda cool? + +Tutorial: + +- disable inteldrm/radeondrm + +- make + +- ria + +- ascend blob - /dev/null blob + 2c22d89edd26ebfa94da6439d811b57b062e1d00 (mode 644) --- /dev/null +++ ria/cursor.c @@ -0,0 +1,13 @@ +#include "fb.h" + +void +button_press(int button) +{ + cursor.held[button] = 1; +} + +void +button_release(int button) +{ + cursor.held[button] = 0; +} blob - /dev/null blob + e21f2827e4fdc2ef70f01790ef3584b4b9d14971 (mode 644) --- /dev/null +++ ria/event.c @@ -0,0 +1,32 @@ +#include + +#include "event.h" + +#define EVENT_QUEUE_SIZE 255 + +static struct event queue[EVENT_QUEUE_SIZE]; +static size_t head; +static size_t tail; + +void +event_push(struct event *ev) +{ + size_t n = (head + 1) % EVENT_QUEUE_SIZE; + + if (n == tail) + return; + + queue[head] = *ev; + head = n; +} + +int +event_pop(struct event *ev) +{ + if (head == tail) + return -1; + + *ev = queue[tail]; + tail = (tail + 1) % EVENT_QUEUE_SIZE; + return 0; +} blob - /dev/null blob + 20f5100703baaeb641ad8e2a8e91efac2807c34d (mode 644) --- /dev/null +++ ria/event.h @@ -0,0 +1,35 @@ +enum event_type { + EVENT_TYPE_MOUSE, + EVENT_TYPE_KEYBOARD +}; + +enum event_list { + EVENT_KEY_DOWN, + EVENT_KEY_UP, + EVENT_MOUSE_MOTION, + EVENT_MOUSE_PRESS, + EVENT_MOUSE_RELEASE, +}; + +struct mouse_event { + int type; + int x, y; + int button; +}; + +struct kbd_event { + int type; + int key; +}; + +struct event { + enum event_type type; + + union { + struct mouse_event mouse; + struct kbd_event kbd; + }; +}; + +void event_push(struct event*); +int event_pop(struct event*); blob - /dev/null blob + 8849d4de6d84a880961be9319d2b5ab1f9c50bbf (mode 644) --- /dev/null +++ ria/fb.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include "fb.h" + +struct fbinfo *fb; +struct cursor cursor; + +int +intersects(struct rectangle *, struct rectangle *); + +/* + * Expects 32 bits + */ +void +fill(unsigned int value) +{ + uint32_t *data = (uint32_t *)fb->bdat; + + /* + * 4 channels ARGB + */ + for (size_t i = 0; i < fb->bytes/4; i++) + data[i] = value; + + damage(&(struct rectangle) { 0, 0, fb->width, fb->height }); +} + +void +draw_cursor() +{ + int x1 = cursor.x; + int y1 = cursor.y; + + int x2 = cursor.x + CURSOR_WIDTH; + int y2 = cursor.y + CURSOR_HEIGHT; + + uint32_t *dat = (uint32_t *)fb->dat; + + /* Clamp */ + if (x2 > fb->width) x2 = fb->width; + if (y2 > fb->height) y2 = fb->height; + + for (int j = y1; j < y2; j++) { + int idx = j * fb->width + x1; + memcpy(dat + idx, cursor.bits, (x2 - x1) * 4); + } +} + +void +damage(struct rectangle *rect) +{ + int x1 = rect->x1 < rect->x2 ? rect->x1 : rect->x2; + int y1 = rect->y1 < rect->y2 ? rect->y1 : rect->y2; + int x2 = rect->x1 < rect->x2 ? rect->x2 : rect->x1; + int y2 = rect->y1 < rect->y2 ? rect->y2 : rect->y1; + + /* CLAMP */ + if (x1 > fb->width) x1 = fb->width; + if (x2 > fb->width) x2 = fb->width; + if (y1 > fb->height) y1 = fb->height; + if (y2 > fb->height) y2 = fb->height; + + if (x1 < 0) { x2 = (x2 - x1); x1 = 0; } + if (y1 < 0) { y2 = (y2 - y1); y1 = 0; } + + uint32_t *bdat = (uint32_t *)fb->bdat; + uint32_t *dat = (uint32_t *)fb->dat; + + for (int j = y1; j < y2; j++) { + int idx = j * fb->width + x1; + memcpy(dat + idx, bdat + idx, (x2 - x1) * 4); /* 4 channels */ + } +} + + +int intersects(struct rectangle *a, struct rectangle *b) +{ + return (a->x1 <= b->x2 && a->x2 >= b->x2) && (a->y1 <= b->y2 && a->y2 >= b->y1); +} blob - /dev/null blob + b1b7b1f224308bbf60c20abd12306a19a4a191d4 (mode 644) --- /dev/null +++ ria/fb.h @@ -0,0 +1,41 @@ +#include + +#define CURSOR_WIDTH 16 +#define CURSOR_HEIGHT 16 + +#define BUTTON_1 0 +#define BUTTON_2 1 +#define BUTTON_3 2 + +struct cursor { + unsigned char bits[CURSOR_WIDTH * CURSOR_HEIGHT * 4]; + unsigned char held[3]; + int16_t x; + int16_t y; +}; + +struct rectangle { + int x1; + int y1; + int x2; + int y2; +}; + +struct fbinfo { + unsigned int width; + unsigned int height; + unsigned int depth; + void *dat; + void *bdat; /* back-buffer */ + size_t bytes; +}; + +void fill(unsigned int); +void draw_cursor(); +void damage(struct rectangle *); + +void button_press(int); +void button_release(int); + +extern struct fbinfo *fb; +extern struct cursor cursor; blob - /dev/null blob + 5e6dfb744c4e93a1e07353ce7fc4a5d72043639d (mode 644) --- /dev/null +++ ria/kbd.h @@ -0,0 +1,5 @@ +struct kbd_map { + int keysym; +}; + +int get_kbd_map(struct kbd_map **, unsigned int, int); blob - /dev/null blob + 98b14321611425116ca425cff8db37ac7581f2b0 (mode 644) --- /dev/null +++ ria/kmap.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include "kbd.h" + +/* + * Source: /usr/include/dev/usb/ukbmap.c + * + * This is shit + */ +static struct kbd_map usb_us[] = { +/* keysym */ + [0x04] = { KS_a }, + [0x05] = { KS_b }, + [0x06] = { KS_c }, + [0x07] = { KS_d }, + [0x08] = { KS_e }, + [0x09] = { KS_f }, + [0x0A] = { KS_g }, + [0x0B] = { KS_h }, + [0x0C] = { KS_i }, + [0x0D] = { KS_j }, + [0x0E] = { KS_k }, + [0x0F] = { KS_l }, + [0x10] = { KS_m }, + [0x11] = { KS_n }, + [0x12] = { KS_o }, + [0x13] = { KS_p }, + [0x14] = { KS_q }, + [0x15] = { KS_r }, + [0x16] = { KS_s }, + [0x17] = { KS_t }, + [0x18] = { KS_u }, + [0x19] = { KS_v }, + [0x1A] = { KS_w }, + [0x1B] = { KS_x }, + [0x1C] = { KS_y }, + [0x1D] = { KS_z }, + [0x1E] = { KS_1 }, + [0x1F] = { KS_2 }, + [0x20] = { KS_3 }, + [0x21] = { KS_4 }, + [0x22] = { KS_5 }, + [0x23] = { KS_6 }, + [0x24] = { KS_7 }, + [0x25] = { KS_8 }, + [0x26] = { KS_9 }, + [0x27] = { KS_0 }, + [0x28] = { KS_Return }, + [0x29] = { KS_Escape }, + [0x2A] = { KS_Delete }, + [0x2B] = { KS_Tab }, + [0x2C] = { KS_space }, + [0x2D] = { KS_minus }, + [0x2E] = { KS_equal }, + [0x2F] = { KS_bracketleft }, + [0x30] = { KS_bracketright }, + [0x31] = { KS_backslash }, + [0x32] = { KS_backslash }, + [0x33] = { KS_semicolon }, + [0x34] = { KS_apostrophe }, + [0x35] = { KS_grave }, + [0x36] = { KS_comma }, + [0x37] = { KS_period }, + [0x38] = { KS_slash }, + [0x39] = { KS_Caps_Lock }, + [0x3A] = { KS_f1 }, + [0x3B] = { KS_f2 }, + [0x3C] = { KS_f3 }, + [0x3D] = { KS_f4 }, + [0x3E] = { KS_f5 }, + [0x3F] = { KS_f6 }, + [0x40] = { KS_f7 }, + [0x41] = { KS_f8 }, + [0x42] = { KS_f9 }, + [0x43] = { KS_f10 }, + [0x44] = { KS_f11 }, + [0x45] = { KS_f12 }, + [0x46] = { KS_Print_Screen }, + [0x47] = { KS_Hold_Screen }, + [0x48] = { KS_Pause }, + [0x49] = { KS_Insert }, + [0x4A] = { KS_Home }, + [0x4B] = { KS_Prior }, + [0x4C] = { KS_KP_Delete }, + [0x4D] = { KS_End }, + [0x4E] = { KS_Next }, + [0x4F] = { KS_Right }, + [0x50] = { KS_Left }, + [0x51] = { KS_Down }, + [0x52] = { KS_Up }, + [0x53] = { KS_Num_Lock }, + [0x54] = { KS_KP_Divide }, + [0x55] = { KS_KP_Multiply }, + [0x56] = { KS_KP_Subtract }, + [0x57] = { KS_KP_Add }, + [0x58] = { KS_KP_Enter }, + [0x59] = { KS_KP_1 }, + [0x5A] = { KS_KP_2 }, + [0x5B] = { KS_KP_3 }, + [0x5C] = { KS_KP_4 }, + [0x5D] = { KS_KP_5 }, + [0x5E] = { KS_KP_6 }, + [0x5F] = { KS_KP_7 }, + [0x60] = { KS_KP_8 }, + [0x61] = { KS_KP_9 }, + [0x62] = { KS_KP_0 }, + [0x63] = { KS_KP_Delete }, /* 100 don't exists */ + [0x64] = { KS_Menu }, + [0x66] = { KS_Cmd_Sleep }, /* 103 either */ + [0x68] = { KS_f13 }, + [0x69] = { KS_f14 }, + [0x6A] = { KS_f15 }, + [0x6B] = { KS_f16 }, + [0x6C] = { KS_f17 }, + [0x6D] = { KS_f18 }, + [0x6E] = { KS_f19 }, + [0x6F] = { KS_f20 }, + [0x70] = { KS_f21 }, + [0x71] = { KS_f22 }, + [0x72] = { KS_f23 }, + [0x73] = { KS_f24 }, + [0x74] = { KS_Open }, + [0x75] = { KS_Help }, + [0x76] = { KS_Props }, + [0x77] = { KS_Front }, + [0x78] = { KS_Cmd }, + [0x79] = { KS_Again }, + [0x7A] = { KS_Undo }, + [0x7B] = { KS_Cut }, + [0x7C] = { KS_Copy }, + [0x7D] = { KS_Paste }, + [0x7E] = { KS_Find }, + [0x7F] = { KS_AudioMute }, + [0x80] = { KS_AudioRaise }, + [0x81] = { KS_AudioLower }, /* Keys [130, 223] are empty */ + [0xE0] = { KS_Control_L }, + [0xE1] = { KS_Shift_L }, + [0xE2] = { KS_Alt_L }, + [0xE3] = { KS_Meta_L }, + [0xE4] = { KS_Control_R }, + [0xE5] = { KS_Shift_R }, + [0xE6] = { KS_Alt_R }, + [0xE7] = { KS_Meta_R }, + [0xE8] = { KS_Cmd_BrightnessUp }, + [0xE9] = { KS_Cmd_BrightnessDown }, + [0xEA] = { KS_Cmd_KbdBacklightToggle }, + [0xEB] = { KS_Cmd_KbdBacklightUp }, + [0xEC] = { KS_Cmd_KbdBacklightDown }, +}; + +int +get_kbd_map(struct kbd_map **kmap, unsigned int type, int encoding) +{ + size_t size = sizeof(usb_us) / sizeof(*usb_us); + *kmap = usb_us; + return size; +} blob - /dev/null blob + 26df1a54c2f1d50fa99ea19e36ebb01633ff6594 (mode 644) --- /dev/null +++ ria/ria.1 @@ -0,0 +1,36 @@ +.Dd $Mdocdate: August 09 2026$ +.Dt RIA 1 +.Os +.Sh NAME +.Nm ria +.Nd rio is amazing +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +.Nm +was created to emulate some of the functionalities of +.Xr rio 1 +and window managers like +.Xr cwm 1 +in order to create a coherent and simple system on +OpenBSD. + +Just as in +.Xr rio 1 +most operations are handled by the mouse. Keybinding +is not supported for shortcut and is not planned in the +future. This is partly to avoid i18n issues and keep the +system simple. +.Sh CAVEATS +For now it only supports 32-bit depth displays and keyboard +driver support is limited to +.Xr ukbd 4 +with us encoding. + +.Xr pckbd 4 +support will be added later. +.Sh SEE ALSO +.Xr cwm 1 , +.Xr rio 1 +.Sh AUTHORS +.An Onana Onana Xavier Manuel Aq Mt xavier@onana.net blob - /dev/null blob + f3eee918ea7d3b2b6bf59106d11e3d56588550d0 (mode 644) --- /dev/null +++ ria/ria.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include + +#include + +#include "wsctl.h" +#include "event.h" +#include "fb.h" + +static volatile sig_atomic_t running = 1; + +void read_kbd(struct kbd_event *); +void read_mouse(struct mouse_event *); + +void int_handler(int); + +/* + * TODO: + * Check ttyname to see if it starts with ttyC[0-N] + * to prevent remote execution of ria(1). + */ + +int +main() +{ + struct event ev; + int ret; + + signal(SIGTERM, int_handler); + signal(SIGINT, int_handler); + + if ((fb = wsctl_init()) == NULL) { + return -1; + } + + fill(0xFF7F7F7F); + draw_cursor(); + + while (running) { + if ((ret = wsctl_run()) == -1) + break; + + while (event_pop(&ev) != -1) { + switch (ev.type) { + case EVENT_TYPE_KEYBOARD: + read_kbd(&ev.kbd); + break; + case EVENT_TYPE_MOUSE: + read_mouse(&ev.mouse); + break; + } + } + } + + fill(0); + wsctl_exit(); +} + + +void +read_kbd(struct kbd_event *kev) +{ + switch (kev->type) { + case EVENT_KEY_DOWN: + if (kev->key == KS_q) + running = 0; + break; + default: + break; + } +} + +void +read_mouse(struct mouse_event *mev) +{ + switch (mev->type) { + case EVENT_MOUSE_MOTION: { + struct rectangle old; + + old.x1 = cursor.x; + old.y1 = cursor.y; + old.x2 = old.x1 + CURSOR_WIDTH; + old.y2 = old.y1 + CURSOR_HEIGHT; + + cursor.x += mev->x; + cursor.y += mev->y; + + if (cursor.x < 0) + cursor.x = 0; + + if (cursor.y < 0) + cursor.y = 0; + + if (cursor.x >= fb->width) + cursor.x = fb->width - 1; + + if (cursor.y >= fb->height) + cursor.y = fb->height - 1; + + damage(&old); + draw_cursor(); + break; + } + case EVENT_MOUSE_PRESS: + if (mev->button >= 0 && mev->button < 3) + button_press(mev->button); + break; + case EVENT_MOUSE_RELEASE: + if (mev->button >= 0 && mev->button < 3) + button_release(mev->button); + break; + default: + break; + } +} + +void +int_handler(int sig) +{ + running = 0; +} blob - /dev/null blob + 9e8340f2a0f48187013f4f16af117daa104484e4 (mode 644) --- /dev/null +++ ria/wsctl.c @@ -0,0 +1,429 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "prot.h" +#include "fb.h" +#include "kbd.h" +#include "event.h" +#include "wsctl.h" + +static int init_kbd(void); +static int init_mouse(void); +static int read_kbd(void); +static int read_mouse(void); +static int read_cmd(void); +static int sock_init(void); +static void sock_exit(void); + +static struct { + int fd; + struct { + int fd; + } mouse; + struct { + int fd; + int maplen; + struct kbd_map *map; + } kbd; + + struct { + int fd; + socklen_t len; + struct sockaddr_un addr; + } sock; + + struct fbinfo *fb; +} wsctl; + +struct fbinfo* +wsctl_init() +{ + int mode = WSDISPLAYIO_MODE_DUMBFB; + struct wsdisplay_fbinfo fbinfo; + struct fbinfo *fbi; + + if ((fbi = malloc(sizeof(*fbi))) == 0) { + fprintf(stderr, "failed to allocate fbinfo\n"); + return NULL; + } + + /* + * TODO: + * Open the active tty instead of /dev/ttyC0 + */ + + if((wsctl.fd = open("/dev/ttyC4", O_RDWR | O_EXCL)) == -1) { + perror("failed to open tty file descriptor"); + free(fbi); + return NULL; + } + + if (init_mouse() == -1) { + close(wsctl.fd); + free(fbi); + return NULL; + } + + if (init_kbd() == -1) { + close(wsctl.mouse.fd); + close(wsctl.fd); + free(fbi); + return NULL; + } + + if (sock_init() == -1) { + close(wsctl.mouse.fd); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(fbi); + } + + if (ioctl(wsctl.fd, WSDISPLAYIO_GINFO, &fbinfo) == -1) { + perror("failed to fetch display information"); + close(wsctl.mouse.fd); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(fbi); + return NULL; + } + + fbi->height = fbinfo.height; + fbi->width = fbinfo.width; + fbi->depth = fbinfo.depth; + + /* + * For now we only support ARGB + */ + if (fbi->depth != 32) { + close(wsctl.mouse.fd); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(fbi); + errno=ENOTSUP; + return NULL; + } + + if ((fbi->bdat = calloc(1, fbi->width * fbi->height * fbi->depth / 8)) == NULL) { + close(wsctl.mouse.fd); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(fbi); + return NULL; + } + + if (ioctl(wsctl.fd, WSDISPLAYIO_SMODE, &mode) == -1) { + perror("could not initialize the framebuffer"); + close(wsctl.mouse.fd); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(fbi); + return NULL; + } + + fbi->bytes = fbi->width * fbi->height * fbi->depth / 8; + + fbi->dat = mmap(NULL, fbi->bytes, PROT_WRITE | PROT_READ, MAP_SHARED, wsctl.fd, 0); + + if (fbi->dat == MAP_FAILED) { + perror("could not map frame buffer"); + mode = WSDISPLAYIO_MODE_EMUL; + ioctl(wsctl.fd, WSDISPLAYIO_SMODE, &mode); + close(wsctl.mouse.fd); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(fbi); + return NULL; + } + + + cursor.x = fbi->width / 2; + cursor.y = fbi->height / 2; + wsctl.fb = fbi; + + return fbi; +} + +void +wsctl_exit() +{ + int mode; + + if (ioctl(wsctl.fd, WSDISPLAYIO_GMODE, &mode) == -1) + perror("failed to get video mode"); + else { + if (mode != WSDISPLAYIO_MODE_EMUL) { + mode = WSDISPLAYIO_MODE_EMUL; + munmap(wsctl.fb->dat, wsctl.fb->bytes); + + if (ioctl(wsctl.fd, WSDISPLAYIO_SMODE, &mode) == -1) + perror("failed to smode to emul"); + } + } + + close(wsctl.mouse.fd); + free(wsctl.fb->bdat); + close(wsctl.kbd.fd); + close(wsctl.fd); + free(wsctl.fb); + sock_exit(); +} + +int +wsctl_run() +{ + struct pollfd pfds[3]; + int ret; + + pfds[0].fd = wsctl.mouse.fd; + pfds[1].fd = wsctl.kbd.fd; + pfds[2].fd = wsctl.sock.fd; + + pfds[0].events = POLLIN; + pfds[1].events = POLLIN; + pfds[2].events = POLLIN; + + ret = poll(pfds, 3, -1); + + if (ret == -1) { + if (errno == EINTR) + return 0; + + perror("poll"); + return -1; + } + + if (pfds[0].revents & POLLIN) + read_mouse(); + + if (pfds[1].revents & POLLIN) + read_kbd(); + + if (pfds[2].revents & POLLIN) + read_cmd(); + + return 0; +} + +static int +init_mouse() +{ + if ((wsctl.mouse.fd = open("/dev/wsmouse", O_RDONLY | O_NONBLOCK)) == -1) { + perror("failed to open mouse"); + return -1; + } + return 0; +} + +/* + * There is probably a better way to do this but unfortunately I did + * not found 1. The method is getting the encoding, getting the type + * usb/pckb etc, and then mapping the ev.value to a lookup table to + * get a keysym. + * + * This makes it so we have to create a lookup table for every single + * device and every encoding. For now only usbkb and us encoding will + * be supported. + */ +static int +init_kbd() +{ + kbd_t encoding; + u_int type; + + if ((wsctl.kbd.fd = open("/dev/wskbd", O_RDONLY | O_NONBLOCK)) == -1) { + perror("failed to open keyboard"); + return -1; + } + + if (ioctl(wsctl.kbd.fd, WSKBDIO_GETENCODING, &encoding) == -1) { + close(wsctl.kbd.fd); + return -1; + } + + if (ioctl(wsctl.kbd.fd, WSKBDIO_GTYPE, &type) == -1) { + close(wsctl.kbd.fd); + return -1; + } + + switch (type) { + case WSKBD_TYPE_USB: + break; + default: + close(wsctl.kbd.fd); + errno = ENOTSUP; + return -1; + } + + switch (encoding) { + case KB_US: + break; + default: + close(wsctl.kbd.fd); + errno = ENOTSUP; + return -1; + } + + wsctl.kbd.maplen = get_kbd_map(&wsctl.kbd.map, encoding, type); + + return 0; +} + + +static int +read_mouse() +{ + unsigned char flags[WSCONS_EVENT_SYNC + 1] = { 0 }; + struct event mev = { 0 }; + struct wscons_event ev; + int n; + + while ((n = read(wsctl.mouse.fd, &ev, sizeof(ev))) > 0) { + switch (ev.type) { + case WSCONS_EVENT_MOUSE_DELTA_X: + mev.mouse.x = ev.value; + break; + case WSCONS_EVENT_MOUSE_DELTA_Y: + mev.mouse.y = -ev.value; + break; + /* Event ready */ + case WSCONS_EVENT_SYNC: + break; + /* Unsupported events */ + case WSCONS_EVENT_MOUSE_UP: + mev.mouse.button = ev.value; + break; + case WSCONS_EVENT_MOUSE_DOWN: + mev.mouse.button = ev.value; + break; + case WSCONS_EVENT_MOUSE_DELTA_Z: + case WSCONS_EVENT_MOUSE_DELTA_W: + case WSCONS_EVENT_MOUSE_ABSOLUTE_W: + case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: + case WSCONS_EVENT_MOUSE_ABSOLUTE_X: + case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: + continue; + } + + flags[ev.type] = 1; + + if (flags[WSCONS_EVENT_SYNC] == 1) { + if (flags[WSCONS_EVENT_MOUSE_DELTA_X] || flags[WSCONS_EVENT_MOUSE_DELTA_Y]) { + mev.mouse.type = EVENT_MOUSE_MOTION; + mev.type = EVENT_TYPE_MOUSE; + + flags[WSCONS_EVENT_MOUSE_DELTA_X] = 0; + flags[WSCONS_EVENT_MOUSE_DELTA_Y] = 0; + } + + if (flags[WSCONS_EVENT_MOUSE_DOWN]) { + mev.mouse.type = EVENT_MOUSE_PRESS; + mev.type = EVENT_TYPE_MOUSE; + + flags[WSCONS_EVENT_MOUSE_DOWN] = 0; + } + + if (flags[WSCONS_EVENT_MOUSE_UP]) { + mev.mouse.type = EVENT_MOUSE_RELEASE; + mev.type = EVENT_TYPE_MOUSE; + + flags[WSCONS_EVENT_MOUSE_UP] = 0; + } + + event_push(&mev); + flags[WSCONS_EVENT_SYNC] = 0; + } + } + return 0; +} + +static int +read_kbd() +{ + struct wscons_event ev; + int keysym; + int n; + + while ((n = read(wsctl.kbd.fd, &ev, sizeof(ev))) > 0) { + struct event push = { 0 }; + push.type = EVENT_TYPE_KEYBOARD; + + switch (ev.type) { + case WSCONS_EVENT_KEY_DOWN: + if (ev.value < 0 || ev.value >= wsctl.kbd.maplen) + continue; + + keysym = wsctl.kbd.map[ev.value].keysym; + push.kbd.type = EVENT_KEY_DOWN; + push.kbd.key = keysym; + break; + case WSCONS_EVENT_KEY_UP: + if (ev.value < 0 || ev.value >= wsctl.kbd.maplen) + continue; + + keysym = wsctl.kbd.map[ev.value].keysym; + push.kbd.type = EVENT_KEY_UP; + push.kbd.key = keysym; + break; + /* Not supported */ + default: + continue; + } + + event_push(&push); + } + return 0; +} + +int +read_cmd() +{ + return 0; +} + + +static int +sock_init() +{ + if ((wsctl.sock.fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) + return -1; + + wsctl.sock.addr.sun_family = AF_UNIX; + memset(wsctl.sock.addr.sun_path, 0, sizeof(wsctl.sock.addr.sun_path)); + strncpy(wsctl.sock.addr.sun_path, RIA_SOCK_PATH, sizeof(wsctl.sock.addr.sun_path)); + + wsctl.sock.len = sizeof(wsctl.sock.addr); + + if (bind(wsctl.sock.fd, (struct sockaddr *)&wsctl.sock.addr, wsctl.sock.len) == -1) { + close(wsctl.sock.fd); + return -1; + } + + if (listen(wsctl.sock.fd, SOMAXCONN)) { + perror("failed to listen"); + close(wsctl.sock.fd); + return -1; + } + + return 0; +} + +static void +sock_exit() +{ + unlink(RIA_SOCK_PATH); +} blob - /dev/null blob + 53028ef6deb1cf043d22636af2f10570970397b5 (mode 644) --- /dev/null +++ ria/wsctl.h @@ -0,0 +1,3 @@ +struct fbinfo *wsctl_init(void); +void wsctl_exit(void); +int wsctl_run(void);