Coding Chase - Projects

My 3D Hub

Thank You For Donating:

Ikeeki (linux-sunxi@irc.freenode.net)
Computer Troubleshooters Brasil

Wednesday 26 February 2014

Qt5 on Cubieboard (A10/A20)

Since last year, I've been working with the Cubieboard community in order to have Qt5 running on Cubie, using the sunxi mali libraries. I started off with Cubieboard A10, then moved on to Cubieboard 2 (A20) and finally Cubietruck (also A20).

My main goal was to be able to cross-compile Qt5 (because native compile takes forever on these embedded devices) and be able to control the entire process, from SD Card image generation to Qt5 App development.

Below is the complete guide to achieve this, it is quite extensive and I advise doing regular SD Card backups along the way:


Cubieboard (A20 Soc, should also work with A10)

Main objectives:

1) Produce a working SD Card image for cubieboard, supporting the latest Mali libraries from sunxi.
2) Cross-Compile Qt5 latest stable version using said libraries
3) Test performance using QuitCoding's Cinematic Experience Demo


Step 1, Building the STOCK SD Card Image


The Sunxi wiki supplies some steps on how to achieve this. You can always use a prebuilt image (cubian, cubiuntu, whatever) but my take on this is to have end-to-end control over the whole process.

This is the general guide to follow when wanting to build a custom image from scratch:

http://linux-sunxi.org/FirstSteps

This process can be quite cumbersome, so there is an alternative to this:

http://linux-sunxi.org/BSP

Using the Board Support Package alternative, generating the initial image is a lot easier. You'll just have to focus on three things:

1) the cross-compile gcc you'll be using
2) the rootfs you'll be using
3) an SD Card class 4 (but 10 would be better) 4GB or more (though 4GB would be ideal in my opinion)

So, use Linux as the dev host (I used Linux Mint x64) and install all the dependencies required in the guide.
Grab the gcc-linaro-arm-linux-gnueabihf-4.8-2013.09 gcc and make sure it's in your env PATH

Next up, clone the sunxi-bsp git repository and start working:

- use ./configure <board> to select your board (cubieboard2 for example)
- make

then to generate the SD Card, follow the guide:

./scripts/sunxi-media-create.sh [device] [hwpack] [rootfs]

[device] is the /dev/ device for the sd card (not the partitions)

[hwpack] is the reference hwpack that results from the make output

[rootfs] - for this one, I've used linaro rootfs:
either this one > linaro-precise-alip-20121124-519
or this newer one > linaro-raring-server-20130826-474

I've done some research for Qt5 on framebuffer mostly, so the server version (no X11) served me right, but choose whatever rocks your boat, considering your Qt5 needs later on.

Once that's done, you'll hopefully have a stock SD card image ready to work.

Things you can tweak at this level:

1) modify your script.bin file, to change output from HDMI to VGA, enable GPIO, etc.
2) modify the linux-sunxi stock kernel - enable functionalities, whatever you need.

After firing the SD Card on Cubie for the first time, you may want to set up a few things like ssh and fixed MAC Address so that you're able to assign static IPs over DHCP for example.

Once your stock card is ready, you may shutdown cubie and pop the card back on your linux host machine and to a sanity backup like so:

# dd bs=1M if=/dev/<card_device> of=/opt/sdcard.img;sync



Step 2, Building/Installing the Mali tweaked Kernel


SD card backup or not, mount the SD Card, specifically the root partition.

I'm not sure if but the time of this writing the stock 3.4 sunxi kernel already has the correct patches for the latest Mali libraries. I've followed ssvb's work on this and found best to just stick to his github repo and his kernels:

https://github.com/ssvb/linux-sunxi

Go for the mali branches and clone the latest:

https://github.com/ssvb/linux-sunxi/tree/20140116-mali-r3p2-01rel2

Once you have it, you'll be OK to build it manually, for the ARM arch on Cubie:

cd linux-sunxi
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sun7i_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j5 uImage modules
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=output modules_install

You'll obtain an output directory with firmware and modules - copy those directories to the /lib/firmware and /lib/modules dirs on the sd card, and also the uImage file (the newly compiled kernel) somewhere around arch/arm/boot....

Unmount the card, fire it up again on cubie, run uname -a and make sure it's using the ssvb's kernel.
(at this point it's up to you to shutdown and do another sd card backup or not)


Step 3, Install the Mali libraries


http://linux-sunxi.org/Binary_drivers

Set the proper permissions and work your way to install the binary drivers. From git, you get the framebuffer and also X11 binary blobs, install whichever suits your needs and your chosen sd card rootfs type (server/desktop)

Just after the git submodule update, when getting to the make install step, instead do:

# make config VERSION=r3p2-01rel1 ABI=armhf EGL_TYPE=framebuffer
# make
# make install

/* for X11 */

EGL_TYPE=x11

/* for X11 */

NOTE:

at make install:

../../../Makefile.split:4: *** missing separator (did you mean TAB instead of 8 spaces?).  Stop.

If you get an error during make/make install about an incorrectly formed Makefile.split file, follow the message, edit the Makefile.split file and replace all 8 space indentations at the beginning of the lines, with 1 tab on each line.

Once the binary drivers are installed, there's a test example which you'll build and run. Getting a coloured triangle like in the video below will confirm that the libraries are working properly:

framebuffer > http://www.youtube.com/watch?v=45ry-PXneCU#t=125

sd card backup decision time!



Step 4, Cross-Compiling Qt5


Ok, so by now Qt5 is all we're missing.

This box.com link should set you up for this step. The Qt5 stable version in there is outdated, since then I've managed to successfully build version 5.2.0 as well, but you can go further.

- Grab the latest stable version from qt-project (by the time you read this, check if newer versions are available):

http://download.qt-project.org/archive/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.xz

Cross-compiling Qt5 will require some dependencies being installed to the env host, as well as the mounted sd card image.

Prepare the host:

sudo apt-get install ia32-libs (consider installing these if your host OS is x64)

update 2014-10-11:
On Ubuntu 14.04 x64 this package doesn't exist anymore, so consider doing the following steps:

sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0 libstdc++6:i386


Next, prepare the sd card system (these are only needed if later on you'd like to also build QtWebkit. For that, Qt must be cross-compiled with these deps installed on the embedded OS)

sudo apt-get install flex bison gperf libicu-dev libxslt-dev ruby

Create an SD card image using dd on the cross compile host (I'm using Linux Mint) - check the paths!

dd bs=1M if=/dev/mmcblk0 of=/opt/qt5.cubieboard2A20.workbench/linaro.1211.ssvb.malifb.Qt511.QtWebkit.img;sync

Mount the SD Card image, just the OS partition (exclude the boot partition)
With linux you have "parted" to find the byte offset:
parted <sdcardimage>
> unit B
> p
this will show the partitions on the SD Card image, use the starting byte for the root partition, where de system lies
In my case:
mount -o loop,offset=68157440 /opt/qt5.cubieboard2A20.workbench/linaro.1211.ssvb.malifb.Qt511.QtWebkit.img /opt/qt5.cubieboard2A20.workbench/cubie2-rootfs/

git clone git://gitorious.org/cross-compile-tools/cross-compile-tools.git

Fix the library paths between the sd card image and the compiler - this should only have to be done once

./fixQualifiedLibraryPaths /opt/qt5.cubieboard2.workbench/cubie-rootfs /opt/qt5.cubieboard2/gcc-linaro-arm-linux-gnueabihf-4.8-2013.09_linux/bin/arm-linux-gnueabihf-g++

Uncompress the Qt5 archive as root and copy over the mkspec files for cubieboard:

cp -R linux-cubieboard2-g++ ./qt-everywhere-opensource-src-5.1.1/qtbase/mkspecs/devices/

(these mkspecs are based on the beagleboard files, included in the Qt5 sources)


/* For framebuffer */

(from the box.com archives)
cp -R qeglfshooks_stub.cpp ./qt-everywhere-opensource-src-5.1.1/qtbase/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp


NOTE: on later Qt5 sources, the qeglfshooks_stub I have may not cut it. You may need to manually edit the file and change it, if so, do it according to this:

Modified qeglfshooks_stub.cpp for 5.2.0, only needed to modify EGLNativeWindowType QEglFSHooks::createNativeWindow like in 5.1.1:

EGLNativeWindowType QEglFSHooks::createNativeWindow(QPlatformWindow *platformWindow,
                                                    const QSize &size,
                                                    const QSurfaceFormat &format)
{
    Q_UNUSED(platformWindow);
    Q_UNUSED(size);
    Q_UNUSED(format);
    //return 0;

    static struct mali_native_window native_window = {
        .width = (short unsigned int)size.width(),
        .height = (short unsigned int)size.height(),
    };
    return &native_window;
}




/* For framebuffer */


Get ready to compile Qt5 for framebuffer (adapt the configure line paths to your own)

cd qt-everywhere-opensource-src-5.1.1

Important: Check all your paths below

./configure \
-opengl es2 \
-device linux-cubieboard2-g++ \
-device-option CROSS_COMPILE=/opt/sdcard.cubieboard.workbench/gcc-linaro-arm-linux-gnueabihf-4.8-2013.09_linux/bin/arm-linux-gnueabihf- \
-sysroot /opt/qt5.cubieboard2A20.workbench/cubie2-rootfs \
-opensource \
-confirm-license \
-optimized-qmake \
-release \
-make libs \
-prefix /usr/local/qt5cb2 \
-no-pch \
-nomake examples \
-nomake tests \
-no-xcb \
-eglfs \
-v

Check the config.summary file, mine is below - again this is the framebuffer version:

cat qt-everywhere-opensource-src-5.1.1/qtbase/config.summary 

   Configure summary

Building on:   linux-g++ (x86_64, CPU features: mmx sse sse2)
Building for:  devices/linux-cubieboard2-g++ (arm, CPU features: neon)
Platform notes:

            - Also available for Linux: linux-kcc linux-icc linux-cxx
        
qmake vars .......... styles += mac fusion windows QMAKE_CFLAGS_FONTCONFIG = -I/opt/qt5.cubieboard2A20.workbench/cubie2-rootfs/usr/include/freetype2   QMAKE_LIBS_FONTCONFIG = -L/opt/qt5.cubieboard2A20.workbench/cubie2-rootfs/usr/lib/arm-linux-gnueabihf -lfontconfig -lfreetype   DEFINES += QT_NO_LIBUDEV DEFINES += QT_NO_XCB DEFINES += QT_NO_XKBCOMMON PRECOMPILED_DIR = .pch/release-shared OBJECTS_DIR = .obj/release-shared MOC_DIR = .moc/release-shared RCC_DIR = .rcc/release-shared UI_DIR = .uic/release-shared sql-drivers =  sql-plugins =  sqlite qmake switches ......... 

Build options:
  Configuration .......... accessibility audio-backend c++11 clock-gettime clock-monotonic compile_examples concurrent cross_compile egl eglfs evdev eventfd fontconfig full-config getaddrinfo getifaddrs iconv icu inotify ipv6ifname large-config largefile linuxfb medium-config minimal-config mremap neon nis opengl opengles2 pcre png qpa qpa reduce_exports reduce_relocations release rpath shared small-config system-freetype system-zlib v8 xlib xrender 
  Build parts ............  libs
  Mode ................... release
  Using C++11 ............ yes
  Using PCH .............. no
  Target compiler supports:
    iWMMXt/Neon .......... no/yes

Qt modules and options:
  Qt D-Bus ............... no
  Qt Concurrent .......... yes
  Qt GUI ................. yes
  Qt Widgets ............. yes
  JavaScriptCore JIT ..... yes (To be decided by JavaScriptCore)
  QML debugging .......... yes
  Use system proxies ..... no

Support enabled for:
  Accessibility .......... yes
  ALSA ................... no
  CUPS ................... no
  FontConfig ............. yes
  Iconv .................. yes
  ICU .................... yes
  Image formats: 
    GIF .................. yes (plugin, using system library)
    JPEG ................. yes (plugin, using bundled copy)
    PNG .................. yes (in QtGui, using bundled copy)
  Glib ................... no
  GStreamer .............. no
  GTK theme .............. no
  Large File ............. yes
  libudev ................ no
  Networking: 
    getaddrinfo .......... yes
    getifaddrs ........... yes
    IPv6 ifname .......... yes
    OpenSSL .............. no
  NIS .................... yes
  OpenGL ................. yes (OpenGL ES 2.x)
  OpenVG ................. no
  PCRE ................... yes (bundled copy)
  pkg-config ............. yes 
  PulseAudio ............. no
  QPA backends: 
    DirectFB ............. no
    EGLFS ................ yes
    KMS .................. no
    LinuxFB .............. yes
    XCB .................. no
  Session management ..... yes
  SQL drivers: 
    DB2 .................. no
    InterBase ............ no
    MySQL ................ no
    OCI .................. no
    ODBC ................. no
    PostgreSQL ........... no
    SQLite 2 ............. no
    SQLite ............... yes (plugin, using bundled copy)
    TDS .................. no
  udev ................... no
  xkbcommon .............. no
  zlib ................... yes (system library)


Important bits:

  QPA backends: 
    DirectFB ............. no
    EGLFS ................ yes
    KMS .................. no
    LinuxFB .............. yes
    XCB .................. no


(For QtWebkit, as a side note, ICU must be available as well)


make -j 5 && make install


Once Qt5 builds:

the library files will be placed in /usr/local/qt5cb2 in the sd card rootfs
the qmake binary will be placed in /usr/local/qt5cb2 on the dev host

My host took less than 1h to build everything successfully, QtWebkit as well


Step 5, Cross-Compiling Qt5 Apps


Ok, by now you should have:

- a working SD Card image, with the latest mali libraries and installed Qt5 libraries
- a Qt5 development environment on your host

Make sure the SD Card image is unmounted and burn it on a card:

# dd bs=1M if=/path/cubie.img of=<sd device>; sync

Start cubieboard and make sure it's fully functional, and then get back to the development host.

On the host, you'll need to install and configure Qt Creator. Grab it from qtproject (http://qt-project.org/downloads)

To configure it, you will need to:

- set up the GCC compiler - use the linaro gcc
- set up the qmake binary - use the qmake binary from /usr/local/qt5cb2
- mount the SD card image you have, just the root partition
- set up the device, use cubie's ssh credentials

And that's it. Create an empty project, Qt Creator will generate a blank view with "Hello World" written on it, and build/deploy it to Cubie. If needed, check path permissions on Cubie to make sure that Qt Creator can deploy the files over ssh, and you're done!

Videos below show QuitCoding' Cinematic Experience running on mali libraries (framebuffer version) - pretty decent FPS!

http://www.youtube.com/watch?v=me5mHAKS1MA
http://www.youtube.com/watch?v=qedtjOUPDAw

Sunday 23 February 2014

Jolla TOH SDK - creating ambiences for your Jolla

Jolla recently released the TOH SDK, or The Other Half SDK, allowing anyone with the creativity and means to hack the back cover on the mobile device - and some people have already come up with some nifty solutions.

In the meantime and on a different angle, the SDK also includes a template ambiance, a theme, to be activated by the cover over NFC, upon contact.

Hoping to build the template and have it "just work", I fired up the SailfishOS SDK IDE - Qt Creator - and opened the project. Building the RPM resulted in some curious error messages.

Talking to some of the people on the #SailfishOS channel on freenode didn't get me that far in terms of loading the template, but eventually I got it and here's how to do it:

- Install the SailfishOS SDK
- Update the SDK (SailfishOS option on the left)
- Update the IDE (update notifications on the bottom right of Qt Creator's main window)
- Import the template project
- Modify the included template.spec file
- Create a missing "translations" directory inside the defined shadow build dir for the project
- Release > Deploy as RPM Package

At this point, Qt Creator complained about not being able to remotely execute the deployed binaries - to be expected, so I closed the popup message.

Moving onto the phone, ssh into it and checking the /usr/share/ambience directory didn't show the template files - but rebooting the phone made them show up, and the template ambience was then available in the Gallery app.

I removed the template ambience from the pulley menu but the /usr/share/ambience files still remained, so I manually removed those with devel-su

Redeploying the template ambience and rebooting the phone once again got me my template to be chosen from the Gallery.

I've placed the modified ambience template project on bitbucket, maybe it'll be useful to someone else as well.

Update:

There are two (unofficial) bitbucket repositories available with ambience template versions for Windows and Linux:


My First SailfishOS App

A few years back, when Android came out, I thought about developing a simple app that would let me control my home devices over SSH, without the hassle of actually login in and execute the commands manually.

I got an alpha version up and running but didn't have the time to maintain the project and eventually left it behind.

Just recently I've had the opportunity to mess around with a Jolla mobile device, which led me to the community behind it, and SailfishOS/Mer/Qt.

For the past year or so I had been dealing with Qt on embedded devices and seeing as SailfishOS is still under development, curiosity took the best of me and what better way to mess with it than my old project!

So oneSSHot took form once more, but this time I've followed through and it is now available at the Jolla Store.

The application itself uses the system's underlying ssh binaries to do the work, may have some bugs still which I'm clearing up as I go along, but overall it is pretty usable.

Instead of using direct user/password authentication over SSH, the app uses private/public key pair authentication.

I've made the source code available here:

https://bitbucket.org/wickwire/sailfishos-onesshot

... and some example commands to test it out:

echo 'SailfishOS: '`date +'%y-%m-%d %H:%M:%S'` > /tmp/onesshot.tmp
 
/home/wickwire/startFirefox.bash

(and on the remote host)

$ cat startFirefox.bash 
#!/bin/bash

export DISPLAY=:0
/usr/bin/firefox http://www.cnn.com