Malc's idea seems to work so take that for what it's worth :)<jadamcze> cheriff: ps3 fb is ARGB8888, libvncserver doesn't seem to support converting from that format
<jadamcze> There appears to be no magic option to get the colours right. afaict.
<malc> just add one to fb_ea if you're not using the alpha...
Hi, I find this useful, so thought I might share. It takes whatever format /dev/fb0 is set to, and uses it as input for a simple VNC server.
Caveats:
- resends entire buffer each frame
 probably not secure much
 colours seem mixed up, either an endian or pixel format issue
Try using ps3-video-mode to change the size of the framebuffer, and hence the performance.. 720p seems to work nicely for me on a 100MB network.
You need to have libvncserver properly installed. Gentoo just emerged it properly for me.
Credits: mostly ripped from the provided sample applications
Building:
Code: Select all
make main.o
gcc -o main main.o -lvncserver
./mainCode: Select all
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <rfb/rfb.h>
#include <rfb/keysym.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <asm/ps3fb.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
typedef struct ClientData {
    rfbBool oldButton;
    int oldx,oldy;
} ClientData;
rfbClientPtr gcl = NULL;
static void doptr(int buttonMask,int x,int y,rfbClientPtr cl){
}
static void dokey(rfbBool down,rfbKeySym key,rfbClientPtr cl)
{
}
static void clientgone(rfbClientPtr cl)
{
    free(cl->clientData);
    gcl = NULL;
}   
static enum rfbNewClientAction newclient(rfbClientPtr cl)
{
    cl->clientData = (void*)calloc(sizeof(ClientData),1);
    cl->clientGoneHook = clientgone;
    gcl = cl;
    return RFB_CLIENT_ACCEPT;
}   
int main(int argc, char *argv[]){
    int fd = open("/dev/fb0", O_RDWR);
    struct ps3fb_ioctl_res res;
    
    ioctl(fd, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res);
    printf("xres: %d, yres: %d, xoff: %d, yoff: %d, num_frames: %d\n",
            res.xres, res.yres, res.xoff, res.yoff, res.num_frames); 
    unsigned int length = res.xres * res.yres * 4 * res.num_frames;  
    int bpp = 4; 
    
    void * buffer = mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0);
    rfbScreenInfoPtr rfbScreen =
        rfbGetScreen(&argc,argv, res.xres, res.yres,8,3,bpp);
    rfbScreen->desktopName = "PS3 VNC";
    rfbScreen->frameBuffer = buffer;
    rfbScreen->alwaysShared = TRUE;
    rfbScreen->ptrAddEvent = doptr;
    rfbScreen->kbdAddEvent = dokey;
    rfbScreen->newClientHook = newclient;
    rfbScreen->httpDir = "../classes";
    rfbScreen->httpEnableProxyConnect = TRUE;
    rfbInitServer(rfbScreen);
    while(1){
        rfbMarkRectAsModified(rfbScreen, 0,0,res.xres,  res.yres);
        rfbProcessEvents(rfbScreen,1);
        if (gcl){
            rfbSendUpdateBuf(gcl);
        }   
    }
}