diff -r d1acc2a527af emu/Linux-fb/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/LICENSE Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,26 @@ +Copyright (c) 2005, 2006. 2008, 2011 Alexander Sychev. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * The name of authora may not be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -r d1acc2a527af emu/Linux-fb/devapm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/devapm.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,231 @@ +/****************************************************** +* +* Adanced power management (APM) support for Inferno OS +* +* Author: Alexander Sychev +* +*******************************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include +#include +#include "fb.h" +#include + +enum{ + Qdir, + Qapm, +}; + +static +Dirtab apmtab[]={ + ".", {Qdir, 0, QTDIR}, 0, 0555, /* entry for "." must be first if devgen used */ + "apm", {Qapm, 0}, 0, 0666, +}; + + +static Lock apmlock; +static int apmfd = -1; +static Lock proclock; +static int procfd = -1; + +int apm_dev_init() +{ + int result; + lock(&apmlock); + result = ((apmfd == -1) && ((apmfd = open("/dev/apm_bios", O_WRONLY)) < 0)) ? 1 : 0; + unlock(&apmlock); + if(apmfd == -1) + fprint(2, "can't open /dev/apm_bios: %s\n", strerror(errno)); + return result; +} + +int apm_proc_init() +{ + int result; + lock(&proclock); + result = ((procfd == -1) && ((procfd = open("/proc/apm", O_RDONLY))< 0)) ? 1 : 0; + unlock(&proclock); + if(procfd == -1) + fprint(2, "can't open /proc/apm: %s\n", strerror(errno)); + return result; +} + +int apm_dev_close() +{ + int result; + lock(&apmlock); + result = ((apmfd == -1) || close(apmfd)) ? 1 : 0; + apmfd = -1; + unlock(&apmlock); + return result; +} + +int apm_proc_close() +{ + int result; + lock(&proclock); + result = ((procfd == -1) || close(procfd)) ? 1 : 0; + procfd = -1; + unlock(&proclock); + return result; +} + + +void apm_suspend() +{ + int result; + if(apm_dev_init()) + return; + sync(); + lock(&apmlock); + result = ioctl(apmfd, APM_IOC_SUSPEND, 0); + unlock(&apmlock); + if(result) + error(Eio); +} + +int apm_blank(int vesastt) +{ + int result; + static int currvesastt = -1; + + if (currvesastt == vesastt) + return 0; + lock(&apmlock); + result = fb_blank(vesastt); + unlock(&apmlock); + if(result) + error(Eio); + else + currvesastt = vesastt; + return result; +} + +static Chan* +apmattach(char* spec) +{ + if(apm_dev_init() || apm_proc_init()) + error(Enoattach); + return devattach('S', spec); +} + +static Walkqid* +apmwalk(Chan *c, Chan *nc, char **name, int nname) +{ + return devwalk(c, nc, name, nname, apmtab, nelem(apmtab), devgen); +} + +static int +apmstat(Chan* c, uchar *db, int n) +{ + return devstat(c, db, n, apmtab, nelem(apmtab), devgen); +} + +static Chan* +apmopen(Chan* c, int omode) +{ + apm_proc_init(); + return devopen(c, omode, apmtab, nelem(apmtab), devgen); +} + +static void +apmclose(Chan* c) +{ + USED(c); + apm_proc_close(); +} + +static long +apmread(Chan* c, void* a, long n, vlong offset) +{ + USED(offset); + switch((ulong)c->qid.path) { + case Qdir: + return devdirread(c, a, n, apmtab, nelem(apmtab), devgen); + case Qapm: { + char buffer[100] = {0}; + char driver_version[10] = {0}; + int version_major = 0; + int version_minor = 0; + int flags = 0; + int line_status = 0; + int battery_status = 0; + int battery_flags = 0; + int battery_percentage = 0; + int battery_time = 0; + char units[10] = {0}; + if(read(procfd, buffer, sizeof(buffer)) < 0) + error(Eio); + sscanf(buffer, "%s %d.%d %x %x %x %x %d%% %d %s\n", + driver_version, + &version_major, + &version_minor, + &flags, + &line_status, + &battery_status, + &battery_flags, + &battery_percentage, + &battery_time, + units); + int result = sprint(buffer, "%s %d%% %d min ", + ((battery_status) ? "online" : "offline"), + (((battery_percentage >= 0) && (battery_percentage <= 100)) ? battery_percentage : 0), + (strncmp(units, "min", sizeof("min")) ? (battery_time / 60) : battery_time)); + return readstr(offset, a, n, buffer); + } + default: + n=0; + break; + } + return n; +} + + +static long +apmwrite(Chan* c, void* a, long n, vlong offset) +{ + char buffer[128] = {0}; + USED(a); + USED(offset); + switch((ulong)c->qid.path) { + case Qapm: + if(n > sizeof(buffer)) + n = sizeof(buffer)- 1; + strncpy(buffer, a, n); + if(strncmp(buffer, "suspend", sizeof("suspend")) == 0) { + apm_suspend(); + return n; + }else if(strncmp(buffer, "blank", sizeof("blank")) == 0) { + apm_blank(FB_BLANK); + return n; + } + error(Ebadctl); + break; + default: + error(Ebadusefd); + } + return n; +} + +Dev apmdevtab = { /* defaults in dev.c */ + 'S', + "apm", + + devinit, /* devinit */ + apmattach, + apmwalk, + apmstat, + apmopen, + devcreate, /* devcreate */ + apmclose, + apmread, + devbread, /* devbread */ + apmwrite, + devbwrite, /* devbwrite */ + devremove, /* devremove */ + devwstat, /* devwstat */ +}; diff -r d1acc2a527af emu/Linux-fb/emu-fb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/emu-fb Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,107 @@ +dev + root + cons + env + mnt + pipe + prog + prof + srv + dup + ssl + cap + fs + cmd cmd + indir + + draw + pointer + snarf + + ip ipif-posix ipaux + eia +# audio audio + mem + apm +lib + interp + tk + freetype + math + draw screen + + memlayer + memdraw + keyring + sec + mp + + 9 + +link + input +mod + sys + draw + + tk + math + srv srv + keyring + loader + freetype + +port + alloc + cache + chan + dev + devtab + dial + dis + discall + env + error + errstr + exception + exportfs + inferno + latin1 + main + parse + pgrp + print + proc + qio + random + sysfile + uqid + +code + +init + emuinit + +root + /dev / + /fd / + /prog / + /net / + /net.alt / + /chan / + /nvfs / + /env / +# /chan +# /dev +# /dis +# /env +# /n +# /net +# /nvfs / +# /prog +# /icons +# /osinit.dis +# /dis/emuinit.dis +# /dis/lib/auth.dis +# /dis/lib/ssl.dis +# /n/local / diff -r d1acc2a527af emu/Linux-fb/fb.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/fb.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,826 @@ +/****************************************************** +* +* Linux frame buffer device support for Inferno OS +* +* Copyright (c) 2005, 2006, 2008, 2011 Alexander Sychev. +* All rights reserved. +* Use of this source code is governed by a BSD-style +* license that can be found in the LICENSE file. +* +*******************************************************/ +#include "dat.h" +#include "fns.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fb.h" + +static int fbfd = -1; +static int fbsize = 0; +static struct fb_var_screeninfo origvsi; +static struct fb_var_screeninfo curvsi; +static struct fb_cmap origcmap; +static struct fb_cmap curcmap; +static int tty0 = -1; +int tty = -1; +static int old_stdin = -1; +static unsigned short prevtty = -1; +static unsigned short activetty = -1; +static unsigned short oldfb = -1; +static int oldtermmode = KD_TEXT; +static struct vt_mode oldvtmode; +struct termios oldtermattr; +static int vt_init(); +static void vt_deinit(); + +static int enum_modes(int xres, int yres); +static int get_params(int* x, int* y, int* bpp, unsigned long* channel); +static int set_cmap(); + +uint suspend = 0; + +int fb_init(int* xres, int* yres, int* bpp, unsigned long* channel) +{ + unsigned char* res = 0; + int size = 0; + struct fb_fix_screeninfo fsi; + + char* fbdev = getenv("FRAMEBUFFER"); + + if( !fbdev || !*fbdev ) + fbdev = "/dev/fb0"; + + fbfd = open(fbdev, O_RDWR); + + if(fbfd < 0){ + fprint(2, "framebuffer: cannot open a file %s: %s\n", fbdev, strerror(errno)); + return 0; + } + + + if(ioctl(fbfd, FBIOGET_FSCREENINFO, &fsi)){ + fprint(2, "framebuffer: cannot get fixed screen info: %s\n", strerror(errno)); + return -1; + } + + fbsize = fsi.smem_len; + + if(ioctl(fbfd, FBIOBLANK, 0)){ + close(fbfd); + fprint(2, "framebuffer: cannot blank the framebuffer: %s\n", strerror(errno)); + return 0; + } + + if(ioctl(fbfd, FBIOGET_VSCREENINFO, &origvsi)){ + close(fbfd); + fprint(2, "framebuffer: cannot get the variable screen info: %s\n", strerror(errno)); + return 0; + } + + curvsi = origvsi; + curvsi.activate = FB_ACTIVATE_NOW; + if(ioctl(fbfd, FBIOPUT_VSCREENINFO, &curvsi)){ + fprint(2, "framebuffer: cannot put the new variable screen info: %s\n", strerror(errno)); + return 0; + } + + if(vt_init()){ + close(fbfd); + return 0; + } +#if defined(OLD_KBD_SUPPORT) + kbdinit(); +#endif + + if(!get_params(xres, yres, bpp, channel)) { + fb_deinit(); + return 0; + } + memset(&origcmap, 0, sizeof(origcmap)); + memset(&curcmap, 0, sizeof(curcmap)); + if(!set_cmap()){ + fb_deinit(); + return 0; + } + + return 1; +} + +unsigned char* fb_get() +{ + unsigned char* res = mmap(0, fbsize, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, 0); + if(res == MAP_FAILED){ + fprint(2, "framebuffer: cannot map the framebuffer: %s\n", strerror(errno)); + return 0; + } + + return res; +} + +void +fb_release(unsigned char* buf) +{ + if(munmap(buf,fbsize)) + fprint(2, "framebuffer: cannot release the framebuffer: %s\n", strerror(errno)); +} + +int +fb_blank(int mode) +{ + int fbmode; + switch(mode){ + case FB_NO_BLANK: fbmode = FB_BLANK_UNBLANK; break; + case FB_BLANK: fbmode = FB_BLANK_POWERDOWN; break; + default: return -1; + } + return ioctl(fbfd, FBIOBLANK, fbmode); +} + +void +fb_deinit() +{ + if(fbfd < 0) + return; + vt_deinit(); + if(origcmap.len) + ioctl(fbfd, FBIOPUTCMAP, &origcmap); + if(origcmap.red) + free(origcmap.red); + if(origcmap.green) + free(origcmap.green); + if(origcmap.blue) + free(origcmap.blue); + if(curcmap.red) + free(curcmap.red); + if(curcmap.green) + free(curcmap.green); + if(curcmap.blue) + free(curcmap.blue); + ioctl(fbfd, FBIOPUT_VSCREENINFO, &origvsi); + close(fbfd); +} + +static char* +get_line(char** curpos, char* bufend) +{ + char* res = *curpos; + while(*curpos < bufend){ + if(**curpos == '\n'){ + **curpos = 0; + *curpos += 1; + return res; + } + if(**curpos == 0){ + *curpos += 1; + return res; + } + *curpos += 1; + } + return 0; +} + +static char* +parse_mode(char* beginofmode, char* bufend) +{ + char* beginofline = 0; + int tmp = 0; + char value[10] = {0}; + int geometryfound = 0; + int timingsfound = 0; + int rgbafound = 0; + do { + beginofline = get_line(&beginofmode, bufend); + if(!beginofline) + return beginofmode; + + if(sscanf(beginofline, + " geometry %d %d %d %d %d", + &curvsi.xres, + &curvsi.yres, + &tmp, + &tmp, + &curvsi.bits_per_pixel) == 5){ + geometryfound = 1; + curvsi.sync = 0; + curvsi.xoffset = 0; + curvsi.yoffset = 0; + curvsi.xres_virtual = curvsi.xres; + curvsi.yres_virtual = curvsi.yres; + continue; + } + if(sscanf(beginofline, + " timings %d %d %d %d %d %d %d", + &curvsi.pixclock, + &curvsi.left_margin, + &curvsi.right_margin, + &curvsi.upper_margin, + &curvsi.lower_margin, + &curvsi.hsync_len, + &curvsi.vsync_len) == 7){ + timingsfound = 1; + continue; + } + if((sscanf(beginofline, + " hsync %6s", + value) == 1) && + !strcmp(value, "high")){ + curvsi.sync |= FB_SYNC_HOR_HIGH_ACT; + continue; + } + if((sscanf(beginofline, + " vsync %6s", + value) == 1) && + !strcmp(value, "high")){ + curvsi.sync |= FB_SYNC_VERT_HIGH_ACT; + continue; + } + if((sscanf(beginofline, + " csync %6s", + value) == 1) && + !strcmp(value, "high")){ + curvsi.sync |= FB_SYNC_COMP_HIGH_ACT ; + continue; + } + if((sscanf(beginofline, + " extsync %6s", + value) == 1) && + !strcmp(value, "true")){ + curvsi.sync |= FB_SYNC_EXT; + continue; + } + if((sscanf(beginofline, + " laced %6s", + value) == 1) && + !strcmp(value, "true")){ + curvsi.sync |= FB_VMODE_INTERLACED; + continue; + } + if((sscanf(beginofline, + " double %6s", + value) == 1) && + !strcmp(value, "true")){ + curvsi.sync |= FB_VMODE_DOUBLE; + continue; + } + if(sscanf(beginofline, + " rgba %d/%d,%d/%d,%d/%d,%d/%d", + &curvsi.red.length, + &curvsi.red.offset, + &curvsi.green.length, + &curvsi.green.offset, + &curvsi.blue.length, + &curvsi.blue.offset, + &curvsi.transp.length, + &curvsi.transp.offset) == 8){ + rgbafound = 1; + continue; + } + + } + while(!strstr(beginofline, "endmode")); + if(!rgbafound) { + curvsi.transp.length = curvsi.transp.offset = 0; + curvsi.red.msb_right = curvsi.green.msb_right = 0; + curvsi.blue.msb_right = curvsi.transp.msb_right = 0; + switch(curvsi.bits_per_pixel){ + case 8: + curvsi.red.offset = 0; + curvsi.red.length = 8; + curvsi.green.offset = 0; + curvsi.green.length = 8; + curvsi.blue.offset = 0; + curvsi.blue.length = 8; + case 16: + curvsi.red.offset = 11; + curvsi.red.length = 5; + curvsi.green.offset = 5; + curvsi.green.length = 6; + curvsi.blue.offset = 0; + curvsi.blue.length = 5; + break; + + case 24: + curvsi.red.offset = 16; + curvsi.red.length = 8; + curvsi.green.offset = 8; + curvsi.green.length = 8; + curvsi.blue.offset = 0; + curvsi.blue.length = 8; + break; + + case 32: + curvsi.red.offset = 16; + curvsi.red.length = 8; + curvsi.green.offset = 8; + curvsi.green.length = 8; + curvsi.blue.offset = 0; + curvsi.blue.length = 8; + break; + } + + } + if(geometryfound && timingsfound) + return 0; + return beginofmode; +} + +static int +enum_modes(int xres, int yres) +{ + int fd = -1; + struct stat status; + char* modesfile = MAP_FAILED; + char* beginofline = 0; + char* curpos = 0; + char* bufend = 0; + int bestx = 0; + int besty = 0; + int bestbpp = 0;; + char* bestmode; + char* beginofmode = 0; + fd = open("/etc/fb.modes", O_RDONLY); + if(fd < 0){ + fprint(2, "framebuffer: cannot open the file /etc/fb.modes: %s\n", strerror(errno)); + return 0; + } + + if(fstat(fd, &status) < 0){ + fprint(2, "framebuffer: cannot stat the file /etc/fb.modes: %s\n", strerror(errno)); + close(fd); + return 0; + } + + modesfile = mmap(0, status.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + if(modesfile == MAP_FAILED){ + fprint(2, "framebuffer: cannot map /etc/fb.modes: %s\n", strerror(errno)); + close(fd); + return 0; + } + modesfile[status.st_size] = 0; + curpos = modesfile; + bufend = modesfile + status.st_size; + bestmode = bufend; + do { + char mode[50] = {0}; + beginofline = get_line(&curpos, bufend); + if(!beginofline) + break; + if(sscanf(beginofline, "mode \"%50[^\"]\"", mode) == 1){ + beginofmode = beginofline; + do { + int res = -1; + int x = 0; + int y = 0; + int bpp = 0; + int tmp = 0; + beginofline = get_line(&curpos, bufend); + if(!beginofline) + break; + res = sscanf(beginofline, + " geometry %d %d %d %d %d", + &x, + &y, + &tmp, + &tmp, + &bpp); + if(res == 5){ + if((((x >= bestx) && (x <= xres)) || + ((y >= besty) && (y <= yres))) && + (bpp>=bestbpp)) { + bestmode = beginofmode; + bestx = x; + besty = y; + bestbpp = bpp; + } + } + + } + while(!strstr(beginofline, "endmode")); + } + } + while(beginofline); + curpos = parse_mode(bestmode, bufend); + munmap(modesfile, status.st_size); + close(fd); + + if(curpos) { + fprint(2, "framebuffer: mode %dx%d hasn't found in /etc/fb.modes\n", xres, yres); + return 0; + } + return 1; +} + + +static int +get_params(int* x, int* y, int* bpp, unsigned long* channel) +{ + if(enum_modes(*x, *y)) { + if(ioctl(fbfd, FBIOPUT_VSCREENINFO, &curvsi)){ + fprint(2, "framebuffer: cannot put the new variable screen info: %s\n", strerror(errno)); + return 0; + } + if(ioctl(fbfd, FBIOGET_VSCREENINFO, &curvsi)){ + close(fbfd); + fprint(2, "framebuffer: cannot get the variable screen info: %s\n", strerror(errno)); + return 0; + } + } + else + fprint(2,"framebuffer: cannot enumerate video modes - current framebuffer settings will be used\n"); + + *x=curvsi.xres; + *y=curvsi.yres; + *bpp=curvsi.bits_per_pixel; + + switch (curvsi.bits_per_pixel) { + case 8: + *channel=CMAP8; + break; + case 16: + case 24: + if(curvsi.transp.length) + *channel=CHAN4(CAlpha,curvsi.transp.length, + CRed,curvsi.red.length, + CGreen,curvsi.green.length, + CBlue,curvsi.blue.length); + + else + *channel=CHAN3(CRed,curvsi.red.length, + CGreen,curvsi.green.length, + CBlue,curvsi.blue.length); + break; + case 32: + if(curvsi.transp.length) + *channel=CHAN4(CAlpha,curvsi.transp.length, + CRed,curvsi.red.length, + CGreen,curvsi.green.length, + CBlue,curvsi.blue.length); + else + *channel=CHAN4(CIgnore,curvsi.bits_per_pixel - curvsi.red.length - curvsi.green.length - curvsi.blue.length, + CRed,curvsi.red.length, + CGreen,curvsi.green.length, + CBlue,curvsi.blue.length); + break; + + } + return 1; +} + +static int +set_cmap() +{ + struct fb_fix_screeninfo fsi; + int i, red_size, green_size, blue_size; + int r, g, b, cr, cg, cb, v, num, den, idx; + + if(ioctl(fbfd, FBIOGET_FSCREENINFO, &fsi)){ + fprint(2, "framebuffer: cannot get fixed screen info: %s\n", strerror(errno)); + return 0; + + } + origcmap.start = 0; + origcmap.len = 256; + origcmap.red = malloc(256 * sizeof(unsigned short)); + origcmap.green = malloc(256 * sizeof(unsigned short)); + origcmap.blue = malloc(256 * sizeof(unsigned short)); + origcmap.transp = 0; + memset(origcmap.red, 0, 256 * sizeof(unsigned short)); + memset(origcmap.green, 0, 256 * sizeof(unsigned short)); + memset(origcmap.blue, 0, 256 * sizeof(unsigned short)); + if(ioctl(fbfd, FBIOGETCMAP, &origcmap)){ + fprint(2, "framebuffer: cannot get color map: %s\n", strerror(errno)); + origcmap.len = 0; + } + + switch(fsi.visual) { + case FB_VISUAL_PSEUDOCOLOR: + curcmap.start = 0; + curcmap.len = 256; + curcmap.red = malloc(256 * sizeof(unsigned short)); + curcmap.green = malloc(256 * sizeof(unsigned short)); + curcmap.blue = malloc(256 * sizeof(unsigned short)); + curcmap.transp = 0; + memset(curcmap.red, 0, 256 * sizeof(unsigned short)); + memset(curcmap.green, 0, 256 * sizeof(unsigned short)); + memset(curcmap.blue, 0, 256 * sizeof(unsigned short)); + for(r=0; r!=4; r++) { + for(g = 0; g != 4; g++) { + for(b = 0; b!=4; b++) { + for(v = 0; v!=4; v++) { + den=r; + if(g > den) + den=g; + if(b > den) + den=b; + /* divide check -- pick grey shades */ + if(den==0) + cr=cg=cb=v*17; + else { + num=17*(4*den+v); + cr=r*num/den; + cg=g*num/den; + cb=b*num/den; + } + idx = r*64 + v*16 + ((g*4 + b + v - r) & 15); + /* was idx = 255 - idx; */ + curcmap.red[idx] = cr*0x0101; + curcmap.green[idx] = cg*0x0101; + curcmap.blue[idx] = cb*0x0101; + } + } + } + } + break; + case FB_VISUAL_TRUECOLOR: + return 1; + case FB_VISUAL_DIRECTCOLOR: + red_size = 1 << curvsi.red.length; + green_size = 1 << curvsi.green.length; + blue_size = 1 << curvsi.blue.length; + curcmap.start = 0; + curcmap.len = red_size; + if(curcmap.len < green_size) + curcmap.len = green_size; + if(curcmap.len < blue_size) + curcmap.len = blue_size; + curcmap.red = malloc(red_size * sizeof(unsigned short)); + curcmap.green = malloc(green_size * sizeof(unsigned short)); + curcmap.blue = malloc(blue_size * sizeof(unsigned short)); + curcmap.transp = 0; + memset(curcmap.red, 0, red_size * sizeof(unsigned short)); + memset(curcmap.green, 0, green_size * sizeof(unsigned short)); + memset(curcmap.blue, 0, blue_size * sizeof(unsigned short)); + for(i=0; i < red_size; i++) + curcmap.red[i] = i*256/red_size*0x0101; + for(i=0; i < green_size; i++) + curcmap.green[i] = i*256/green_size*0x0101; + for(i=0; i < blue_size; i++) + curcmap.blue[i] = i*256/blue_size*0x0101; + break; + default: + fprint(2, "framebuffer: not supported visual type of the framebuffer\n" ); + return 0; + } + if(ioctl(fbfd, FBIOPUTCMAP, &curcmap)){ + fprint(2, "framebuffer: cannot put color map: %s\n", strerror(errno)); + return 0; + } + return 1; +} + +static int +get_fb4vt(int vt) +{ + struct fb_con2fbmap map; + + map.console = vt; + + if(ioctl(fbfd, FBIOGET_CON2FBMAP, &map )){ + fprint(2, "framebuffer: cannot get framebuffer console: %s\n", strerror(errno)); + return -1; + } + + return map.framebuffer; +} + +static int +set_fb4vt(int virtualterm, int fb) +{ + struct fb_con2fbmap map; + + if(fb >= 0) + map.framebuffer = fb; + else { + struct stat aStat; + if(fstat(fbfd, &aStat)){ + fprint(2, "framebuffer: cannot get status of the framebuffer: %s\n", strerror(errno)); + return -1; + } + map.framebuffer =(aStat.st_rdev & 0xFF) >> 5; + } + + map.console = virtualterm; + + if(ioctl(fbfd, FBIOPUT_CON2FBMAP, &map)){ + fprint(2, "framebuffer: cannot set a virtual terminal for the framebufer: %s\n", strerror(errno)); + return -1; + } + return 0; +} + +static void +handler(int signo) +{ + USED(signo); +} + +static void +suspendproc(void* param) +{ + struct sigaction act; + sigset_t mask; + + struct vt_mode newvtmode; + + newvtmode.mode = VT_PROCESS; + newvtmode.waitv = 0; + newvtmode.relsig = SIGIO; + newvtmode.acqsig = SIGIO; + if(ioctl(tty, VT_SETMODE, &newvtmode)){ + fprint(2, "framebuffer: cannot set mode for the terminal: %s\n", strerror(errno)); + vt_deinit(); + return; + } + + memset(&act, 0 , sizeof(act)); + act.sa_handler = handler; + sigaction(SIGIO, &act, nil); + + while(1){ + sigprocmask(SIG_SETMASK, NULL, &mask); + sigdelset(&mask, SIGIO); + sigsuspend(&mask); + if(!suspend){ + suspend = 1; + if(ioctl(tty, VT_RELDISP, 1) < 0){ + fprint(2, "framebuffer: can't switch from terminal: %s\n"); + return; + } + } + else{ + if(ioctl(tty, VT_RELDISP, 2) < 0){ + fprint(2, "framebuffer: can't switch to terminal: %s\n", strerror(errno)); + return; + } + + if (ioctl(tty, KDSETMODE, KD_GRAPHICS ) < 0){ + fprint(2, "framebuffer: cannot set the terminal to the graphics mode: %s\n", strerror(errno)); + return; + } + curvsi.activate = FB_ACTIVATE_NOW; + if(ioctl(fbfd, FBIOPUT_VSCREENINFO, &curvsi)){ + fprint(2, "framebuffer: cannot put the new variable screen info: %s\n", strerror(errno)); + return; + } + + if(ioctl(fbfd, FBIOPUTCMAP, &curcmap)){ + fprint(2, "framebuffer: cannot put color map: %s\n", strerror(errno)); + return; + } + suspend = 0; + Rectangle rect; + rect.min.x = 0; + rect.min.y = 0; + rect.max.x = Xsize; + rect.max.y = Ysize; + flushmemscreen(rect); + } + } +} + +static int +vt_init() +{ + struct vt_stat vtstat; + char ttyname[20] = {0}; + struct termios t; + if((((tty0 = open("/dev/tty0", O_WRONLY)) < 0)) && + (((tty0 = open("/dev/vc/0", O_RDWR)) < 0))){ + fprint(2, "framebuffer: cannot open a terminal: %s\n", strerror(errno)); + return -1; + } + if(ioctl(tty0, VT_GETSTATE, &vtstat) < 0){ + fprint(2, "framebuffer: cannot get state of the terminal: %s\n", strerror(errno)); + close(tty0); + return -1; + } + + prevtty = vtstat.v_active; + + if((ioctl(tty0, VT_OPENQRY, &activetty) == -1) || + (activetty ==(unsigned short)-1)){ + fprint(2, "framebuffer: cannot open new terminal: %s\n", strerror(errno)); + close(tty0); + return -1; + } + + oldfb = get_fb4vt(activetty); + set_fb4vt(activetty, -1); + + if(ioctl(tty0, VT_ACTIVATE, activetty)){ + fprint(2, "framebuffer: cannot activate terminal: %s\n", strerror(errno)); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); + return -1; + } + + if(ioctl(tty0, VT_WAITACTIVE, activetty)){ + fprint(2, "framebuffer: cannot activate terminal: %s\n", strerror(errno)); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); + return -1; + } + + if((snprintf(ttyname, sizeof(ttyname), "/dev/tty%d", activetty) < 0) || + (((tty = open(ttyname, O_RDWR)) < 0) && + (errno != ENOENT)) && + (snprintf(ttyname, sizeof(ttyname), "/dev/vc/%d", activetty) < 0) || + ((tty = open(ttyname, O_RDWR)) < 0)){ + fprint(2, "framebuffer: cannot activate terminal: %s\n", strerror(errno)); + ioctl(tty0, VT_ACTIVATE, prevtty); + ioctl(tty0, VT_WAITACTIVE, prevtty); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); + return -1; + } + + if(ioctl(tty, KDGETMODE, &oldtermmode)){ + fprint(2, "framebuffer: cannot get a terminal mode: %s\n", strerror(errno)); + ioctl(tty0, VT_ACTIVATE, prevtty); + ioctl(tty0, VT_WAITACTIVE, prevtty); + close(tty); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); + return -1; + } + + if(ioctl(tty, KDSETMODE, KD_GRAPHICS)){ + fprint(2, "framebuffer: cannot set the terminal to the graphics mode: %s\n", strerror(errno)); + ioctl(tty0, VT_ACTIVATE, prevtty); + ioctl(tty0, VT_WAITACTIVE, prevtty); + close(tty); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); + return -1; + } + + ioctl(tty0, TIOCNOTTY, 0); + ioctl(tty, TIOCSCTTY, 0); + + const char setcursoroff [] = "\033[?1;0;0c"; + const char setblankoff [] = "\033[9;0]"; + + write(tty, setcursoroff, sizeof(setcursoroff)); + write(tty, setblankoff, sizeof(setblankoff)); + + + if(ioctl(tty, VT_GETMODE, &oldvtmode)){ + fprint(2, "framebuffer: cannot get mode for the terminal: %s\n", strerror(errno)); + ioctl(tty0, VT_ACTIVATE, prevtty); + ioctl(tty0, VT_WAITACTIVE, prevtty); + close(tty); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); + return -1; + } + + + kproc("suspendProc", suspendproc, 0, 0); + + tcgetattr(tty, &oldtermattr); + t = oldtermattr; + t.c_lflag &= ~(ICANON|ECHO|ISIG); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + tcsetattr(tty, TCSANOW, &t); + + return 0; +} + +static void +vt_deinit() +{ + tcsetattr(tty, TCSANOW, &oldtermattr); + const char setcursoron [] = "\033[?0;0;0c"; + const char setblankon [] = "\033[9;10]"; + + write(tty, setcursoron, sizeof(setcursoron)); + write(tty, setblankon, sizeof(setblankon)); + + ioctl(tty, VT_SETMODE, &oldvtmode); + + ioctl(tty, KDSETMODE, oldtermmode); + ioctl(tty0, VT_ACTIVATE, prevtty); + ioctl(tty0, VT_WAITACTIVE, prevtty); + set_fb4vt(activetty, oldfb); + close(tty); + ioctl(tty0, VT_ACTIVATE, prevtty); + ioctl(tty0, VT_WAITACTIVE, prevtty); + ioctl(tty0, VT_DISALLOCATE, activetty); + close(tty0); +} diff -r d1acc2a527af emu/Linux-fb/fb.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/fb.h Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,25 @@ +/************************************************* +* +* Linux frame buffer device support for Inferno OS +* +* Author: Alexander Sychev +* +**************************************************/ + +#if !defined (__FB_H_included__) +#define __FB_H_included__ + +enum{ + FB_NO_BLANK, + FB_BLANK, +}; + +extern uint suspend; + +int fb_init(int* xres, int* yres, int* bpp, unsigned long* channel); +unsigned char* fb_get(); +void fb_release(unsigned char* buffer); +int fb_blank(int mode); +void fb_deinit() ; + +#endif // __FB_H_included__ diff -r d1acc2a527af emu/Linux-fb/input.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,82 @@ +/*********************************************** +* +* Generic input handling for Inferno OS +* +* Authors: Salva Peiró +* Alexander Sychev +* +************************************************/ + +#include "dat.h" +#include "fns.h" +#include "input.h" +#include "fb.h" + +enum +{ + NEVENTS = 5, + EVENTSZ = sizeof(struct input_event), +}; + +static void +proc(void* param) +{ + int count; + Handler* handler = (Handler*)param; + struct input_event ev[NEVENTS]; + for(;;) { + count = read(handler->fd, ev, sizeof(ev)); + if(count >= EVENTSZ && !suspend) + handler->func(ev, count / EVENTSZ); + } +} + +static void +init(void) +{ + int i = 0; + + for(i = 0; handlers[i].func != 0; ++i){ + if(handlers[i].init(&handlers[i]) < 0) + continue; + + kproc(handlers[i].procname, proc, &handlers[i], 0); + } + if(handlers[i].func != 0){ + fprint(2, "emu: handlers haven't started\n"); + for(i = 0; handlers[i].func !=0; ++i) + handlers[i].deinit(&handlers[i]); + + } +} + +int +input_init(Handler* handler) +{ + if(((handler->fd = open(handler->filename, O_RDONLY)) < 0)) { + fprint(2, "can't open %s device: %s\n", handler->filename, strerror(errno)); + return -1; + } + return 0; +} + +int +input_init_vp(Handler* handler) +{ + ispointervisible = 1; // have pointer only under acme? + return input_init(handler); +} + +void +input_deinit(Handler* handler) +{ + if(handler->fd != -1) + close(handler->fd); +} + +void +inputlink() +{ + init(); +} + diff -r d1acc2a527af emu/Linux-fb/input.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input.h Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,37 @@ +/*********************************************** +* +* Generic input handling for Inferno OS +* +* Authors: Salva Peiró +* Alexander Sychev +* +************************************************/ + +#if !defined(__INPUT_H_included__) +#define __INPUT_H_included__ +#include + +enum +{ + DblTime = 300000 /* double click time in micro seconds */ +}; + +/* pointer/keyboard specific functions */ +typedef struct Handler Handler; +struct Handler{ + int fd; + char* filename; + char* procname; + int (*init)(Handler* handler); + void (*func)(struct input_event*, int); + void (*deinit)(Handler*); +}; + +int input_init(Handler*); +int input_init_vp(Handler*); /* initialization with turning pointer visible */ +void input_deinit(Handler*); + +extern struct Handler handlers[]; +extern int ispointervisible; + +#endif /*__INPUT_H_included__*/ diff -r d1acc2a527af emu/Linux-fb/input_h3900.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_h3900.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,126 @@ +/*************************************************** +* +* Compaq/HP iPAQ h3970 input handling for Inferno OS +* +* Author: Alexander Sychev +* +****************************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "keyboard.h" +#include + + +static struct { + int screenfd; + int keyfd; + int button; +} touchscreen; + +typedef struct { + uchar pressed; + uchar reserved1; + Rune x; + Rune y; + Rune reserved2; +} Packet __attribute__ ((packed)); + +static void +touchscreen_stylus(Packet* packet, int count) +{ + int i; + for(i = 0; i < count; i++) { + if(packet [ i ].pressed) + mousetrack(touchscreen.button, packet [ i ].x, packet [ i ].y, 0); + else + mousetrack(0, 0, 0, 1); + } + return; +} + +static void +touchscreen_keys(uchar* packet, int size) +{ + int i; + static int buttons[] = {0, Esc, LCtrl, LShift, RShift, RCtrl, Right, Down, Up, Left, Middle, PwrOff}; + for(i = 0; i < size; i++) { + int released = packet[i] & 0x80; + int key = buttons [packet[i] & 0x0F]; + if(released) + touchscreen.button = 1; + else { + switch(key) { + case LCtrl: + case RCtrl: + touchscreen.button = 2; + break; + case LShift: + case RShift: + touchscreen.button = 4; + break; + case PwrOff: + apm_suspend(); + break; + default: + touchscreen.button = 1; + gkbdputc(gkbdq, key); + break; + } + } + } + return; +} + +static void +touchscreenProc(void* dummy) +{ + for(;;) { + Packet packets[10]; + int count = read(touchscreen.screenfd, packets, sizeof(packets)); + if(count > 0) + touchscreen_stylus(packets, count / sizeof(Packet)); + } +} + + +static void +keysProc(void* dummy) +{ + for(;;) { + uchar buffer[32]; + int count = read(touchscreen.keyfd, buffer, sizeof(buffer)); + if(count > 0) + touchscreen_keys(buffer, count); + } +} + +static void +touchscreeninit(void) +{ + if(((touchscreen.screenfd = open("/dev/touchscreen/0", O_RDONLY)) < 0)) { + fprint(2, "can't open touchscreen device: %s\n", strerror(errno)); + return; + } + + if((touchscreen.keyfd = open("/dev/touchscreen/key", O_RDONLY)) < 0) { + fprint(2, "can't open touchescreen keys device: %s\n", strerror(errno)); + close(touchscreen.screenfd); + return; + } + + touchscreen.button = 1; + + kproc("touchscreenProc", touchscreenProc, nil, 0); + + kproc("keysProc", keysProc, nil, 0); + +} + +void +h3900_tslink(void) +{ + touchscreeninit(); +} + diff -r d1acc2a527af emu/Linux-fb/input_kbd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_kbd.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,128 @@ +/************************************************* +* +* Generic keyboard input handling for Inferno OS +* based on sources form Inferno distribution +* +* Copyright (c) 2005, 2006, 2008, 2011 Alexander Sychev. +* All rights reserved. +* +**************************************************/ + +#include "keyboard.h" + +char *gkscanid = "emu_pc"; + +/* + * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard. + * A 'standard' keyboard doesn't produce anything above 0x58. + */ +Rune kbtab[] = { + [0x00] No, Esc, '1', '2', '3', '4', '5', '6', + [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t', + [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + [0x18] 'o', 'p', '[', ']', '\n', LCtrl, 'a', 's', + [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + [0x28] '\'', '`', LShift, '\\', 'z', 'x', 'c', 'v', + [0x30] 'b', 'n', 'm', ',', '.', '/', RShift, '*', + [0x38] LAlt, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5, + [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', + [0x48] '8', '9', '-', '4', '5', '6', '+', '1', + [0x50] '2', '3', '0', '.', No, No, No, KF|11, + [0x58] KF|12, No, No, No, No, No, No, No, + [0x60] '\n', RCtrl, '/', No, RAlt, No, Home, Up, + [0x68] Pgup, Left, Right, End, Down, Pgdown, Ins, Del, + [0x70] No, No, No, No, No, No, No, No, + [0x78] No, No, No, No, No, No, No, No, +}; + +Rune kbtabshift[] = { + [0x00] No, Esc, '!', '@', '#', '$', '%', '^', + [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t', + [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + [0x18] 'O', 'P', '{', '}', '\n', LCtrl, 'A', 'S', + [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + [0x28] '"', '~', LShift, '|', 'Z', 'X', 'C', 'V', + [0x30] 'B', 'N', 'M', '<', '>', '?', RShift, '*', + [0x38] LAlt, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5, + [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', + [0x48] '8', '9', '-', '4', '5', '6', '+', '1', + [0x50] '2', '3', '0', '.', No, No, No, KF|11, + [0x58] KF|12, No, No, No, No, No, No, No, + [0x60] '\n', RCtrl, '/', No, RAlt, No, Home, Up, + [0x68] Pgup, Left, Right, End, Down, Pgdown, Ins, Del, + [0x70] No, No, No, No, No, No, No, No, + [0x78] No, No, No, No, No, No, No, No, +}; + + +static void +keyboard(struct input_event* ev, int count) +{ + int i, keydown; + static int alt, caps, ctl, num, shift; + Rune c; + for (i=0; i < count; i++){ + if (ev[i].type != EV_KEY) + continue; + + keydown = ev[i].value ? 1 : 0; + if(gkscanq != nil){ + uchar ch = ev[i].code; + if(!keydown) + ch |= 0x80; + qproduce(gkscanq, &ch, 1); + return; + } + + c = ev[i].code; + switch(c) { + case KEY_LEFTALT: + case KEY_RIGHTALT: + alt = keydown; + continue; + case KEY_LEFTSHIFT: + case KEY_RIGHTSHIFT: + shift = keydown; + continue; + case KEY_LEFTCTRL: + case KEY_RIGHTCTRL: + ctl = keydown; + continue; + case KEY_CAPSLOCK: + if(keydown) + caps ^= 1; + continue; + case KEY_NUMLOCK: + if(keydown) + num ^= 1; + continue; + case KEY_DELETE: + if(ctl&&alt) + cleanexit(0); + default: + if(!keydown) + continue; + if(c > sizeof(kbtab)) + continue; + if(shift) + c = kbtabshift[c]; + else + c = kbtab[c]; + if(caps){ + if(c<='z' && c>='a') + c += 'A' - 'a'; + else if(c<='Z' && c>='A') + c -= 'A' - 'a'; + } + /*Alt-Fx are terminal switching sequences*/ + if(alt && (c & KF)){ + alt = c = 0; + continue; + } + } + + if(ctl) + c &= 0x9f; + gkbdputc(gkbdq, c); + } +} diff -r d1acc2a527af emu/Linux-fb/input_mouse.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_mouse.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,71 @@ +/************************************************* +* +* Generic mouse input handling for Inferno OS +* +* Author: Alexander Sychev +* +**************************************************/ + +static void +mouse(struct input_event* ev, int count) +{ + int i; + int dx = 0, dy = 0, dbl = 0; + + static int b; + static int lastb; + static struct timeval lastt; + + for (i=0; i < count; i++){ + b &= ~(1<<8); + switch(ev[i].type){ + case EV_REL: + switch(ev[i].code){ + case REL_X: + dx = ev[i].value; + break; + case REL_Y: + dy = ev[i].value; + break; + } + mousetrack(b, dx, dy, 1); + break; + case EV_KEY: + if(ev[i].value){ + switch(ev[i].code){ + case BTN_LEFT: + b |= 1; + break; + case BTN_MIDDLE: + b |= 2; + break; + case BTN_RIGHT: + b |= 4; + break; + } + if((b == lastb) && + (ev[i].time.tv_sec == lastt.tv_sec) && + ((ev[i].time.tv_usec - lastt.tv_usec) < DblTime)) + dbl = 1; + lastb = b; + lastt = ev[i].time; + if(dbl) + b = b | 1<<8; + } + else + switch(ev[i].code){ + case BTN_LEFT: + b &= ~1; + break; + case BTN_MIDDLE: + b &= ~2; + break; + case BTN_RIGHT: + b &= ~4; + break; + } + mousetrack(b, dx, dy, 1); + break; + } + } +} diff -r d1acc2a527af emu/Linux-fb/input_pc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_pc.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,19 @@ +/************************************************* +* +* Usual PC input handling for Inferno OS +* +* Author: Alexander Sychev +* +**************************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "input.h" + +#include "input_kbd.c" +#include "input_mouse.c" + +struct Handler handlers[] = {{-1, "/dev/input/event3", "ptrProc", input_init_vp, mouse, input_deinit}, + {-1, "/dev/input/event2", "kbdProc", input_init, keyboard, input_deinit}, + {-1, 0, 0, 0, 0}}; diff -r d1acc2a527af emu/Linux-fb/input_t3.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_t3.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,139 @@ +/******************************************* +* +* Palm T3 input handling for Inferno OS +* +* Author: Salva Peiró +* +********************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "keyboard.h" +#include +#include "fb.h" +#include "input.h" + +static int xabs[5], yabs[5]; + +static int b = 0; + +const char scrdev[] = "/dev/input/event3"; +const char keydev[] = "/dev/input/event1"; + +static void +t3stylus(struct input_event* ev, int count) +{ + int i, touch=0; + int x, y, p, dbl = 0; + static int lastb; + static struct timeval lastt; + + for (i=0; i < count; i++){ + if(0) fprint(2, "%d/%d [%d] ", i, count, ev[i].code); + switch(ev[i].type){ + case EV_ABS: + switch(ev[i].code){ + case ABS_X: + x = Xsize - Xsize*(ev[i].value-xabs[1])/(float)(xabs[2]-xabs[1]); + break; + case ABS_Y: + y = Ysize - Ysize*(ev[i].value-yabs[1])/(float)(yabs[2]-yabs[1]); + break; + case ABS_PRESSURE: + p = ev[i].value; + break; + } + break; + case EV_KEY: + if (ev[i].value){ + touch=1; + if(b==lastb && ev[i].time.tv_sec == lastt.tv_sec && + (ev[i].time.tv_usec-lastt.tv_usec) < DblTime) + dbl = 1; + lastb = b; + lastt = ev[i].time; + if(dbl) + b = b | 1<<8; + } + break; + case EV_SYN: + if (i==3 && p>0) // motion + mousetrack (b, x, y, 0); +// else if (i>3 && p>0 && touch) // press +// mousetrack(b, x, y, 0); + else if (i>3 && p==0 && !touch) // release + mousetrack(0, 0, 0, 1); + return; + } + } +} + +static void +t3keys(struct input_event* ev, int count) +{ + int i, key; + static int t3_buttons[] = { + No, + [KEY_ENTER] = '\n', + [KEY_F3] = No, [KEY_F4] = No, + [KEY_F7] = PwrOff, + [KEY_F9] = LCtrl, [KEY_F10] = Esc, + [KEY_F11] = LShift, [KEY_F12] = RShift, + [KEY_UP] = Up, [KEY_LEFT] = Left, [KEY_RIGHT] = Right, [KEY_DOWN] = Down, + }; + + for (i=0; i < count; i++){ + if (ev[i].type != EV_KEY) + continue; + + if (ev[i].value) + b = 1; + else { + key = t3_buttons [ev[i].code]; + if (key != No) + apm_blank(FB_NO_BLANK); + switch(key) { + case No: + break; + case RShift: + b = 1; + break; + case LCtrl: + b = 2; + break; + case LShift: + b = 4; + break; + case PwrOff: + apm_suspend(); + break; + default: + gkbdputc(gkbdq, key); + break; + } + } + } + return; +} + +static int +t3config(Handler* handler) +{ + int res = input_init_vp(handler); + if(res) + return res; + // corrections to touchscreen dimension + ioctl(handlers->fd, EVIOCGABS(ABS_X), xabs); + ioctl(handlers->fd, EVIOCGABS(ABS_Y), yabs); + xabs[1] = xabs[1] + 143; + xabs[2] = xabs[2] - 108; + yabs[2] = yabs[2] + 35; + + return 0; +} + +struct Handler handlers[] = {{-1, "/dev/input/event3", "scrProc", t3config, t3stylus, input_deinit}, + {-1, "/dev/input/event1", "keysProc", input_init, t3keys, input_deinit}, + {-1, 0, 0, 0, 0}}; + diff -r d1acc2a527af emu/Linux-fb/input_t40.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_t40.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,20 @@ +/************************************************* +* +* IBM ThinkPad T40 input handling for Inferno OS +* (differs from PC in event filenames) +* +* Author: Alexander Sychev +* +**************************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "input.h" + +#include "input_kbd.c" +#include "input_mouse.c" + +struct Handler handlers[] = {{-1, "/dev/input/event4", "ptrProc", input_init_vp, mouse, input_deinit}, + {-1, "/dev/input/event3", "kbdProc", input_init, keyboard, input_deinit}, + {-1, 0, 0, 0, 0}}; diff -r d1acc2a527af emu/Linux-fb/input_t42.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_t42.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,20 @@ +/************************************************* +* +* IBM ThinkPad T40 input handling for Inferno OS +* (differs from PC in event filenames) +* +* Author: Alexander Sychev +* +**************************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "input.h" + +#include "input_kbd.c" +#include "input_mouse.c" + +struct Handler handlers[] = {{-1, "/dev/input/event2", "ptrProc", input_init_vp, mouse, input_deinit}, + {-1, "/dev/input/event0", "kbdProc", input_init, keyboard, input_deinit}, + {-1, 0, 0, 0, 0}}; diff -r d1acc2a527af emu/Linux-fb/input_ts.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/input_ts.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,59 @@ +/*************************************************** +* +* Generic touchscreen input handling for Inferno OS +* (still in development) +* +* Author: Alexander Sychev +* +****************************************************/ + + +static void +touchscreen(struct input_event* ev, int count) +{ + int i; + int x, y, p, dbl = 0; + static int b, lastb; + static struct timeval lastt; + + for (i=0; i < count; i++){ + b &= ~(1<<8); + switch(ev[i].type){ + case EV_ABS: + switch(ev[i].code){ + case ABS_X: + x = ev[i].value; + break; + case ABS_Y: + y = ev[i].value; + break; + case ABS_PRESSURE: + p = ev[i].value; + break; + } + break; + case EV_KEY: + if(!ev[i].value) + break; + b = code2button(ev[i].code); + touch = 1; + if((b == lastb) && + (ev[i].time.tv_sec == lastt.tv_sec) && + ((ev[i].time.tv_usec - lastt.tv_usec) < DblTime)) + dbl = 1; + lastb = b; + lastt = ev[i].time; + if(dbl) + b |= 1<<8; + break; + case EV_SYN: + if (i==3 && p>0) // motion + mousetrack (b, x, y, 0); +// else if (i>3 && p>0 && touch) // press +// mousetrack(b, x, y, 0); + else if (i>3 && p==0 && !touch) // release + mousetrack(0, 0, 0, 1); + return; + } + } +} diff -r d1acc2a527af emu/Linux-fb/mkfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/mkfile Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,56 @@ +<../../mkconfig +#Configurable parameters +TARGET= t42 # pc t40 t3 h3900 +CONF=emu-fb #default configuration +CONFLIST=emu-fb +CLEANCONFLIST= + +INSTALLDIR=$ROOT/$SYSTARG/$OBJTYPE/bin #path of directory where kernel is installed + +#end configurable parameters + +<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system + +<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $PORT, $LIBS + +OBJ=\ + asm-$OBJTYPE.$O\ + os.$O\ + fb.$O\ + screen.$O\ + input_$TARGET.$O\ + $CONF.root.$O\ + lock.$O\ + $DEVS\ + $PORT\ + +LIBNAMES=${LIBS:%=lib%.a} +#libs=${LIBS:%=$ROOT/$OBJDIR/lib/lib%.a} + +HFILES=\ + +CFLAGS=-DFB_SUPPORT '-DROOT="'$ROOT'"' -DEMU -I. -I../port -I$ROOT/$SYSTARG/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp $CTHREADFLAGS $CFLAGS $EMUOPTIONS +SYSLIBS= -lm -lrt +KERNDATE=`{$NDATE} + +default:V: $O.$CONF + +$O.$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES + $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c + $LD $LDFLAGS -o $target $OBJ $CONF.$O $LIBFILES $SYSLIBS + +install:V: $O.$CONF + cp $O.$CONF $INSTALLDIR/$CONF + +%.$O: ../Linux/%.c + $CC $CFLAGS -I. ../Linux/$stem.c + +%.$O: ../Linux/%.S + $AS $ASFLAGS ../Linux/$stem.S + +<../port/portmkfile + +devfs.$O: ../port/devfs-posix.c + +input_t40.$O: input_kbd.c input_mouse.c +input_pc.$O: input_kbd.c input_mouse.c \ No newline at end of file diff -r d1acc2a527af emu/Linux-fb/screen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emu/Linux-fb/screen.c Mon Oct 10 09:04:29 2011 +0300 @@ -0,0 +1,406 @@ +/******************************************************************** +* +* the screen implementation with using the Linux frame buffer support +* +* Author: Alexander Sychev email:santucco@gmail.com +* +*********************************************************************/ + +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "fb.h" + +#include +#include +#include + +Point mousexy(void); + +static ulong displaychannel = 0; +static int displaydepth = 0; +static int isscreeninited = 0; +static uchar* screendata = 0; +static uchar* framebuffer = 0; +int ispointervisible = 0; + +static void initcursor(uchar*, uchar*, int, int, int, int); +static void cleanpointer(); +static void drawpointer(int, int); + +static struct { + char* clip; + int size; +} clipboard; + +typedef struct ICursor ICursor; +struct ICursor { + ulong inuse; + int x; + int y; + int hotx; + int hoty; + int w; + int h; + uchar* set; + uchar* clr; +}; +static ICursor icursor; + +static int +revbyte(int b) +{ + int r; + + r = 0; + r |= (b&0x01) << 7; + r |= (b&0x02) << 5; + r |= (b&0x04) << 3; + r |= (b&0x08) << 1; + r |= (b&0x10) >> 1; + r |= (b&0x20) >> 3; + r |= (b&0x40) >> 5; + r |= (b&0x80) >> 7; + return r; +} + +static void +curslock(void) +{ + while(_tas(&icursor.inuse) != 0) + osyield(); +} + +static void +cursunlock(void) +{ + icursor.inuse = 0; +} + +void +drawcursor(Drawcursor* c) +{ + int h, bpl; + Point mousepos = mousexy(); + if(suspend) + return; + drawqlock(); + cleanpointer(); + if(c->data == nil) + initcursor(0, 0, 0, 0, 0, 0); + else { + h = (c->maxy-c->miny)/2; /* image, then mask */ + bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 1); + initcursor(c->data, c->data + h*bpl, h, bpl*8, c->hotx, c->hoty); + } + setpointer(mousepos.x, mousepos.y); + drawqunlock(); +} + +uchar* +attachscreen(Rectangle *rectangle, ulong *channel, int *depth, int *width, int *softscreen) +{ + if(!isscreeninited) { + if (!fb_init(&Xsize, &Ysize, &displaydepth, &displaychannel)) { + fprint(2, "cannot init framebuffer\n"); + return 0; + } + framebuffer = fb_get(); + if(!framebuffer) { + fprint(2, "cannot get framebuffer\n"); + return 0; + } + screendata = malloc(Xsize * Ysize *(displaydepth / 8)); + if(!screendata) { + fprint(2, "cannot allocate screen buffer\n"); + return 0; + } + initcursor(0, 0, 0, 0, 0, 0); + } + Xsize &= ~0x3; /* ensure multiple of 4 */ + rectangle->min.x = 0; + rectangle->min.y = 0; + rectangle->max.x = Xsize; + rectangle->max.y = Ysize; + + *channel = displaychannel; + *depth = displaydepth; + + *width = (Xsize / 4) * (*depth / 8); + *softscreen = 1; + if(!isscreeninited) + isscreeninited = 1; + return screendata; +} + +void +detachscreen() +{ + free(icursor.set); + icursor.set = 0; + free(icursor.clr); + icursor.clr = 0; + free(screendata); + screendata = 0; + fb_release(framebuffer); + framebuffer = 0; + fb_deinit(); + if(clipboard.clip) { + free(clipboard.clip); + clipboard.clip = 0; + clipboard.size = 0; + } +} + +#define max(a,b)(((a)>(b))?(a):(b)) +#define min(a,b)(((a)<(b))?(a):(b)) + +void +flushmemscreen(Rectangle rectangle) +{ + if(suspend) + return; + if(!framebuffer || !screendata) + return; + int depth = displaydepth / 8; + int bpl = Xsize * depth; + int i; + uchar* framebufpos = framebuffer; + uchar* screendatapos = screendata; + int width; + + if(rectangle.min.x < 0) + rectangle.min.x = 0; + if(rectangle.min.y < 0) + rectangle.min.y = 0; + if(rectangle.max.x > Xsize) + rectangle.max.x = Xsize; + if(rectangle.max.y > Ysize) + rectangle.max.y = Ysize; + + if((rectangle.max.x < rectangle.min.x) || (rectangle.max.y < rectangle.min.y)) + return; + + framebufpos += rectangle.min.y * bpl + rectangle.min.x * depth; + screendatapos += rectangle.min.y * bpl + rectangle.min.x * depth; + width = (rectangle.max.x - rectangle.min.x) * depth; + for(i = rectangle.min.y; i < rectangle.max.y; i++) { + memcpy(framebufpos, screendatapos, width); + framebufpos += bpl; + screendatapos += bpl; + } + + if(!ispointervisible) + return; + Point mousepos = mousexy(); + curslock(); + if((max(rectangle.min.x, mousepos.x + icursor.hotx) > min(rectangle.max.x, mousepos.x + icursor.hotx + icursor.w)) || + (max(rectangle.min.y, mousepos.y + icursor.hoty) > min(rectangle.max.y, mousepos.y + icursor.hoty + icursor.h))) { + cursunlock(); + return; + } + cursunlock(); + drawpointer(mousepos.x, mousepos.y); +} +uchar DefaultPointer [] = { + 0x00, 0x00, /* 0000000000000000 */ + 0x7F, 0xFE, /* 0111111111111110 */ + 0x7F, 0xFC, /* 0111111111111100 */ + 0x7F, 0xF8, /* 0111111111111000 */ + 0x7F, 0xF0, /* 0111111111110000 */ + 0x7F, 0xE0, /* 0111111111100000 */ + 0x7F, 0xC0, /* 0111111111000000 */ + 0x7F, 0xE0, /* 0111111111100000 */ + 0x7F, 0xF0, /* 0111111111110000 */ + 0x7F, 0xF8, /* 0111111111111000 */ + 0x7C, 0xFC, /* 0111110011111100 */ + 0x78, 0x7E, /* 0111100001111110 */ + 0x70, 0x3C, /* 0111000000111100 */ + 0x60, 0x18, /* 0110000000011000 */ + 0x40, 0x00, /* 0100000000000000 */ + 0x00, 0x00, /* 0000000000000000 */ +}; + +uchar DefaultPointerMask [] = { + 0xFF, 0xFF, /* 1111111111111111 */ + 0xFF, 0xFF, /* 1111111111111111 */ + 0xFF, 0xFE, /* 1111111111111110 */ + 0xFF, 0xFC, /* 1111111111111100 */ + 0xFF, 0xF8, /* 1111111111111000 */ + 0xFF, 0xF0, /* 1111111111110000 */ + 0xFF, 0xE0, /* 1111111111100000 */ + 0xFF, 0xF0, /* 1111111111110000 */ + 0xFF, 0xF8, /* 1111111111111000 */ + 0xFF, 0xFC, /* 1111111111111100 */ + 0xFF, 0xFE, /* 1111111111111110 */ + 0xFC, 0xFF, /* 1111110011111111 */ + 0xF8, 0x7E, /* 1111100001111110 */ + 0xF0, 0x3C, /* 1111000000111100 */ + 0xE0, 0x18, /* 1110000000011000 */ + 0xC0, 0x00, /* 1100000000000000 */ +}; + +static const int DefaultPointerHeight = 16; +static const int DefaultPointerWidth = 16; + +static void +initcursor(uchar* clr, uchar* set, int height, int width, int hotx, int hoty) +{ + uchar i, j, k; + uchar *ps, *pc, *bc, *bs, cb, sb; + int depth = displaydepth / 8; + int bpl; + + if(!clr) { + set = DefaultPointer; + clr = DefaultPointerMask; + height = DefaultPointerWidth; + width = DefaultPointerHeight; + hotx = 0; + hoty = 0; + } + bpl = width / 8; + curslock(); + if(icursor.set) + free(icursor.set); + icursor.set = malloc(height * width * depth); + if(!icursor.set) { + fprint(2, "cannot allocate cursor"); + return; + } + memset(icursor.set, 0xFF, height * width * depth); + + if(icursor.clr) + free(icursor.clr); + icursor.clr = malloc(height * width * depth); + if(!icursor.clr) { + fprint(2, "cannot allocate cursor mask"); + return; + } + memset(icursor.clr, 0x0, height * width * depth); + + ps = icursor.set; + pc = icursor.clr; + bs = set; + bc = clr; + for(i = 0; i < height; i++) { + for(j = 0; j < bpl; j++) { + sb = revbyte(bs[j]); + cb = revbyte(bs[j] | bc[j]); + for(k = 0; k < 8; k++) { + if(sb & (1< Xsize) + x = Xsize; + if(y < 0) + y = 0; + else if(y > Ysize) + y = Ysize; + curslock(); + icursor.x = x; + icursor.y = y; + cursunlock(); + drawpointer(icursor.x, icursor.y); +} + +static void +cleanpointer() +{ + if(!framebuffer || !screendata) + return; + int depth = displaydepth / 8; + int bpl = Xsize * depth; + int i; + int x = icursor.x + icursor.hotx; + if(x < 0) + x = 0; + int y = icursor.y + icursor.hoty; + if(y < 0) + y = 0; + uchar* framebufpos = framebuffer + y * bpl + x * depth; + uchar* screendatapos = screendata + y * bpl + x * depth; + int width = icursor.w * depth; + int height = ((y + icursor.h) < Ysize) ? icursor.h : Ysize - y; + for(i = 0; i < height; i++) { + memcpy(framebufpos, screendatapos, width); + framebufpos += bpl; + screendatapos += bpl; + } +} + +static void +drawpointer(int x, int y) +{ + uchar i = 0, j, k, J = 0; + uchar depth = displaydepth / 8; + x += icursor.hotx; + y += icursor.hoty; + if(x < 0){ + J = -x * depth; + x = 0; + } + if(y < 0){ + i = -y; + y = 0; + } + uchar* curpos = framebuffer + y * Xsize * depth + x * depth; + curslock(); + int width = ((x + icursor.w) < Xsize) ? icursor.w : Xsize - x; + int height = ((y + icursor.h) < Ysize) ? icursor.h : Ysize - y; + for(; i < height; i++, curpos += Xsize * depth) + for(j = J, k = 0; j < width * depth; j++, k++) + if(icursor.clr[i * depth * icursor.w + j]) + curpos[k] = icursor.set[i * depth * icursor.w + j]; + cursunlock(); +} + +char* +clipread(void) +{ + return clipboard.clip; +} + +int +clipwrite(char *buf) +{ + int size = strlen(buf); + if((size > clipboard.size) && realloc(clipboard.clip, size)) { + clipboard.size = size; + strncpy(clipboard.clip, buf, clipboard.size); + } + return 0; +} + +int +segflush(void *va, ulong len) +{ + return 0; +} + + diff -r d1acc2a527af emu/Linux/os.c --- a/emu/Linux/os.c Mon Oct 03 19:15:19 2011 +0100 +++ b/emu/Linux/os.c Mon Oct 10 09:04:29 2011 +0300 @@ -297,6 +297,9 @@ if(dflag == 0) termrestore(); +#if defined(FB_SUPPORT) + fb_deinit(); +#endif kill(0, SIGKILL); exit(0); @@ -319,7 +322,9 @@ Proc *p; void *tos; char sys[64]; - +#if defined(FB_SUPPORT) + sigset_t mask; +#endif setsid(); gethostname(sys, sizeof(sys)); @@ -340,6 +345,11 @@ act.sa_handler = SIG_IGN; sigaction(SIGCHLD, &act, nil); +#if defined(FB_SUPPORT) + sigemptyset(&mask); + sigaddset(&mask, SIGIO); + sigprocmask(SIG_BLOCK, &mask, NULL); +#endif /* * For the correct functioning of devcmd in the * face of exiting slaves diff -r d1acc2a527af emu/port/devpointer.c --- a/emu/port/devpointer.c Mon Oct 03 19:15:19 2011 +0100 +++ b/emu/port/devpointer.c Mon Oct 10 09:04:29 2011 +0300 @@ -73,6 +73,14 @@ x += mouse.v.x; y += mouse.v.y; } + if(x < 0) + x = 0; + else if (x > Xsize) + x = Xsize; + if(y < 0) + y = 0; + else if (y > Ysize) + y = Ysize; msec = osmillisec(); if(0 && b && (mouse.v.b ^ b)&0x1f){ if(msec - mouse.v.msec < 300 && mouse.lastb == b @@ -100,7 +108,7 @@ ptrq.put++; Wakeup(&ptrq.r); /* drawactive(1); */ -/* setpointer(x, y); */ + setpointer(x, y); } static int @@ -251,6 +259,8 @@ else b = mouse.v.b; /*mousetrack(b, x, y, msec);*/ + mouse.v.x = x; + mouse.v.y = y; setpointer(x, y); USED(b); break;