start new makefile, migrate to libpicofe

This commit is contained in:
notaz 2013-06-22 19:16:08 +03:00
parent 4685e5a10e
commit e743be2070
47 changed files with 246 additions and 6342 deletions

View file

@ -1,97 +0,0 @@
# settings
#use_fbdev = 1
#fake_in_gp2x = 1
use_musashi = 1
#use_fame = 1
use_cz80 = 1
use_sh2drc = 1
#use_sh2mame = 1
#drc_debug = 3
#drc_debug_interp = 1
#profile = 1
all: mkdirs PicoDrive
-include Makefile.local
ifndef ARCH
ARCH = x86
endif
DEFINES = _UNZIP_SUPPORT IO_STATS IN_EVDEV
CFLAGS += -ggdb -Wall -falign-functions=2
CFLAGS += -I../.. -I.
LDFLAGS += -lm -lpng
ifeq "$(ARCH)" "arm"
CFLAGS += -mcpu=arm920t
DEFINES += ARM
endif
CC ?= $(CROSS)gcc
# frontend
OBJS += io.o emu.o blit.o in_evdev.o plat.o sndout_oss.o log_io.o
# common
OBJS += platform/common/main.o platform/common/emu.o platform/common/menu_pico.o \
platform/common/config.o platform/common/fonts.o platform/common/readpng.o \
platform/common/input.o
ifeq "$(use_fbdev)" "1"
DEFINES += FBDEV
OBJS += fbdev.o
else
LDFLAGS += -lpthread
LDFLAGS += -lX11
endif
ifeq "$(fake_in_gp2x)" "1"
DEFINES += IN_GP2X FAKE_IN_GP2X
OBJS += platform/gp2x/in_gp2x.o
DIRS += platform/gp2x
endif
ifeq "$(ARCH)" "arm"
OBJS += pico/carthw/svp/stub_arm.o
endif
OBJS += pico/sound/mix.o
OBJS += pico/carthw/svp/compiler.o
# zlib
OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \
zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o zlib/uncompr.o
# unzip
OBJS += unzip/unzip.o unzip/unzip_stream.o
vpath %.c = ../..
vpath %.s = ../..
vpath %.S = ../..
vpath %.asm = ../..
DIRS += platform/linux zlib unzip
include ../common/common.mak
include ../common/revision.mak
CFLAGS += $(addprefix -D,$(DEFINES))
clean: tidy
@$(RM) PicoDrive
tidy:
$(RM) $(OBJS)
rm -rf $(DIRS)
@make -C ../../cpu/mz80/ clean
PicoDrive : $(OBJS)
@echo ">>>" $@
$(CC) $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=PicoDrive.map -o $@
pprof: pprof.c
$(CROSS)gcc -O2 -ggdb -DPPROF -DPPROF_TOOL -I../../ -I. $^ -o $@
%.o : %.asm
@echo ">>>" $<
nasm -f elf $< -o $@

View file

@ -6,11 +6,11 @@
#include <stdio.h>
#include <unistd.h>
#include "../libpicofe/menu.h"
#include "../libpicofe/plat.h"
#include "../libpicofe/linux/sndout_oss.h"
#include "../common/emu.h"
#include "../common/menu.h"
#include "../common/plat.h"
#include "../common/arm_utils.h"
#include "../linux/sndout_oss.h"
#include "version.h"
#include <pico/pico_int.h>

View file

@ -1,311 +0,0 @@
/*
* (C) Gražvydas "notaz" Ignotas, 2009-2010
*
* This work is licensed under the terms of any of these licenses
* (at your option):
* - GNU GPL, version 2 or later.
* - GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/fb.h>
#include <linux/matroxfb.h>
#include "fbdev.h"
#define PFX "fbdev: "
struct vout_fbdev {
int fd;
void *mem;
size_t mem_size;
struct fb_var_screeninfo fbvar_old;
struct fb_var_screeninfo fbvar_new;
int buffer_write;
int fb_size;
int buffer_count;
int top_border, bottom_border;
void *mem_saved;
size_t mem_saved_size;
};
void *vout_fbdev_flip(struct vout_fbdev *fbdev)
{
int draw_buf;
if (fbdev->buffer_count < 2)
return fbdev->mem;
draw_buf = fbdev->buffer_write;
fbdev->buffer_write++;
if (fbdev->buffer_write >= fbdev->buffer_count)
fbdev->buffer_write = 0;
fbdev->fbvar_new.yoffset =
(fbdev->top_border + fbdev->fbvar_new.yres + fbdev->bottom_border) * draw_buf +
fbdev->top_border;
ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write;
}
void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev)
{
int arg = 0;
ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg);
}
/* it is recommended to call vout_fbdev_clear() before this */
void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp,
int left_border, int right_border, int top_border, int bottom_border, int buffer_cnt)
{
int w_total = left_border + w + right_border;
int h_total = top_border + h + bottom_border;
size_t mem_size;
int ret;
// unblank to be sure the mode is really accepted
ioctl(fbdev->fd, FBIOBLANK, FB_BLANK_UNBLANK);
if (fbdev->fbvar_new.bits_per_pixel != bpp ||
fbdev->fbvar_new.xres != w ||
fbdev->fbvar_new.yres != h ||
fbdev->fbvar_new.xres_virtual != w_total||
fbdev->fbvar_new.yres_virtual < h_total ||
fbdev->fbvar_new.xoffset != left_border ||
fbdev->buffer_count != buffer_cnt)
{
if (fbdev->fbvar_new.bits_per_pixel != bpp ||
w != fbdev->fbvar_new.xres || h != fbdev->fbvar_new.yres)
printf(PFX "switching to %dx%d@%d\n", w, h, bpp);
fbdev->fbvar_new.xres = w;
fbdev->fbvar_new.yres = h;
fbdev->fbvar_new.xres_virtual = w_total;
fbdev->fbvar_new.yres_virtual = h_total * buffer_cnt;
fbdev->fbvar_new.xoffset = left_border;
fbdev->fbvar_new.yoffset = top_border;
fbdev->fbvar_new.bits_per_pixel = bpp;
fbdev->fbvar_new.nonstd = 0; // can set YUV here on omapfb
fbdev->buffer_count = buffer_cnt;
fbdev->buffer_write = buffer_cnt > 1 ? 1 : 0;
// seems to help a bit to avoid glitches
vout_fbdev_wait_vsync(fbdev);
ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
if (ret == -1) {
// retry with no multibuffering
fbdev->fbvar_new.yres_virtual = h_total;
ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
if (ret == -1) {
perror(PFX "FBIOPUT_VSCREENINFO ioctl");
return NULL;
}
fbdev->buffer_count = 1;
fbdev->buffer_write = 0;
fprintf(stderr, PFX "Warning: failed to increase virtual resolution, "
"multibuffering disabled\n");
}
}
fbdev->fb_size = w_total * h_total * bpp / 8;
fbdev->top_border = top_border;
fbdev->bottom_border = bottom_border;
mem_size = fbdev->fb_size * fbdev->buffer_count;
if (fbdev->mem_size >= mem_size)
goto out;
if (fbdev->mem != NULL)
munmap(fbdev->mem, fbdev->mem_size);
fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) {
fprintf(stderr, PFX "Warning: can't map %zd bytes, doublebuffering disabled\n", mem_size);
fbdev->buffer_count = 1;
fbdev->buffer_write = 0;
mem_size = fbdev->fb_size;
fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
}
if (fbdev->mem == MAP_FAILED) {
fbdev->mem = NULL;
fbdev->mem_size = 0;
perror(PFX "mmap framebuffer");
return NULL;
}
fbdev->mem_size = mem_size;
out:
return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write;
}
void vout_fbdev_clear(struct vout_fbdev *fbdev)
{
memset(fbdev->mem, 0, fbdev->mem_size);
}
void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count)
{
int stride = fbdev->fbvar_new.xres_virtual * fbdev->fbvar_new.bits_per_pixel / 8;
int i;
if (y + count > fbdev->top_border + fbdev->fbvar_new.yres)
count = fbdev->top_border + fbdev->fbvar_new.yres - y;
if (y >= 0 && count > 0)
for (i = 0; i < fbdev->buffer_count; i++)
memset((char *)fbdev->mem + fbdev->fb_size * i + y * stride, 0, stride * count);
}
int vout_fbdev_get_fd(struct vout_fbdev *fbdev)
{
return fbdev->fd;
}
struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int bpp, int buffer_cnt)
{
struct vout_fbdev *fbdev;
int req_w, req_h;
void *pret;
int ret;
fbdev = calloc(1, sizeof(*fbdev));
if (fbdev == NULL)
return NULL;
fbdev->fd = open(fbdev_name, O_RDWR);
if (fbdev->fd == -1) {
fprintf(stderr, PFX "%s: ", fbdev_name);
perror("open");
goto fail_open;
}
ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old);
if (ret == -1) {
perror(PFX "FBIOGET_VSCREENINFO ioctl");
goto fail;
}
fbdev->fbvar_new = fbdev->fbvar_old;
req_w = fbdev->fbvar_new.xres;
if (*w != 0)
req_w = *w;
req_h = fbdev->fbvar_new.yres;
if (*h != 0)
req_h = *h;
pret = vout_fbdev_resize(fbdev, req_w, req_h, bpp, 0, 0, 0, 0, buffer_cnt);
if (pret == NULL)
goto fail;
printf(PFX "%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_new.xres,
fbdev->fbvar_new.yres, fbdev->fbvar_new.bits_per_pixel);
*w = fbdev->fbvar_new.xres;
*h = fbdev->fbvar_new.yres;
memset(fbdev->mem, 0, fbdev->mem_size);
// some checks
ret = 0;
ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret);
if (ret != 0)
fprintf(stderr, PFX "Warning: vsync doesn't seem to be supported\n");
if (fbdev->buffer_count > 1) {
fbdev->buffer_write = 0;
fbdev->fbvar_new.yoffset = fbdev->fbvar_new.yres * (fbdev->buffer_count - 1);
ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new);
if (ret != 0) {
fbdev->buffer_count = 1;
fprintf(stderr, PFX "Warning: can't pan display, doublebuffering disabled\n");
}
}
printf("fbdev initialized.\n");
return fbdev;
fail:
close(fbdev->fd);
fail_open:
free(fbdev);
return NULL;
}
static void vout_fbdev_release(struct vout_fbdev *fbdev)
{
ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old);
if (fbdev->mem != MAP_FAILED)
munmap(fbdev->mem, fbdev->mem_size);
fbdev->mem = NULL;
}
int vout_fbdev_save(struct vout_fbdev *fbdev)
{
void *tmp;
if (fbdev == NULL || fbdev->mem == NULL || fbdev->mem == MAP_FAILED) {
fprintf(stderr, PFX "bad args for save\n");
return -1;
}
if (fbdev->mem_saved_size < fbdev->mem_size) {
tmp = realloc(fbdev->mem_saved, fbdev->mem_size);
if (tmp == NULL)
return -1;
fbdev->mem_saved = tmp;
}
memcpy(fbdev->mem_saved, fbdev->mem, fbdev->mem_size);
fbdev->mem_saved_size = fbdev->mem_size;
vout_fbdev_release(fbdev);
return 0;
}
int vout_fbdev_restore(struct vout_fbdev *fbdev)
{
int ret;
if (fbdev == NULL || fbdev->mem != NULL) {
fprintf(stderr, PFX "bad args/state for restore\n");
return -1;
}
fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0);
if (fbdev->mem == MAP_FAILED) {
perror(PFX "restore: memory restore failed");
return -1;
}
memcpy(fbdev->mem, fbdev->mem_saved, fbdev->mem_size);
ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new);
if (ret == -1) {
perror(PFX "restore: FBIOPUT_VSCREENINFO");
return -1;
}
return 0;
}
void vout_fbdev_finish(struct vout_fbdev *fbdev)
{
vout_fbdev_release(fbdev);
if (fbdev->fd >= 0)
close(fbdev->fd);
fbdev->fd = -1;
free(fbdev);
}

View file

@ -1,14 +0,0 @@
struct vout_fbdev;
struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int bpp, int buffer_count);
void *vout_fbdev_flip(struct vout_fbdev *fbdev);
void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev);
void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp,
int left_border, int right_border, int top_border, int bottom_border,
int buffer_count);
void vout_fbdev_clear(struct vout_fbdev *fbdev);
void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count);
int vout_fbdev_get_fd(struct vout_fbdev *fbdev);
int vout_fbdev_save(struct vout_fbdev *fbdev);
int vout_fbdev_restore(struct vout_fbdev *fbdev);
void vout_fbdev_finish(struct vout_fbdev *fbdev);

View file

@ -1,655 +0,0 @@
/*
* (C) Gražvydas "notaz" Ignotas, 2008-2010
*
* This work is licensed under the terms of any of these licenses
* (at your option):
* - GNU GPL, version 2 or later.
* - GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/input.h>
#include <errno.h>
#include "../common/input.h"
#include "in_evdev.h"
#define MAX_ABS_DEVS 8
typedef struct {
int fd;
int *kbits;
int abs_min_x; /* abs->digital mapping */
int abs_max_x;
int abs_min_y;
int abs_max_y;
int abs_lzone;
int abs_lastx;
int abs_lasty;
int kc_first;
int kc_last;
unsigned int abs_count;
int abs_mult[MAX_ABS_DEVS]; /* 16.16 multiplier to IN_ABS_RANGE */
int abs_adj[MAX_ABS_DEVS]; /* adjust for centering */
unsigned int abs_to_digital:1;
} in_evdev_t;
#ifndef KEY_CNT
#define KEY_CNT (KEY_MAX + 1)
#endif
#define KEYBITS_BIT(x) (keybits[(x)/sizeof(keybits[0])/8] & \
(1 << ((x) & (sizeof(keybits[0])*8-1))))
#define KEYBITS_BIT_SET(x) (keybits[(x)/sizeof(keybits[0])/8] |= \
(1 << ((x) & (sizeof(keybits[0])*8-1))))
#define KEYBITS_BIT_CLEAR(x) (keybits[(x)/sizeof(keybits[0])/8] &= \
~(1 << ((x) & (sizeof(keybits[0])*8-1))))
int in_evdev_allow_abs_only;
#define IN_EVDEV_PREFIX "evdev:"
static const char * const in_evdev_keys[KEY_CNT] = {
[0 ... KEY_MAX] = NULL,
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
[KEY_3] = "3", [KEY_4] = "4",
[KEY_5] = "5", [KEY_6] = "6",
[KEY_7] = "7", [KEY_8] = "8",
[KEY_9] = "9", [KEY_0] = "0",
[KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal",
[KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab",
[KEY_Q] = "Q", [KEY_W] = "W",
[KEY_E] = "E", [KEY_R] = "R",
[KEY_T] = "T", [KEY_Y] = "Y",
[KEY_U] = "U", [KEY_I] = "I",
[KEY_O] = "O", [KEY_P] = "P",
[KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace",
[KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl",
[KEY_A] = "A", [KEY_S] = "S",
[KEY_D] = "D", [KEY_F] = "F",
[KEY_G] = "G", [KEY_H] = "H",
[KEY_J] = "J", [KEY_K] = "K",
[KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon",
[KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave",
[KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash",
[KEY_Z] = "Z", [KEY_X] = "X",
[KEY_C] = "C", [KEY_V] = "V",
[KEY_B] = "B", [KEY_N] = "N",
[KEY_M] = "M", [KEY_COMMA] = "Comma",
[KEY_DOT] = "Dot", [KEY_SLASH] = "Slash",
[KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk",
[KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space",
[KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1",
[KEY_F2] = "F2", [KEY_F3] = "F3",
[KEY_F4] = "F4", [KEY_F5] = "F5",
[KEY_F6] = "F6", [KEY_F7] = "F7",
[KEY_F8] = "F8", [KEY_F9] = "F9",
[KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock",
[KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7",
[KEY_KP8] = "KP8", [KEY_KP9] = "KP9",
[KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4",
[KEY_KP5] = "KP5", [KEY_KP6] = "KP6",
[KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1",
[KEY_KP2] = "KP2", [KEY_KP3] = "KP3",
[KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot",
[KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
[KEY_F11] = "F11", [KEY_F12] = "F12",
[KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter",
[KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash",
[KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt",
[KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home",
[KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp",
[KEY_LEFT] = "Left", [KEY_RIGHT] = "Right",
[KEY_END] = "End", [KEY_DOWN] = "Down",
[KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert",
[KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro",
[KEY_HELP] = "Help", [KEY_MENU] = "Menu",
[KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction",
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
[BTN_4] = "Btn4", [BTN_5] = "Btn5",
[BTN_6] = "Btn6", [BTN_7] = "Btn7",
[BTN_8] = "Btn8", [BTN_9] = "Btn9",
[BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn",
[BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn",
[BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn",
[BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn",
[BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn",
[BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn",
[BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn",
[BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2",
[BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4",
[BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6",
[BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA",
[BTN_B] = "BtnB", [BTN_C] = "BtnC",
[BTN_X] = "BtnX", [BTN_Y] = "BtnY",
[BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL",
[BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2",
[BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
[BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
[BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
[BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
[BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
};
static void in_evdev_probe(void)
{
long keybits[KEY_CNT / sizeof(long) / 8];
long absbits[(ABS_MAX+1) / sizeof(long) / 8];
int i;
// the kernel might support and return less keys then we know about,
// so make sure the buffers are clear.
memset(keybits, 0, sizeof(keybits));
memset(absbits, 0, sizeof(absbits));
for (i = 0;; i++)
{
int support = 0, count = 0;
int u, ret, fd, kc_first = KEY_MAX, kc_last = 0, have_abs = 0;
in_evdev_t *dev;
char name[64];
snprintf(name, sizeof(name), "/dev/input/event%d", i);
fd = open(name, O_RDONLY|O_NONBLOCK);
if (fd == -1) {
if (errno == EACCES)
continue; /* maybe we can access next one */
break;
}
/* check supported events */
ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support);
if (ret == -1) {
printf("in_evdev: ioctl failed on %s\n", name);
goto skip;
}
if (support & (1 << EV_KEY)) {
ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
if (ret == -1) {
printf("in_evdev: ioctl failed on %s\n", name);
goto skip;
}
/* check for interesting keys */
for (u = 0; u < KEY_CNT; u++) {
if (KEYBITS_BIT(u)) {
if (u < kc_first)
kc_first = u;
if (u > kc_last)
kc_last = u;
if (u != KEY_POWER && u != KEY_SLEEP && u != BTN_TOUCH)
count++;
if (u == BTN_TOUCH) /* we can't deal with ts currently */
goto skip;
}
}
}
dev = calloc(1, sizeof(*dev));
if (dev == NULL)
goto skip;
ret = ioctl(fd, EVIOCGKEY(sizeof(keybits)), keybits);
if (ret == -1) {
printf("Warning: EVIOCGKEY not supported, will have to track state\n");
dev->kbits = calloc(KEY_CNT, sizeof(int));
if (dev->kbits == NULL) {
free(dev);
goto skip;
}
}
/* check for abs too */
if (support & (1 << EV_ABS)) {
struct input_absinfo ainfo;
int dist;
ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits);
if (ret == -1)
goto no_abs;
if (absbits[0] & (1 << ABS_X)) {
ret = ioctl(fd, EVIOCGABS(ABS_X), &ainfo);
if (ret == -1)
goto no_abs;
dist = ainfo.maximum - ainfo.minimum;
dev->abs_lzone = dist / 4;
dev->abs_min_x = ainfo.minimum;
dev->abs_max_x = ainfo.maximum;
}
if (absbits[0] & (1 << ABS_Y)) {
ret = ioctl(fd, EVIOCGABS(ABS_Y), &ainfo);
if (ret == -1)
goto no_abs;
dist = ainfo.maximum - ainfo.minimum;
dev->abs_min_y = ainfo.minimum;
dev->abs_max_y = ainfo.maximum;
}
for (u = 0; u < MAX_ABS_DEVS; u++) {
ret = ioctl(fd, EVIOCGABS(u), &ainfo);
if (ret == -1)
break;
dist = ainfo.maximum - ainfo.minimum;
if (dist != 0)
dev->abs_mult[u] = IN_ABS_RANGE * 2 * 65536 / dist;
dev->abs_adj[u] = -(ainfo.maximum + ainfo.minimum + 1) / 2;
have_abs = 1;
}
dev->abs_count = u;
}
no_abs:
if (count == 0 && !have_abs) {
free(dev);
goto skip;
}
dev->fd = fd;
dev->kc_first = kc_first;
dev->kc_last = kc_last;
if (count > 0 || in_evdev_allow_abs_only)
dev->abs_to_digital = 1;
strcpy(name, IN_EVDEV_PREFIX);
ioctl(fd, EVIOCGNAME(sizeof(name)-6), name+6);
printf("in_evdev: found \"%s\" with %d events (type %08x)\n",
name+6, count, support);
in_register(name, fd, dev, KEY_CNT, in_evdev_keys, 0);
continue;
skip:
close(fd);
}
}
static void in_evdev_free(void *drv_data)
{
in_evdev_t *dev = drv_data;
if (dev == NULL)
return;
close(dev->fd);
free(dev);
}
static const char * const *
in_evdev_get_key_names(int *count)
{
*count = KEY_CNT;
return in_evdev_keys;
}
static void or_binds(const int *binds, int key, int *result)
{
int t;
for (t = 0; t < IN_BINDTYPE_COUNT; t++)
result[t] |= binds[IN_BIND_OFFS(key, t)];
}
/* ORs result with binds of pressed buttons
* XXX: should measure performance hit of this func, might need to optimize */
static int in_evdev_update(void *drv_data, const int *binds, int *result)
{
struct input_event ev[16];
struct input_absinfo ainfo;
int keybits_[KEY_CNT / sizeof(int)];
int *keybits = keybits_;
in_evdev_t *dev = drv_data;
int rd, ret, u, lzone;
if (dev->kbits == NULL) {
ret = ioctl(dev->fd, EVIOCGKEY(sizeof(keybits_)), keybits_);
if (ret == -1) {
perror("in_evdev: ioctl failed");
return -1;
}
}
else {
keybits = dev->kbits;
while (1) {
rd = read(dev->fd, ev, sizeof(ev));
if (rd < (int)sizeof(ev[0])) {
if (errno != EAGAIN)
perror("in_evdev: read failed");
break;
}
for (u = 0; u < rd / sizeof(ev[0]); u++) {
if (ev[u].type != EV_KEY)
continue;
else if (ev[u].value == 1)
KEYBITS_BIT_SET(ev[u].code);
else if (ev[u].value == 0)
KEYBITS_BIT_CLEAR(ev[u].code);
}
}
}
for (u = dev->kc_first; u <= dev->kc_last; u++) {
if (KEYBITS_BIT(u))
or_binds(binds, u, result);
}
/* map X and Y absolute to UDLR */
lzone = dev->abs_lzone;
if (dev->abs_to_digital && lzone != 0) {
ret = ioctl(dev->fd, EVIOCGABS(ABS_X), &ainfo);
if (ret != -1) {
if (ainfo.value < dev->abs_min_x + lzone) or_binds(binds, KEY_LEFT, result);
if (ainfo.value > dev->abs_max_x - lzone) or_binds(binds, KEY_RIGHT, result);
}
ret = ioctl(dev->fd, EVIOCGABS(ABS_Y), &ainfo);
if (ret != -1) {
if (ainfo.value < dev->abs_min_y + lzone) or_binds(binds, KEY_UP, result);
if (ainfo.value > dev->abs_max_y - lzone) or_binds(binds, KEY_DOWN, result);
}
}
return 0;
}
static int in_evdev_update_analog(void *drv_data, int axis_id, int *result)
{
struct input_absinfo ainfo;
in_evdev_t *dev = drv_data;
int ret;
if ((unsigned int)axis_id >= MAX_ABS_DEVS)
return -1;
ret = ioctl(dev->fd, EVIOCGABS(axis_id), &ainfo);
if (ret != 0)
return ret;
*result = (ainfo.value + dev->abs_adj[axis_id]) * dev->abs_mult[axis_id];
*result >>= 16;
return 0;
}
static int in_evdev_set_blocking(in_evdev_t *dev, int y)
{
long flags;
int ret;
flags = (long)fcntl(dev->fd, F_GETFL);
if ((int)flags == -1) {
perror("in_evdev: F_GETFL fcntl failed");
return -1;
}
if (flags & O_NONBLOCK) {
/* flush the event queue */
struct input_event ev;
do {
ret = read(dev->fd, &ev, sizeof(ev));
}
while (ret == sizeof(ev));
}
if (y)
flags &= ~O_NONBLOCK;
else
flags |= O_NONBLOCK;
ret = fcntl(dev->fd, F_SETFL, flags);
if (ret == -1) {
perror("in_evdev: F_SETFL fcntl failed");
return -1;
}
return 0;
}
static int in_evdev_get_config(void *drv_data, int what, int *val)
{
in_evdev_t *dev = drv_data;
switch (what) {
case IN_CFG_ABS_AXIS_COUNT:
*val = dev->abs_count;
break;
default:
return -1;
}
return 0;
}
static int in_evdev_set_config(void *drv_data, int what, int val)
{
in_evdev_t *dev = drv_data;
int tmp;
switch (what) {
case IN_CFG_BLOCKING:
return in_evdev_set_blocking(dev, val);
case IN_CFG_ABS_DEAD_ZONE:
if (val < 1 || val > 99 || dev->abs_lzone == 0)
return -1;
/* XXX: based on X axis only, for now.. */
tmp = (dev->abs_max_x - dev->abs_min_x) / 2;
dev->abs_lzone = tmp - tmp * val / 100;
if (dev->abs_lzone < 1)
dev->abs_lzone = 1;
else if (dev->abs_lzone >= tmp)
dev->abs_lzone = tmp - 1;
break;
default:
return -1;
}
return 0;
}
static int in_evdev_update_keycode(void *data, int *is_down)
{
int ret_kc = -1, ret_down = 0;
in_evdev_t *dev = data;
struct input_event ev;
int rd;
/* do single event, the caller sometimes wants
* to do select() in blocking mode */
rd = read(dev->fd, &ev, sizeof(ev));
if (rd < (int) sizeof(ev)) {
if (errno != EAGAIN) {
perror("in_evdev: error reading");
//sleep(1);
ret_kc = -2;
}
goto out;
}
if (ev.type == EV_KEY) {
if (ev.value < 0 || ev.value > 1)
goto out;
ret_kc = ev.code;
ret_down = ev.value;
goto out;
}
else if (ev.type == EV_ABS && dev->abs_to_digital)
{
int lzone = dev->abs_lzone, down = 0, *last;
// map absolute to up/down/left/right
if (lzone != 0 && ev.code == ABS_X) {
if (ev.value < dev->abs_min_x + lzone)
down = KEY_LEFT;
else if (ev.value > dev->abs_max_x - lzone)
down = KEY_RIGHT;
last = &dev->abs_lastx;
}
else if (lzone != 0 && ev.code == ABS_Y) {
if (ev.value < dev->abs_min_y + lzone)
down = KEY_UP;
else if (ev.value > dev->abs_max_y - lzone)
down = KEY_DOWN;
last = &dev->abs_lasty;
}
else
goto out;
if (down == *last)
goto out;
if (down == 0 || *last != 0) {
/* key up or direction change, return up event for old key */
ret_kc = *last;
ret_down = 0;
*last = 0;
goto out;
}
ret_kc = *last = down;
ret_down = 1;
goto out;
}
out:
if (is_down != NULL)
*is_down = ret_down;
return ret_kc;
}
static const struct {
short key;
short pbtn;
} key_pbtn_map[] =
{
{ KEY_UP, PBTN_UP },
{ KEY_DOWN, PBTN_DOWN },
{ KEY_LEFT, PBTN_LEFT },
{ KEY_RIGHT, PBTN_RIGHT },
/* XXX: maybe better set this from it's plat code somehow */
/* Pandora */
{ KEY_END, PBTN_MOK },
{ KEY_PAGEDOWN, PBTN_MBACK },
{ KEY_HOME, PBTN_MA2 },
{ KEY_PAGEUP, PBTN_MA3 },
{ KEY_LEFTCTRL, PBTN_MENU },
{ KEY_RIGHTSHIFT, PBTN_L },
{ KEY_RIGHTCTRL, PBTN_R },
/* Caanoo */
{ BTN_THUMB2, PBTN_MOK },
{ BTN_THUMB, PBTN_MBACK },
{ BTN_TRIGGER, PBTN_MA2 },
{ BTN_TOP, PBTN_MA3 },
{ BTN_BASE, PBTN_MENU },
{ BTN_TOP2, PBTN_L },
{ BTN_PINKIE, PBTN_R },
/* "normal" keyboards */
{ KEY_ENTER, PBTN_MOK },
{ KEY_ESC, PBTN_MBACK },
{ KEY_A, PBTN_MA2 },
{ KEY_S, PBTN_MA3 },
{ KEY_BACKSLASH, PBTN_MENU },
{ KEY_LEFTBRACE, PBTN_L },
{ KEY_RIGHTBRACE, PBTN_R },
};
#define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
static int in_evdev_menu_translate(void *drv_data, int keycode, char *charcode)
{
in_evdev_t *dev = drv_data;
int ret = 0;
int i;
if (keycode < 0)
{
/* menu -> kc */
keycode = -keycode;
for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
if (key_pbtn_map[i].pbtn == keycode) {
int k = key_pbtn_map[i].key;
/* should really check EVIOCGBIT, but this is enough for now */
if (dev->kc_first <= k && k <= dev->kc_last)
return k;
}
}
else
{
for (i = 0; i < KEY_PBTN_MAP_SIZE; i++) {
if (key_pbtn_map[i].key == keycode) {
ret = key_pbtn_map[i].pbtn;
break;
}
}
if (charcode != NULL && (unsigned int)keycode < KEY_CNT &&
in_evdev_keys[keycode] != NULL && in_evdev_keys[keycode][1] == 0)
{
char c = in_evdev_keys[keycode][0];
if ('A' <= c && c <= 'Z')
c = 'a' + c - 'A';
ret |= PBTN_CHAR;
*charcode = c;
}
}
return ret;
}
/* remove binds of missing keys, count remaining ones */
static int in_evdev_clean_binds(void *drv_data, int *binds, int *def_binds)
{
int keybits[KEY_CNT / sizeof(int)];
in_evdev_t *dev = drv_data;
int i, t, ret, offs, count = 0;
memset(keybits, 0, sizeof(keybits));
ret = ioctl(dev->fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
if (ret == -1) {
perror("in_evdev: ioctl failed");
// memset(keybits, 0xff, sizeof(keybits)); /* mark all as good */
}
if (dev->abs_to_digital && dev->abs_lzone != 0) {
KEYBITS_BIT_SET(KEY_LEFT);
KEYBITS_BIT_SET(KEY_RIGHT);
KEYBITS_BIT_SET(KEY_UP);
KEYBITS_BIT_SET(KEY_DOWN);
}
for (i = 0; i < KEY_CNT; i++) {
for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
offs = IN_BIND_OFFS(i, t);
if (!KEYBITS_BIT(i))
binds[offs] = def_binds[offs] = 0;
if (binds[offs])
count++;
}
}
return count;
}
static const in_drv_t in_evdev_drv = {
.prefix = IN_EVDEV_PREFIX,
.probe = in_evdev_probe,
.free = in_evdev_free,
.get_key_names = in_evdev_get_key_names,
.clean_binds = in_evdev_clean_binds,
.get_config = in_evdev_get_config,
.set_config = in_evdev_set_config,
.update = in_evdev_update,
.update_analog = in_evdev_update_analog,
.update_keycode = in_evdev_update_keycode,
.menu_translate = in_evdev_menu_translate,
};
void in_evdev_init(const struct in_default_bind *defbinds)
{
in_register_driver(&in_evdev_drv, defbinds);
}

View file

@ -2,11 +2,11 @@
#include <stdlib.h>
#include <string.h>
#include "../libpicofe/menu.h"
#include "../libpicofe/input.h"
#include "../libpicofe/linux/sndout_oss.h"
#include "../common/emu.h"
#include "../common/menu.h"
#include "../common/plat.h"
#include "../common/input.h"
#include "sndout_oss.h"
#include "../common/input_pico.h"
#include "version.h"
#include "log_io.h"

View file

@ -1,209 +0,0 @@
/*
* (C) Gražvydas "notaz" Ignotas, 2008-2010
*
* This work is licensed under the terms of any of these licenses
* (at your option):
* - GNU GPL, version 2 or later.
* - GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
*/
#define _GNU_SOURCE 1
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dirent.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include "../common/plat.h"
/* XXX: maybe unhardcode pagesize? */
#define HUGETLB_PAGESIZE (2 * 1024 * 1024)
#define HUGETLB_THRESHOLD (HUGETLB_PAGESIZE / 2)
#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000 /* arch specific */
#endif
int plat_is_dir(const char *path)
{
DIR *dir;
if ((dir = opendir(path))) {
closedir(dir);
return 1;
}
return 0;
}
int plat_get_root_dir(char *dst, int len)
{
int j, ret;
ret = readlink("/proc/self/exe", dst, len - 1);
if (ret < 0) {
perror("readlink");
ret = 0;
}
dst[ret] = 0;
for (j = strlen(dst); j > 0; j--)
if (dst[j] == '/') {
dst[++j] = 0;
break;
}
return j;
}
#ifdef __GP2X__
/* Wiz has a borked gettimeofday().. */
#define plat_get_ticks_ms plat_get_ticks_ms_good
#define plat_get_ticks_us plat_get_ticks_us_good
#endif
unsigned int plat_get_ticks_ms(void)
{
struct timeval tv;
unsigned int ret;
gettimeofday(&tv, NULL);
ret = (unsigned)tv.tv_sec * 1000;
/* approximate /= 1000 */
ret += ((unsigned)tv.tv_usec * 4195) >> 22;
return ret;
}
unsigned int plat_get_ticks_us(void)
{
struct timeval tv;
unsigned int ret;
gettimeofday(&tv, NULL);
ret = (unsigned)tv.tv_sec * 1000000;
ret += (unsigned)tv.tv_usec;
return ret;
}
void plat_sleep_ms(int ms)
{
usleep(ms * 1000);
}
int plat_wait_event(int *fds_hnds, int count, int timeout_ms)
{
struct timeval tv, *timeout = NULL;
int i, ret, fdmax = -1;
fd_set fdset;
if (timeout_ms >= 0) {
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
timeout = &tv;
}
FD_ZERO(&fdset);
for (i = 0; i < count; i++) {
if (fds_hnds[i] > fdmax) fdmax = fds_hnds[i];
FD_SET(fds_hnds[i], &fdset);
}
ret = select(fdmax + 1, &fdset, NULL, NULL, timeout);
if (ret == -1)
{
perror("plat_wait_event: select failed");
sleep(1);
return -1;
}
if (ret == 0)
return -1; /* timeout */
ret = -1;
for (i = 0; i < count; i++)
if (FD_ISSET(fds_hnds[i], &fdset))
ret = fds_hnds[i];
return ret;
}
void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
{
static int hugetlb_disabled;
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
void *req, *ret;
req = (void *)addr;
if (need_exec)
prot |= PROT_EXEC;
if (is_fixed)
flags |= MAP_FIXED;
if (size >= HUGETLB_THRESHOLD && !hugetlb_disabled)
flags |= MAP_HUGETLB;
ret = mmap(req, size, prot, flags, -1, 0);
if (ret == MAP_FAILED && (flags & MAP_HUGETLB)) {
fprintf(stderr,
"warning: failed to do hugetlb mmap (%p, %zu): %d\n",
req, size, errno);
hugetlb_disabled = 1;
flags &= ~MAP_HUGETLB;
ret = mmap(req, size, prot, flags, -1, 0);
}
if (ret == MAP_FAILED)
return NULL;
if (req != NULL && ret != req)
fprintf(stderr,
"warning: mmaped to %p, requested %p\n", ret, req);
return ret;
}
void *plat_mremap(void *ptr, size_t oldsize, size_t newsize)
{
void *ret;
ret = mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE);
if (ret == MAP_FAILED)
return NULL;
if (ret != ptr)
printf("warning: mremap moved: %p -> %p\n", ptr, ret);
return ret;
}
void plat_munmap(void *ptr, size_t size)
{
int ret;
ret = munmap(ptr, size);
if (ret != 0 && (size & (HUGETLB_PAGESIZE - 1))) {
// prehaps an autorounded hugetlb mapping?
size = (size + HUGETLB_PAGESIZE - 1) & ~(HUGETLB_PAGESIZE - 1);
ret = munmap(ptr, size);
}
if (ret != 0) {
fprintf(stderr,
"munmap(%p, %zu) failed: %d\n", ptr, size, errno);
}
}
/* lprintf */
void lprintf(const char *fmt, ...)
{
va_list vl;
va_start(vl, fmt);
vprintf(fmt, vl);
va_end(vl);
}

View file

@ -1,175 +0,0 @@
/* sound output via OSS */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <unistd.h>
#include "sndout_oss.h"
static int sounddev = -1, mixerdev = -1;
static int can_write_safe;
#define FRAG_COUNT 4
int sndout_oss_init(void)
{
if (mixerdev >= 0) close(mixerdev);
mixerdev = open("/dev/mixer", O_RDWR);
if (mixerdev == -1)
{
perror("open(\"/dev/mixer\")");
}
return 0;
}
void sndout_oss_stop(void)
{
if (sounddev < 0)
return;
ioctl(sounddev, SOUND_PCM_SYNC, 0);
close(sounddev);
sounddev = -1;
}
int sndout_oss_start(int rate, int stereo, int frames_in_frag)
{
static int s_oldrate = 0, s_oldstereo = 0;
int frag, bsize, bits, ret;
// GP2X: if no settings change, we don't need to do anything,
// since audio is never stopped there
if (sounddev >= 0 && rate == s_oldrate && s_oldstereo == stereo)
return 0;
sndout_oss_stop();
sounddev = open("/dev/dsp", O_WRONLY);
if (sounddev == -1)
{
perror("open(\"/dev/dsp\")");
sounddev = open("/dev/dsp1", O_WRONLY);
if (sounddev == -1) {
perror("open(\"/dev/dsp1\")");
return -1;
}
}
// try to fit frames_in_frag frames worth of data in fragment
// ignore mono because it's unlikely to be used and
// both GP2X and Wiz mixes mono to stereo anyway.
bsize = (frames_in_frag * rate / 50) * 4;
for (frag = 0; bsize; bsize >>= 1, frag++)
;
frag |= FRAG_COUNT << 16; // fragment count
ret = ioctl(sounddev, SNDCTL_DSP_SETFRAGMENT, &frag);
if (ret < 0)
perror("SNDCTL_DSP_SETFRAGMENT failed");
bits = 16;
ret = ioctl(sounddev, SNDCTL_DSP_STEREO, &stereo);
if (ret == 0)
ret = ioctl(sounddev, SNDCTL_DSP_SETFMT, &bits);
if (ret == 0)
ret = ioctl(sounddev, SNDCTL_DSP_SPEED, &rate);
if (ret < 0)
perror("failed to set audio format");
#ifdef __GP2X__
// not sure if this is still needed (avoiding driver bugs?)
usleep(192*1024);
#endif
printf("sndout_oss_start: %d/%dbit/%s, %d buffers of %i bytes\n",
rate, bits, stereo ? "stereo" : "mono", frag >> 16, 1 << (frag & 0xffff));
s_oldrate = rate; s_oldstereo = stereo;
can_write_safe = 0;
return 0;
}
int sndout_oss_write(const void *buff, int len)
{
return write(sounddev, buff, len);
}
#include "../common/plat.h"
/* not really non-blocking, just detects if blocking occurs
* and starts skipping writes in case it does. */
int sndout_oss_write_nb(const void *buff, int len)
{
static int lag_counter, skip_counter;
unsigned int t;
int ret;
if (lag_counter > 2) {
// skip writes if audio starts blocking
lag_counter = 0;
skip_counter = FRAG_COUNT;
}
if (skip_counter > 0) {
skip_counter--;
return len;
}
t = plat_get_ticks_ms();
ret = sndout_oss_write(buff, len);
t = plat_get_ticks_ms() - t;
if (t > 1) {
// this shouldn't really happen, most likely audio is out of sync
lag_counter++;
if (lag_counter > 2)
printf("audio lag %u\n", t);
}
else
lag_counter = 0;
return ret;
}
int sndout_oss_can_write(int bytes)
{
audio_buf_info bi;
int ret;
#ifdef __GP2X__
// note: SNDCTL_DSP_GETOSPACE crashes F100 kernel for some reason
// if called too early, so we work around here
if (can_write_safe++ < 8)
return 1;
#endif
ret = ioctl(sounddev, SNDCTL_DSP_GETOSPACE, &bi);
if (ret < 0)
return 1;
// have enough bytes to write + 1 frag
return bi.bytes - bi.fragsize >= bytes ? 1 : 0;
}
void sndout_oss_sync(void)
{
ioctl(sounddev, SOUND_PCM_SYNC, 0);
}
void sndout_oss_setvol(int l, int r)
{
if (mixerdev < 0) return;
l=l<0?0:l; l=l>255?255:l; r=r<0?0:r; r=r>255?255:r;
l<<=8; l|=r;
ioctl(mixerdev, SOUND_MIXER_WRITE_PCM, &l); /*SOUND_MIXER_WRITE_VOLUME*/
}
void sndout_oss_exit(void)
{
if (sounddev >= 0) close(sounddev); sounddev = -1;
if (mixerdev >= 0) close(mixerdev); mixerdev = -1;
}

View file

@ -1,9 +0,0 @@
int sndout_oss_init(void);
int sndout_oss_start(int rate, int stereo, int frames_in_frag);
void sndout_oss_stop(void);
int sndout_oss_write(const void *buff, int len);
int sndout_oss_write_nb(const void *buff, int len);
int sndout_oss_can_write(int bytes);
void sndout_oss_sync(void);
void sndout_oss_setvol(int l, int r);
void sndout_oss_exit(void);

View file

@ -1,455 +0,0 @@
/*
* (C) Gražvydas "notaz" Ignotas, 2009-2012
*
* This work is licensed under the terms of any of these licenses
* (at your option):
* - GNU GPL, version 2 or later.
* - GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <linux/kd.h>
#include "xenv.h"
#define PFX "xenv: "
#define FPTR(f) typeof(f) * p##f
#define FPTR_LINK(xf, dl, f) { \
xf.p##f = dlsym(dl, #f); \
if (xf.p##f == NULL) { \
fprintf(stderr, "missing symbol: %s\n", #f); \
goto fail; \
} \
}
struct xstuff {
Display *display;
Window window;
FPTR(XCreateBitmapFromData);
FPTR(XCreatePixmapCursor);
FPTR(XFreePixmap);
FPTR(XOpenDisplay);
FPTR(XDisplayName);
FPTR(XCloseDisplay);
FPTR(XCreateSimpleWindow);
FPTR(XChangeWindowAttributes);
FPTR(XSelectInput);
FPTR(XMapWindow);
FPTR(XNextEvent);
FPTR(XCheckTypedEvent);
FPTR(XWithdrawWindow);
FPTR(XGrabKeyboard);
FPTR(XPending);
FPTR(XLookupKeysym);
FPTR(XkbSetDetectableAutoRepeat);
FPTR(XStoreName);
FPTR(XIconifyWindow);
FPTR(XMoveResizeWindow);
FPTR(XInternAtom);
FPTR(XSetWMHints);
FPTR(XSync);
};
static struct xstuff g_xstuff;
static Cursor transparent_cursor(struct xstuff *xf, Display *display, Window win)
{
Cursor cursor;
Pixmap pix;
XColor dummy;
char d = 0;
memset(&dummy, 0, sizeof(dummy));
pix = xf->pXCreateBitmapFromData(display, win, &d, 1, 1);
cursor = xf->pXCreatePixmapCursor(display, pix, pix,
&dummy, &dummy, 0, 0);
xf->pXFreePixmap(display, pix);
return cursor;
}
static int x11h_init(int *xenv_flags, const char *window_title)
{
unsigned int display_width, display_height;
Display *display;
XSetWindowAttributes attributes;
Window win;
Visual *visual;
long evt_mask;
void *x11lib;
int screen;
memset(&g_xstuff, 0, sizeof(g_xstuff));
x11lib = dlopen("libX11.so.6", RTLD_LAZY);
if (x11lib == NULL) {
fprintf(stderr, "libX11.so load failed:\n%s\n", dlerror());
goto fail;
}
FPTR_LINK(g_xstuff, x11lib, XCreateBitmapFromData);
FPTR_LINK(g_xstuff, x11lib, XCreatePixmapCursor);
FPTR_LINK(g_xstuff, x11lib, XFreePixmap);
FPTR_LINK(g_xstuff, x11lib, XOpenDisplay);
FPTR_LINK(g_xstuff, x11lib, XDisplayName);
FPTR_LINK(g_xstuff, x11lib, XCloseDisplay);
FPTR_LINK(g_xstuff, x11lib, XCreateSimpleWindow);
FPTR_LINK(g_xstuff, x11lib, XChangeWindowAttributes);
FPTR_LINK(g_xstuff, x11lib, XSelectInput);
FPTR_LINK(g_xstuff, x11lib, XMapWindow);
FPTR_LINK(g_xstuff, x11lib, XNextEvent);
FPTR_LINK(g_xstuff, x11lib, XCheckTypedEvent);
FPTR_LINK(g_xstuff, x11lib, XWithdrawWindow);
FPTR_LINK(g_xstuff, x11lib, XGrabKeyboard);
FPTR_LINK(g_xstuff, x11lib, XPending);
FPTR_LINK(g_xstuff, x11lib, XLookupKeysym);
FPTR_LINK(g_xstuff, x11lib, XkbSetDetectableAutoRepeat);
FPTR_LINK(g_xstuff, x11lib, XStoreName);
FPTR_LINK(g_xstuff, x11lib, XIconifyWindow);
FPTR_LINK(g_xstuff, x11lib, XMoveResizeWindow);
FPTR_LINK(g_xstuff, x11lib, XInternAtom);
FPTR_LINK(g_xstuff, x11lib, XSetWMHints);
FPTR_LINK(g_xstuff, x11lib, XSync);
//XInitThreads();
g_xstuff.display = display = g_xstuff.pXOpenDisplay(NULL);
if (display == NULL)
{
fprintf(stderr, "cannot connect to X server %s, X handling disabled.\n",
g_xstuff.pXDisplayName(NULL));
goto fail2;
}
visual = DefaultVisual(display, 0);
if (visual->class != TrueColor)
fprintf(stderr, PFX "warning: non true color visual\n");
printf(PFX "X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display),
VendorRelease(display), DisplayString(display), ProtocolVersion(display),
ProtocolRevision(display));
screen = DefaultScreen(display);
display_width = DisplayWidth(display, screen);
display_height = DisplayHeight(display, screen);
printf(PFX "display is %dx%d\n", display_width, display_height);
g_xstuff.window = win = g_xstuff.pXCreateSimpleWindow(display,
RootWindow(display, screen), 0, 0, display_width, display_height,
0, BlackPixel(display, screen), BlackPixel(display, screen));
attributes.override_redirect = True;
attributes.cursor = transparent_cursor(&g_xstuff, display, win);
g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
if (window_title != NULL)
g_xstuff.pXStoreName(display, win, window_title);
evt_mask = ExposureMask | FocusChangeMask | PropertyChangeMask;
if (xenv_flags && (*xenv_flags & XENV_CAP_KEYS))
evt_mask |= KeyPressMask | KeyReleaseMask;
if (xenv_flags && (*xenv_flags & XENV_CAP_MOUSE))
evt_mask |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
g_xstuff.pXSelectInput(display, win, evt_mask);
g_xstuff.pXMapWindow(display, win);
g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
// XSetIOErrorHandler
// we don't know when event dispatch will be called, so sync now
g_xstuff.pXSync(display, False);
return 0;
fail2:
dlclose(x11lib);
fail:
g_xstuff.display = NULL;
fprintf(stderr, "x11 handling disabled.\n");
return -1;
}
static void x11h_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
int (*mouseb_cb)(void *cb_arg, int x, int y, int button, int is_pressed),
int (*mousem_cb)(void *cb_arg, int x, int y),
void *cb_arg)
{
XEvent evt;
int keysym;
while (g_xstuff.pXPending(g_xstuff.display))
{
g_xstuff.pXNextEvent(g_xstuff.display, &evt);
switch (evt.type)
{
case Expose:
while (g_xstuff.pXCheckTypedEvent(g_xstuff.display, Expose, &evt))
;
break;
case KeyPress:
keysym = g_xstuff.pXLookupKeysym(&evt.xkey, 0);
if (key_cb != NULL)
key_cb(cb_arg, keysym, 1);
break;
case KeyRelease:
keysym = g_xstuff.pXLookupKeysym(&evt.xkey, 0);
if (key_cb != NULL)
key_cb(cb_arg, keysym, 0);
break;
case ButtonPress:
if (mouseb_cb != NULL)
mouseb_cb(cb_arg, evt.xbutton.x, evt.xbutton.y,
evt.xbutton.button, 1);
break;
case ButtonRelease:
if (mouseb_cb != NULL)
mouseb_cb(cb_arg, evt.xbutton.x, evt.xbutton.y,
evt.xbutton.button, 0);
break;
case MotionNotify:
if (mousem_cb != NULL)
mousem_cb(cb_arg, evt.xmotion.x, evt.xmotion.y);
break;
}
}
}
static void x11h_wait_vmstate(void)
{
Atom wm_state = g_xstuff.pXInternAtom(g_xstuff.display, "WM_STATE", False);
XEvent evt;
int i;
usleep(20000);
for (i = 0; i < 20; i++) {
while (g_xstuff.pXPending(g_xstuff.display)) {
g_xstuff.pXNextEvent(g_xstuff.display, &evt);
// printf("w event %d\n", evt.type);
if (evt.type == PropertyNotify && evt.xproperty.atom == wm_state)
return;
}
usleep(200000);
}
fprintf(stderr, PFX "timeout waiting for wm_state change\n");
}
static int x11h_minimize(void)
{
XSetWindowAttributes attributes;
Display *display = g_xstuff.display;
Window window = g_xstuff.window;
int screen = DefaultScreen(g_xstuff.display);
int display_width, display_height;
XWMHints wm_hints;
XEvent evt;
g_xstuff.pXWithdrawWindow(display, window, screen);
attributes.override_redirect = False;
g_xstuff.pXChangeWindowAttributes(display, window,
CWOverrideRedirect, &attributes);
wm_hints.flags = StateHint;
wm_hints.initial_state = IconicState;
g_xstuff.pXSetWMHints(display, window, &wm_hints);
g_xstuff.pXMapWindow(display, window);
while (g_xstuff.pXNextEvent(display, &evt) == 0)
{
// printf("m event %d\n", evt.type);
switch (evt.type)
{
case FocusIn:
goto out;
default:
break;
}
}
out:
g_xstuff.pXWithdrawWindow(display, window, screen);
// must wait for some magic vmstate property change before setting override_redirect
x11h_wait_vmstate();
attributes.override_redirect = True;
g_xstuff.pXChangeWindowAttributes(display, window,
CWOverrideRedirect, &attributes);
// fixup window after resize on override_redirect loss
display_width = DisplayWidth(display, screen);
display_height = DisplayHeight(display, screen);
g_xstuff.pXMoveResizeWindow(display, window, 0, 0, display_width, display_height);
g_xstuff.pXMapWindow(display, window);
g_xstuff.pXGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, CurrentTime);
g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
// we don't know when event dispatch will be called, so sync now
g_xstuff.pXSync(display, False);
return 0;
}
static struct termios g_kbd_termios_saved;
static int g_kbdfd = -1;
static int tty_init(void)
{
struct termios kbd_termios;
int mode;
g_kbdfd = open("/dev/tty", O_RDWR);
if (g_kbdfd == -1) {
perror(PFX "open /dev/tty");
return -1;
}
if (ioctl(g_kbdfd, KDGETMODE, &mode) == -1) {
perror(PFX "(not hiding FB): KDGETMODE");
goto fail;
}
if (tcgetattr(g_kbdfd, &kbd_termios) == -1) {
perror(PFX "tcgetattr");
goto fail;
}
g_kbd_termios_saved = kbd_termios;
kbd_termios.c_lflag &= ~(ICANON | ECHO); // | ISIG);
kbd_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
kbd_termios.c_cc[VMIN] = 0;
kbd_termios.c_cc[VTIME] = 0;
if (tcsetattr(g_kbdfd, TCSAFLUSH, &kbd_termios) == -1) {
perror(PFX "tcsetattr");
goto fail;
}
if (ioctl(g_kbdfd, KDSETMODE, KD_GRAPHICS) == -1) {
perror(PFX "KDSETMODE KD_GRAPHICS");
tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved);
goto fail;
}
return 0;
fail:
close(g_kbdfd);
g_kbdfd = -1;
return -1;
}
static void tty_end(void)
{
if (g_kbdfd < 0)
return;
if (ioctl(g_kbdfd, KDSETMODE, KD_TEXT) == -1)
perror(PFX "KDSETMODE KD_TEXT");
if (tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved) == -1)
perror(PFX "tcsetattr");
close(g_kbdfd);
g_kbdfd = -1;
}
int xenv_init(int *xenv_flags, const char *window_title)
{
int ret;
ret = x11h_init(xenv_flags, window_title);
if (ret == 0)
goto out;
if (xenv_flags != NULL)
*xenv_flags &= ~(XENV_CAP_KEYS | XENV_CAP_MOUSE); /* TODO? */
ret = tty_init();
if (ret == 0)
goto out;
fprintf(stderr, PFX "error: both x11h_init and tty_init failed\n");
ret = -1;
out:
return ret;
}
int xenv_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
int (*mouseb_cb)(void *cb_arg, int x, int y, int button, int is_pressed),
int (*mousem_cb)(void *cb_arg, int x, int y),
void *cb_arg)
{
if (g_xstuff.display) {
x11h_update(key_cb, mouseb_cb, mousem_cb, cb_arg);
return 0;
}
// TODO: read tty?
return -1;
}
/* blocking minimize until user maximizes again */
int xenv_minimize(void)
{
int ret;
if (g_xstuff.display) {
xenv_update(NULL, NULL, NULL, NULL);
ret = x11h_minimize();
xenv_update(NULL, NULL, NULL, NULL);
return ret;
}
return -1;
}
void xenv_finish(void)
{
// TODO: cleanup X?
tty_end();
}
#if 0
int main()
{
int i, r, d;
xenv_init("just a test");
for (i = 0; i < 5; i++) {
while ((r = xenv_update(&d)) > 0)
printf("%d %x %d\n", d, r, r);
sleep(1);
if (i == 1)
xenv_minimize();
printf("ll %d\n", i);
}
printf("xenv_finish..\n");
xenv_finish();
return 0;
}
#endif

View file

@ -1,18 +0,0 @@
#define XENV_CAP_KEYS (1<<0)
#define XENV_CAP_MOUSE (1<<1)
/* xenv_flags specify if we need keys and mouse,
* on return, flag is removed if input is not available */
int xenv_init(int *xenv_flags, const char *window_title);
/* read events from X, calling key_cb for key, mouseb_cb for mouse button
* and mousem_cb for mouse motion events */
int xenv_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
int (*mouseb_cb)(void *cb_arg, int x, int y, int button, int is_pressed),
int (*mousem_cb)(void *cb_arg, int x, int y),
void *cb_arg);
int xenv_minimize(void);
void xenv_finish(void);