C++ (Gtkmm) Development with Maemo 3.x for Nokia Internet Tablet

Last changed: Apr 2, 2007 - Updated for IT2006


Contents:


Below is a collection of notes I assembled along the way of porting some of my own C++ Gtkmm-based software to Nokia 770 Internet Tablet.

The official maemo Gtkmm port can be found in Maemo Garage repository. At the time of writing these notes, the *official* port is not mature enough to be seamlessly used by the developers.

Setting Up Development Environment

To install SDK, follow the latest official Maemo Tutorial.

Starting SDK

NOTE: If you are getting this error
 ERROR: Scratchbox dir '/scratchbox/users/YOU/scratchbox/tools/bin' is missing!  
			
then you surely forgot to do step 1, sbox_ctl start command.

Stopping SDK

Make sure you properly logout from SDK. If not, you might damage Scratchbox filesystem!

Switching Between Targets

You have two targets: SDK_PC and SDK_ARMEL. The typical cycle of development is to polish your app under SDK_PC target and then switch to SDK_ARMEL and build the final Debian ARMEL package for it.

Starting with Scratchbox 1.0.x, use % sb-menu to switch between targets.

Remember to log out from all other open terminals.

Installing hildonmm C++ Wrapper

First, setup you environment variables in ~/.bash_profile as follows:


 export PATH=$PATH:. 

 export LANGUAGE=en_GB 
 export LC_ALL=en_GB   
 export PAGER=less     
 export DISPLAY=:2     
		  

The easiest way to install C++ development environment is to pull the prebuilt packages from maemo repository:


% fakeroot apt-get install hildon-fmmm-dev hildon-libsmm-dev
		  

For more information, refer to Programming with maemomm Guide and Maemomm C++ API Reference. Pay particular attention to Changes to gtkmm. If your goal is to port an existing Gtkmm application to Nokia platform, you would need to take into consideration limitations outlined in this chapter.

Building a Debian Package

If a software package you plan to build has already been debianized, then the build process is very trivial:

To build debian package change to package directory and:
 
% dpkg-buildpackage -rfakeroot -tc -uc -us -sa -D 

			

Use fakeroot in place of 'sudo'. Do not try to use root user, it is unnecessary in Scratchbox, fakeroot does the same thing and conveniently without need for typing root password.

To install debian package inside Scratchbox, use dpkg -i.


 
% fakeroot dpkg -i package-name-version.deb

		  

NOTE: Remember, that if the package installed package.sercive file to /usr/share/applications/dbus-1/services/, you whould need to restart the GUI:

% af-sb-init.sh restart

			

For more in-depth information about Debian packaging systems for novice people like myself, you can refer to my Debian Packagings notes.

Summary Of GTK++ Wrappers Interface

Hildon::Window

Hildon::Window represents a top-level window of an application running in the Hildon framework. It provides facilities to manage window menus and toolbars. Each Hildon::Window can have its own menu and toolbars. The application can also have a common menu and toolbar, which are shared among all application windows.

class Hildon::Window : public Gtk::Window
{
   Window ()
   virtual ~Window ()

   void add_toolbar (Gtk::Toolbar& toolbar)
   void remove_toolbar (Gtk::Toolbar& toolbar)

   void add_with_scrollbar (Gtk::Widget& child)
   bool get_is_topmost () const

   const Gtk::Menu* get_menu () const
   Gtk::Menu*       get_menu ()

   void set_menu (Gtk::Menu& menu)

   const HildonWindow* gobj () const
   HildonWindow*       gobj ()

  // Bunch of signals follow ...
}
		  

Hildon::Program

A Hildon::Program is the base of any Hildon application.

It represents an application running in the Hildon framework. The Hildon::Program tracks the top-most status of an application and informs the task navigator when the application can be hibernated.

It also provides tools to get and set menus and toolbars which are common for all application windows.

The Hildon::Program object is created by calling the static get_instance() method, which takes no parameters and returns a new Hildon::Program.


class Hildon::Program : public Glib::Object
{
    virtual ~Program ();

    bool get_is_topmost () const;

    // Registers a HildonWindow as belonging to a given HildonProgram .
    //
    void add_window (Window& window);
    void remove_window (Window& window);

    bool get_can_hibernate () const;
    void set_can_hibernate (bool can_hibernate=true);

    void set_common_menu (Gtk::Menu& menu);
    const Gtk::Menu* get_common_menu () const;
    Gtk::Menu*       get_common_menu ();

    void set_common_toolbar (Gtk::Toolbar& toolbar);
    const Gtk::Toolbar* get_common_toolbar () const;
    Gtk::Toolbar* get_common_toolbar ();

    const HildonProgram* gobj () const;
    HildonProgram*       gobj ();
    HildonProgram*       gobj_copy ();
};

		  

Nokia Internet Tablet Filesystem

IT2006 release of software brings sanity back to the Debian packaging for maemo! Here is the file structure of an application successfully installed on 770:

/
|-home/
|    +-usr/
|        +-MyDocs/
|              +-.images/
|              +-.sounds/
|              +-.videos/
|              |      +-IceAge2.avi
|              +-.documents/
|                     +-.games/
|
+-etc/
|   +-gconf/
|   +-others-menu/
|       +-extra_applications/   
|          +-00102granule.desktop  o
|                                  |
+-usr/                             |
    +-bin/                         | 
    |   +-granule*                 | { softlink made by
    |                              |   debian/package.links }
    |                              |
    +-share/                       |
        |                          |
        +-applications/            |
        |   +-hildon/              |
        |       +-granule.desktop <+
        |
        +-dbus-1/                 
        |   +-services/           
        |       +-com.nokia.granule.service
        |
        +-icons/                  
        |     +-hicolor/          
        |            +-26x26/  
        |                +-hildon/   
        |            +-40x40/     
        |                +-hildon/   
        |            +-scalable/     
        |                +-hildon/   
        +-pixmaps/
            +-granule.png
		  

 

To Flash New Image

Mucking with D-Bug configuration files is a sure thing of locking up the device. To restore or to upgrade, follow official instructions:

  1. First, power the unit down. The start the flasher as root on your Linux box:

    # ./flasher-3.0 -F RX-34_2007SE_3.2007.10-7_PR_COMBINED_MR0_ARM.bin -f -R
    
    flasher v0.8.7 (Oct 17 2006)
    
    SW version in image: RX-34_2007SE_3.2007.10-7_PR_MR0
    Image 'kernel', size 1311104 bytes
            Version 2.6.18-200710osso2
      ...
    Suitable USB device not found, waiting
      ...
    USB device found found at bus 002, device address 008
    Found device RX-34, hardware revision 1301
    NOLO version 1.1.6
    Image 'secondary', size 95872 bytes
            Valid for RX-34: 1301, 1302
            Version 1.1.5-3
    
    Suitable USB device not found, waiting
    
    USB device found found at bus 002, device address 008
    Found device RX-34, hardware revision 1301
    NOLO version 1.1.6
    Version of 'sw-release': RX-34_2007SE_3.2007.10-7_PR_MR0
         ...
    Sending and flashing rootfs image (81920 kB)...
    100% (81920 of 81920 kB, avg. 5631 kB/s)
    
    Finishing flashing... done
    				
  2. Plug in the USB cable.
  3. Hold down 'Home' button and press Power button.
  4. Wait for flasher to begin downloading and release 'Home' button.
  5. Wait for reboot to complete
  6. Copy maemo-profile and maemo-gainroot from MMC card to your home directory and move the files:

    $ cp /media/mmc1/maemo-* .
    $ cp /media/mmc1/usb* .
    $ cp /media/mmc1/granule-* .
    $ cp maemo-profile ~/.profile
    $ cp granule-gstreamer.conf ~/.granule
    				  

Useful Applications

Between each endless reboot of N800 I reinstall the same set of basic applications:

Useful Applications
osso-xterm XTerm
openssh SSH server/client to get remote access
camera Nokia camera application
fbreader eBook reader
maemopadplus Tree-based note/sketch application
fmradio FM radio
gstreamer-tools Comman-line tools to play .mp3 files via DSP

Drop me a note and tell me about your favorites.

To Gain Root Access

To enable root access

  1. Switch off the device
  2. Enable R&D mode:
    
    # ./flasher-3.0 --enable-rd-mode -R 
    				
  3. Switch on the device. Pay attention to the boot sequence - remember to hold down 'Home' key. It is now in R&D mode, allowing for $ sudo /usr/sbin/gainroot.
  4. You can give all users sudo priveleges with:

    $ sudo /usr/sbin/gainroot
    
    Root shell enabled
    BusyBox v1.1.3 (Debian 3:1.1.3-3.osso17) Built-in shell
    
    /home/user # cp maemo-gainroot /usr/sbin/gainroot
    
    OR
    /home/user # cp -p /etc/sudoers /etc/sudoers~ && echo user ALL = NOPASSWD: ALL >> /etc/sudoers
    				
  5. When done, disable R&D mode with flasher:
    # ./flasher-3.0 --disable-rd-mode -R  
    
    Suitable USB device not found, waiting
    
        plug in the USB cable and press 'Home' + 'Power' button
    
    USB device found found at bus 002, device address 010
    Found device RX-34, hardware revision 1301
    NOLO version 1.1.6
    Version of 'sw-release': RX-34_2007SE_3.2007.10-7_PR_MR0
    The device is now in production mode
    				

Refere to HowToBecomeRoot for further information.

COMMENT: If the USB cable is connected when the device is powered up, there is approx. two-second timeout in waiting for flashing commands. If no flashing commands arrive during the time period, nokia start the booting process. If the home button is pressed while powering on, the timeout is removed. Looks like the problem is indeed because of the timeout. The timeout can also be removed by setting the "no-usb-timeout" R&D flag.

Connecting via USB/TCP

When you plug in the USB cable with the default configuration g_file_storage module is loaded into the kernel to give your desktop an access to your SD card in N800 as mass storage.


$ /sbin/lsmod | grep g_file_storage

g_file_storage 24456 0 - Live 0xbf04f000
			

To enable USB network, you have remove g_file_storage module and to load g_ether module instead. I use usbnet script written by Micael Mlivoncic:

$ sudo gainroot

Root shell enabled
BusyBox v1.1.3 (Debian 3:1.1.3-3.osso17) Built-in shell

/home/user # cp usbnet /etc/init.d/usbnet
/home/user # cp usb0 /etc/network/interfaces
			

The usbnet script will unmound SD cards and load the network module. The usb0 configuration file defines the local network settings over usb0 interface.

On your desktop, first check that your kernel has support (either built-in or via module) for usbnet:

[vlg@dollar]> grep "USB_USBNET" /boot/config-`uname -r`

CONFIG_USB_USBNET_MII=m
CONFIG_USB_USBNET=m
			

Add usb0 hotplug action to your /etc/sysconfig/network-scripts/net.hotplug script:

#!/bin/sh

. /etc/sysconfig/network-scripts/network-functions
if [ "$INTERFACE" = "" ]; then
    exit 1
fi

case $ACTION in
add|register)
    ...
    case $INTERFACE in
        # interfaces that are registered after being "up" (?)
        ppp*|ippp*|isdn*|plip*|lo*|irda*|dummy*|ipsec*|tun*|tap*)
            exit 0
            ;;
        usb0)
            ifconfig usb0 192.168.2.14 netmask 255.255.255.0
            route add 192.168.2.15 usb0
            iptables -I INPUT 1 -s 192.168.2.15 -j ACCEPT
            ;;
        # interfaces that are registered then brought up
        *)
         ...

			

Start USB Networking on your N800:

$ sudo gainroot

# /etc/init.d/usbnet start

entering Ethernet via USB mode (g_ether) ...
waiting, then starting up the usb0...
			

Plug in the USB cable and you should have the network setup. Check the status from your desktop with:

$ /sbin/ifconfig -a

usb0      Link encap:Ethernet  HWaddr 8A:CF:16:AB:C0:3A  
          inet addr:192.168.2.14  Bcast:192.168.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
			

Your desktop machine has 192.168.2.14 address, and your N800 has 192.168.2.15 address.

Install openssh package (or dropbear

$ sudo gainroot

Root shell enabled
BusyBox v1.1.3 (Debian 3:1.1.3-3.osso17) Built-in shell

/home/user # apt-get update
/home/user # apt-get install ssh
			

Assign passwords for 'root' and 'user' accounts:

/home/user # passwd
New password: MY-SECRET
Re-enter new password: MY-SECRET

/home/user # passwd user
New password: MY-SECRET
Re-enter new password: MY-SECRET
			

To login from your desktop, install either openssh or dropbear packages and then:


[vlg@dollar]> ssh user@192.168.2.15

BusyBox v1.1.3 (Debian 3:1.1.3-3.osso17) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

~ $ 
			

Small Hints & Tricks

To navigate the entire filesystem from a built-in FileManager, open XTerm with Extras->X Terminal and make appropriate symbolic links:

$ cd ~/MyDocs
$ ln -s / Root
$ ln -s /var/lib/install Install

		  

Be warned, that making the softlinks into the root filesystem will most likely trigger metalayer-crawl application to sap you battery dry. For more details, see Bug 978.

If you Debian packaging system got hosed and you find yourself no longer able to remove an installed package, you must have somehow managed to corrupt your /var/lib/dpkg/status file:. Login as root and try this:

# cd /var/lib/dpkg/
# mv status status.broken
# cp status-old status
		  

Upload Packages To Maemo Extras Repository

So, you want to share your stuff with the others - good for you! The official instructions can be found at https://maemo.org/maemowiki/ExtrasRepository. Needless to say, you need to register with Garage first.

The instructions are biased towards Debian-based developers. If, however, your development host is Fedora Core or anything of that nature, then the process of signing up the packages and submitting them to the Extras repository quickly becomes rather murky.

So, here is how I was able to do it:

  1. Login to your scratchbox SDK and install devscripts package that includes debsign utility. Make sure you scratchbox's /etc/resolv.conf matches the one of your host computer.

    
    scratchbox> fakeroot apt-get devscripts
    scratchbox> logout
    
    			  
  2. Although debsign script is installed in your scratchbox SDK, you can use it as a regular user as well. Adjust your PATH environment variable, so that shell can find debsign

    
    $ export PATH=$PATH:/scratchbox/devkits/debian/bin
    			  
  3. To sign the packages, you would need your GPG public/private keys established. The detailed instructions can be found at http://fedoraproject.org/wiki/DocsProject/UsingGpg/CreatingKeys. At any time, to lookup your public key, ask the GPG server:

    
    $ gpg --fingerprint 3rdshift@comcast.net
    
    pub   1024D/95FC1731 2006-10-21
          Key fingerprint = 1230 2F87 99BC 6A94 0D28  7C4A F07A 4026 95FC 1731
    uid                  Vladislav Grinchenko
    sub   1024g/17C5E02C 2006-10-21
    
    			  

    Mine happens to be 95FC1731.

  4. Time to sign the package. Change to the folder where the Debian packages were built, and sign with debsign:

    
    $ cd /scratchbox/users/vlg/home/vlg/libASSA
    $ ls 
    
    libassa-3.4.2/               libassa_3.4.2.tar.gz
    libassa_3.4.2_armel.changes  libassa-bin_3.4.2_armel.deb
    libassa_3.4.2_armel.deb      libassa-dev_3.4.2_armel.deb
    libassa_3.4.2.dsc            libassa-doc_3.4.2_all.deb
    
    			  

    You are going to sign .changes file and then upload it along with .dsc, .tar.gz, .deb packages.

    
    $ debsign -k95FC1731 libassa_3.4.2_armel.changes
    
      ...
    
    Successfully signed dsc and changes files
    			  
  5. Although, the official instruction calls for using Debian's dput utility to upload the packages, all my attempts to do so failed. It is a Python script you can pull off the web and install locally, but it refused to work properly on Fedora Core 5.

    Use scp instead:

    
    $ scp *.changes *.dsc *.tar.gz *.deb vlg@garage.maemo.org:/var/www/extras/incoming/mistral/
    
    Enter passphrase for key '/home/vlg/.ssh/id_rsa':
    
    libassa_3.4.2_armel.changes        100% 1570     1.5KB/s   00:00
    libassa_3.4.2.dsc               ...
       ...
    			  

    All done! If all went well, your package will appear shortly in the repository ready for distribution.

  6. To download the package to your Nokia 770, launch Tools->Application manager, then from the menu, select Tools->Application catalog .... If not already defined, create a new Catalog entry:

    Edit Catalog
    Web address: http://repository.maemo.org/extras
    Distribution: mistral
    Components: free non-free
    Enabled: yes

    Refresh Application Manager with Tools->Refresh pacakge list and you should see your package listed among applications available for installation.

  7. To refer to your package in HTML page, specify its .install URL like this:

    
    <a href="http://repository.maemo.org/extras/dists/mistral/install/libassa.install">libassa<a>
    			  

    Clicking on it in nokia 770 browser will launch the Application Manager and install the package.

  8. To have the same packages installed in your scratchbox SDK, add repository list to //etc/apt/sources.list file, and then apt-get the package.

    # mistral extras Maemo 2.0
    #
    deb http://repository.maemo.org/extras/ mistral free
    deb-src http://repository.maemo.org/extras/ mistral free
    
    # scirocco extras Maemo 2.1
    #
    deb http://repository.maemo.org/extras/ scirocco free
    deb-src http://repository.maemo.org/extras/ scirocco free
    
    # bora extras Maemo 3.0
    #
    deb http://repository.maemo.org/extras/ bora free
    deb-src http://repository.maemo.org/extras/ bora free
    
    			  
Web Resources

Nokia 770 related blogs


Copyright(C) 2006-2007
Vladislav Grinchenko