PS3 export fb0 to VNC

Investigation into how Linux on the PS3 might lead to homebrew development.

Moderators: cheriff, emoon

Post Reply
cheriff
Regular
Posts: 258
Joined: Wed Jun 23, 2004 5:35 pm
Location: Sydney.au

PS3 export fb0 to VNC

Post by cheriff »

UPDATE: from IRC:
<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...
Malc's idea seems to work so take that for what it's worth :)

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
That last one could be easily fixed with the right parameter in the setup code, I just cant be bothered huntin through headers for it.
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
./main
Code: (ugly and hackish, but mostly works)

Code: 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 &#123;
    rfbBool oldButton;
    int oldx,oldy;
&#125; ClientData;
rfbClientPtr gcl = NULL;

static void doptr&#40;int buttonMask,int x,int y,rfbClientPtr cl&#41;&#123;
&#125;

static void dokey&#40;rfbBool down,rfbKeySym key,rfbClientPtr cl&#41;
&#123;
&#125;

static void clientgone&#40;rfbClientPtr cl&#41;
&#123;
    free&#40;cl->clientData&#41;;
    gcl = NULL;
&#125;   


static enum rfbNewClientAction newclient&#40;rfbClientPtr cl&#41;
&#123;
    cl->clientData = &#40;void*&#41;calloc&#40;sizeof&#40;ClientData&#41;,1&#41;;
    cl->clientGoneHook = clientgone;
    gcl = cl;
    return RFB_CLIENT_ACCEPT;
&#125;   

int main&#40;int argc, char *argv&#91;&#93;&#41;&#123;

    int fd = open&#40;"/dev/fb0", O_RDWR&#41;;
    struct ps3fb_ioctl_res res;
    
    ioctl&#40;fd, PS3FB_IOCTL_SCREENINFO, &#40;unsigned long&#41;&res&#41;;
    printf&#40;"xres&#58; %d, yres&#58; %d, xoff&#58; %d, yoff&#58; %d, num_frames&#58; %d\n",
            res.xres, res.yres, res.xoff, res.yoff, res.num_frames&#41;; 
    unsigned int length = res.xres * res.yres * 4 * res.num_frames;  
    int bpp = 4; 
    
    void * buffer = mmap&#40;NULL, length, PROT_WRITE, MAP_SHARED, fd, 0&#41;;

    rfbScreenInfoPtr rfbScreen =
        rfbGetScreen&#40;&argc,argv, res.xres, res.yres,8,3,bpp&#41;;
    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&#40;rfbScreen&#41;;
    while&#40;1&#41;&#123;
        rfbMarkRectAsModified&#40;rfbScreen, 0,0,res.xres,  res.yres&#41;;
        rfbProcessEvents&#40;rfbScreen,1&#41;;
        if &#40;gcl&#41;&#123;
            rfbSendUpdateBuf&#40;gcl&#41;;
        &#125;   
    &#125;
&#125;
ENJOY![/quote]
Last edited by cheriff on Wed Sep 03, 2008 8:30 am, edited 1 time in total.
Damn, I need a decent signature!
ps2devman
Posts: 259
Joined: Mon Oct 09, 2006 3:56 pm

Post by ps2devman »

thanks for sharing
cheriff
Regular
Posts: 258
Joined: Wed Jun 23, 2004 5:35 pm
Location: Sydney.au

Post by cheriff »

no problem.
One thing I should point out its that the '1' in 'rfbProcessEvents(rfbScreen,1);' refers to how long we should sleep in the select(). Making this larger will cause the server to sleep longer and perhaps not burn so much CPU in the busy loop. I guess each to his own for the CPU/responsiveness tradeoff.

I did try getting it to vsync, hoping that would cause it also sync to the app, thereby refresh at 60Hz and avoid tearing - no such luck. Maybe someone else will have better luck.

I actually optionally incorporate this into my app, so instead of actually rendering to fb0, just to a malloc'd region that is passed to the library and then update the screen in the call to flip(). No tearing that way, and can use arbitrary screen sizes like 800x600, which is a nice size to dev in on a busy screen.

So guess this is more of a proof of concept and starting point, rather than a finished thing anyone would be expected to use as-is :)
Damn, I need a decent signature!
ZeZu
Posts: 2
Joined: Thu Jan 06, 2005 4:13 am

Post by ZeZu »

Here is a quick fix for color correction:

rfbScreen->serverFormat.redShift = 16;
rfbScreen->serverFormat.greenShift = 8;
rfbScreen->serverFormat.blueShift = 0;

Will have more fixes later,
code is very usefull for me, thanks for posting
pettersson
Posts: 2
Joined: Wed Aug 26, 2009 6:08 pm

Post by pettersson »

Hi,

"InStream max string length exceeded" is the error I get when using the code above and trying to connect to my PS3.

Any help or insights are appreciated :)

.pettersson
cheriff
Regular
Posts: 258
Joined: Wed Jun 23, 2004 5:35 pm
Location: Sydney.au

Post by cheriff »

Hi pettersson,

Are you per chance using libvncserver as distributed by debian? (perhaps also including Ubuntu)

I've heard one report that the binary in apt appears to be buggy, but building from source seems to work fine.

Does that help any?

pettersson wrote:Hi,

"InStream max string length exceeded" is the error I get when using the code above and trying to connect to my PS3.

Any help or insights are appreciated :)

.pettersson
Damn, I need a decent signature!
pettersson
Posts: 2
Joined: Wed Aug 26, 2009 6:08 pm

Post by pettersson »

Hi,

thanks for your answer. I compiled libvncserver from the sources.
But i found another solution for my problem: I bought a second PS3, so I have one in my living room and one on my desk, so no need for vnc for now :)

regards,
pettersson
Post Reply