This page highlights some differences between OpenDingux and the legacy system (booboo's kernel and accompanying rootfs).

Be sure to check the OpenDingux Development FAQ.



Frame Buffer

When setting a video mode, the legacy kernel will accept any requested resolution and color depth but regardless of what was asked it will return a 320x240x16bpp mode. This would break SDL's automatic color depth conversion since SDL would think no conversion was necessary. Elta's rootfs patches SDL to work around this issue. In OpenDingux, requests to the kernel for modes other than 320x240x16bpp will fail. If you're using SDL, you can ask SDL for 320x240x8bpp and SDL will automatically do the colorspace conversion for you. If you ask for a resolution other than 320x240, both the kernel and SDL will deny that request.

SDL has three surface modes:

These modes are selected by passing the mentioned flags to SDL_SetVideoMode().

In the legacy kernel, software surface and hardware surface with single buffering work. However, single buffering means that any pixel drawn can immediately end up on the screen even if the current frame is not finished yet. As a result, any graphics that are painted in layers will end up flickering badly. This can be seen in the optional info bar at the top of the screen in psx4all, for example. Double buffering in the legacy kernel is broken so badly it will likely crash or hang the application that tries to use it.

In OpenDingux, all three modes work. Currently the page flip of double buffering is not properly synchronized yet, so there can be glitches, but they are relatively rare. Hardware surface with double buffering is the preferred mode since it has lower overhead than the software surface: one less buffer in memory and one less buffer to copy each frame, and does not suffer from the tearing and layer paint issues of the single buffered hardware surface.

If you want to access the frame buffer directly, make sure you always lock the surface before using the "pixels" pointer in the SDL_Surface struct. Also make sure you end a frame by calling SDL_Flip(), since that works for both software and hardware surfaces, while SDL_UpdateRect() only works for software surfaces.

Here is some stripped down example code:

SDL_Surface *surface = SDL_SetVideoMode(320, 240, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
if (!surface) {
    // ...error handling...

// ...other initialization code...

while (running) {

    // ...stuff to do every frame...

    if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);

    // ...access frame buffer directly through surface->pixels...

    if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);

LCD Backlight

The intensity of the backlight can be controlled through sysfs:

# echo 120 > /sys/class/backlight/pwm-backlight/brightness

From the same brightness file you can also read the current value. The minimum brightness is 0 (off), the maximum can be read from the max_brightness file. The maximum is 255 under OpenDingux, but it's more portable to read it from the file.

The user can control the backlight intensity at all times via the power slider daemon (power + left/right), so there is no real need to have a backlight control in applications as well.

Display Blanking

You can turn off the display by writing the string "1" to the blank file in sysfs:

# echo 1 > /sys/class/graphics/fb0/blank

To turn the display back on, write "0" to the same file.

Blanking not only turns off the backlight, it also powers down the LCD controller and suspends frame uploads to the LCD controller.


ALSA driver

The OpenDingux kernel features a totally new sound driver compared to previous kernels. While those ones did use OSS, OpenDingux has now an ALSA driver. That new driver has been merged on the mainline linux kernel. The rootfs also packs the user-space ALSA library, with a default config, that could be modified to add funny stuff like an equalizer or surround sound. As the integrated SDL library has been compiled to use ALSA, all the programs which are using SDL for sound should work just fine on OpenDingux, provided they have been dynamically linked.


Some programs however do use OSS directly. Those will need to be modified. As the ALSA interface is quite different to the OSS one, a new sound library has been included, libAO. It is really trivial to use and to make a OSS-only program work with ALSA this way. Click here for an example that explains how to use it.

Sound volume

On OpenDingux there is no way for the applications to change the sound volume themselves. It has been disabled on purpose. Instead, the global shortcuts for the volume should be used.


Some applications were reading /dev/mem directly to retrieve the state of the dingoo buttons. To avoid conflicts between the kernel and user space applications accessing the same hardware, /dev/mem has been disabled. The applications should use instead either SDL key events, or use the standard linux way of reading the keys: /dev/event0.

The kernel header <linux/input.h> contains constants named KEY_* with the numbers used to identify keys in input events.

Here is the key mappping for OpenDingux:

D-pad up KEY_UP
D-pad down KEY_DOWN
D-pad left KEY_LEFT
D-pad right KEY_RIGHT
X button KEY_SPACE
Left shoulder KEY_TAB
Right shoulder KEY_BACKSPACE
Power slider KEY_POWER
Power hold KEY_PAUSE

Note that putting the power slider in hold position is a key down event and taking it out of the hold position is a key release event; this is different from a PC pause key where you'd do press+release to pause and press+release again to unpause.

Also see (whilst it is for the Native OS, the SDL information is the same). Also see for an example that also works with OpenDingux

CPU Frequency Control

The sysfs pseudo-files /sys/devices/system/cpu/cpu0/cpufreq/* control the PLL frequency through the cpufreq driver.



You can read the battery status from the following file:


It contains a percentage: 0 is empty and 100 is full. This percentage is a best effort, but it is not very accurate.

Power consumption measurements

Before loading the kernel

55mA = usb boot mode (B pressed during power on)
150mA = hwinit screen

OpenDingux started

48mA = idle, 34MHz, brightness=0, ILI off
66mA = idle, 34MHz, brightness=0
88mA = idle, 34MHz, brightness=100
126mA = idle, 34MHz, brightness=255

68mA = idle, 408MHz, brightness=0, ILI off
88mA = idle, 408MHz, brightness=0
110mA = idle, 408MHz, brightness=100
147mA = idle, 408MHz, brightness=255

80mA = heavy load, 34MHz, brightness=0, ILI off
87mA = heavy load, 34MHz, brightness=0
110mA = heavy load, 34MHz, brightness=100
148mA = heavy load, 34MHz, brightness=255

171mA = heavy load, 408MHz, brightness=0, ILI off
179mA = heavy load, 408MHz, brightness=0
190mA = heavy load, 408MHz, brightness=100
220mA = heavy load, 408MHz, brightness=255

9mA = suspend mode

Building OpenDingux from sources


The basic steps:

$ git clone git://
$ cd qi-kernel
$ git checkout jz-3.3
$ make ARCH=mips a320_defconfig
$ make ARCH=mips vmlinuz.bin

At the time of writing, Linux 3.3 is the most recent kernel, thus the branch named "jz-3.3" is selected in this example. Please adjust it yourself for newer kernel versions. You can use the command "git branch" to see all branches.

If your Dingoo does not have an ILI9331 LCD controller, you have to update the configuration between building a320_defconfig and vmlinuz.bin.

Root file system

The basic steps:

$ git clone git://
$ cd opendingux-buildroot
$ make a320_defconfig
$ make

If you have a multi-core CPU and would like to speed up the build, don't pass "-j" to Make, but instead set the BR2_JLEVEL environment variable. For example: export BR2_JLEVEL=4; this instructs buildroot to perform 4 jobs in parallel.

The skeleton for the root file system is in target/device/opendingux/a320/target_skeleton/. There you can edit the default configuration files or add scripts. After you make your changes, copy the new files to output/target and run make to generate a new rootfs image.

To add a package, first make sure the package is available in buildroot. If a package is not available yet, read docs/buildroot.html for instructions on how to add a package. Then run make menuconfig to enable the package and just make to build it and generate a new rootfs image.

Development in OpenDingux - Hello World!

Installing the toolchain

All the steps described below can be done in user interface with equivalent results.

Take the last available toolchain in OpenDingux page and decompress it:

tar -xvf opendingux-toolchain.2012-06-16.tar.bz2

Copy the extracted folder in /opt:

sudo cp -a opendingux-toolchain /opt

Add the toolchain to your PATH (For always have the toolchain available in your PATH, you can edit your ~/.bashrc and put the command below inside the file):

export PATH="${PATH}:/opt/opendingux-toolchain/usr/bin"

Testing the toolchain

A very simple program is showed below to illustrate how we can make software for OpenDingux:


int main()
    printf("Testing OpenDingux!\n");
    printf("Waiting 5 seconds...\n");
    return 0;

Save the program with filename that you want. In this example the filename will be test_od.c. For compile this source code:

mipsel-linux-gcc test_od.c -o test_od.dge

OBS: Usually, OpenDingux programs have .dge as extension.

After compile the program, we can put this executable in our SD card. We can do this with telnet, or ftp.

We can test this programs in two ways:


Connect with telnet in your dingoo, find your executable and execute(in this example ./test_od.dge).

Directly in OpenDingux

In OpenDingux, go to the Application session, and press Select -> Add link in applications.

So, find your executable and press A. It will create a shortcut to execute your program in the Application session.

Press Select -> Edit test_od.dge and change Display Console to ON.

Now just press A in the shortcut and it will show our message!