Instalación y configuración de Computadores y Periféricos
Escuela Técnica de Ingeniería Informática de Gijón
3º Ingeniería Técnica en Infomática de Sistemas

Desarrollo de Software para PDAs con Linux

Autor: Alberto García Hierro <skyhusker EN handhelds PUNTO org>

Fecha: 2 de mayo de 2005

Objetivos

El objetivo de este trabajo es explicar el proceso de desarrollo de software para un PDA usando Linux tanto en la estación de trabajo como en el propio PDA.

Introducción

Desarrollar software para un PDA es un proceso algo diferente a desarrollar aplicaciones para una estación de trabajo. Debido a que la potencia de estos dispositivos es bastante pequeña, normalmente no se compila en ellos. En su lugar, usaremos la estación de trabajo para llevar a cabo lo que se denomina compilación cruzada, que consiste en realizar una compilación para una arquitectura distinta a la máquina donde se lleva a cabo. Otra dificultad añadida es que vamos a usar Linux y el PDA viene de fábrica con Pocket PC, de manera que también será necesario instalar un nuevo sistema operativo en él.

Configuración de partida

Para llevar a cabo todo el proceso usaremos un PDA HP Ipaq H5550 y un iBook G4 corriendo Gentoo Linux con un kernel 2.6. El software que necesitamos en la estación de trabajo es el siguiente:

Desarrollo

Instalando Linux en el PDA

Comenzaremos eliminando el sistema operativo propietario que se encuentra instalado en el PDA, ya que la aplicación a desarrollar se ejecutará bajo Linux. Para ello lo primero que tenemos que hacer es sutituir el cargador del sistema operativo por otro que nos permita reprogramar la ROM. Se trata de BootBlaster y lo podemos obtener en la página web del proyecto Handhelds.org. Una vez descargado, simplemente lo ejecutamos y seleccionamos la opción "Program" . Al cabo de unos segundos la aplicación nos avisará de que ha termindo su trabajo, de manera que ya podemos resetear el dispositivo y continuar con la instalación.

Para el siguiente paso necesitamos haber descargado una imagen de Familiar, que puede obtenerse en http://familiar.handhelds.org. Una vez terminada la descarga, es el momento de conectarse al PDA a través del puerto de serie para subir la nueva imagen del S.O. y flashear la ROM con ella. La colocamos en su base, lanzamos minicom en la estación de trabajo y lo configuramos para que utilice el puerto de serie donde se conecta el dispositivo, poniendo la velocidad a 115200 y la paridad a None así como desactivando Flow Control, Hardware Handshaking y la cadena de inicialización. Una vez que la comunicación se haya establecido, veremos un prompt donde debemos ejecutar el comando load root. En ese momento, el cargador esperará por la imagen del sistema operativo. Pulsamos la secuencia Control+A, S, seleccionamos el protocolo ymodem y le indicamos el fichero de imagen que previamente hemos descargado. Debido a la baja velocidad del puerto de serie, el proceso de enviar la imagen al PDA llevará alrededor de 45 minutos. Una vez haya terminado, el cargador se encargará de reprogramar la ROM, instalando nuestro flamante sistema operativo libre. Para arrancar usaremos el comando boot y ya podremos ver un sistema Linux totalmente funcional.

Captura de OPIE

Preparando el entorno de compilación cruzada

Ahora que ya tenemos Linux instalado en el PDA, vamos a preparar el entorno de compilación cruzada. Usaremos este proceso porque es mucho más rápido y versátil que la compilación nativa en el PDA.

Para esta labor, usaremos OpenEmbedded. Consta de un núcleo, llamado bitbake y una serie de ficheros que indican a este núcleo como compilar el software. Comenzamos descargando el núcleo desde su repositorio subversion e instalándolo:

$ svn co svn://svn.berlios.de/bitbake/trunk/bitbake
$ cd bitbake
$ ./setup.py install --prefix=/usr/local --install-data=/usr/local/share

A continuación, descargamos los ficheros bb usando BitKeeper:

$ bk clone bk://openembedded.bkbits.net/openembedded

A continuación, creamos el directorio donde llevaremos a cabo la compilación (por ejemplo, build), y a su vez un subdirectorio dentro de este llamado conf, donde copiaremos el fichero openembedded/conf/local.conf. En él, solo tenemos que cambiar los valores de las siguientes variables:

BBFILES := "/home/fiam/src/oe/openembedded/packages/*/*.bb"
#Ojo, cambiar por la ruta apropiada
MACHINE = "h3900"
TARGET_OS = "linux"
DISTRO = "familiar"

Antes de comenzar a compilar, debemos de preparar el entorno para bitbake:

$ export BBPATH=$(pwd)/build:($pwd)/openembedded

Ahora ya podemos comenzar a construir nuestro entorno de compilación cruzada. Este proceso tardará unas cuantas horas, así que una vez llegados a este punto es recomendable tomarse un descanso ;).

$ cd build
$ bitbake qte libpcap openssl sqlite3 libpcap libetpan

Compilando OPIE

OPIE es el entorno gráfico que servirá de soporte a nuestra aplicación. Este entorno tiene la ventaja de basarse en la versión embebida de QT, y por lo tanto, no necesita de un servidor X sino que pinta directamente sobre el framebuffer. Para descargarlo usaremos cvs:

$ export CVSROOT=:pserver:anoncvs@cvs.handhelds.org:/home/cvs
$ cvs login
#Introducimos anoncvs como contraseña
$ cvs -z3 co opie

Preparar la compilación de OPIE es muy sencillo. Usa un sistema de construcción muy similar al del kernel. Vamos a configurarlo usando el interfaz ncurses:

$ cd opie
$ export OPIEDIR=$(pwd)
$ make menuconfig

En este menú debemos seleccionar al menos todas las librerías de OPIE y el gestor de ventanas. También se pueden seleccionar tantas aplicaciones como se desee, siempre que se satisfagan las dependencias. En cuanto a la única opción relevante para la compilación cruzada es la máquina de destino. Simplemente se debe escoger la opción OpenEmbedded e indicar el directorio donde lo hemos construido (en este caso, /home/fiam/src/oe/build/tmp. Una vez configurado, salimos del interfaz de configuración escogiendo guardar los cambios y ejecutamos make para que la compilación se lleve a cabo.

Compartiendo los ficheros por NFS

Ya tenemos todos los binarios necesarios construidos, pero tenemos que configurar nuestra estación de trabajo para que el PDA pueda acceder a ellos a través de la red. Vamos a utilizar NFS, ya que es el sistema más simple para realizar esta tarea. Suponiendo que el servidor NFS ya está instalado sólo necesitamos añadir una línea similar a esta en /etc/exports:

/home 192.168.5.2 (rw,no_root_squash)
#Ojo, no hacer esto sin saber los riesgos que puede conllevar.
#Básicamente, no debería utilizarse esta configuración a menos
#que la red donde resida la máquina sea totalmente confiable.

Es necesario reiniciar nfsd para que los cambios tengan efecto:

$ /etc/init.d/nfs restart
#En otras distribuciones probablemente será diferente.

Conectando el PDA en red

Para conectar el PDA en red, vamos a usar la conexión USB a través de la base. En el PDA no es necesario instalar nada, pero en la estación de trabajo necesitamos el módulo del kernel usbnet. Una vez que tengamos el módulo cargado y ambos dispositivos conectados a través de la base, en los dos aparecerá una nueva interfaz de red llamada usb0 en la estación de trabajo y usbf en el PDA. Con asignarles direcciones de la misma red ya tendremos la conexión lista.

#En la estación de trabajo
$ ifconfig usb0 192.168.5.1
#En el PDA
$ ifconfig usbf 192.168.5.2

Para poder acceder a los ficheros compartidos, es necesario montar el volumen NFS:

$ mount 192.168.5.1:/home /media/net

Ejecutando los nuevos binarios

El PDA ya cuenta con su propia instalación de OPIE, y será la que ejecute por defecto. Para que ejecute la que acabamos de compilar, es necesario indicarlo explícitamente a través de las variables de entorno PATH y LD_LIBRARY_PATH:

$ export STAGING=/media/net/fiam/src/oe/build/tmp/staging/arm-linux/
$ export OPIEDIR=/media/net/fiam/src/oe/opie
$ export PATH=${OPIEDIR}/bin:${STAGING}/bin:${PATH}
$ export LD_LIBRARY_PATH=${OPIEDIR}/lib:${STAGING}/lib:${LD_LIBRARY_PATH}

Para lanzar la nueva versión de OPIE es necesario reiniciarlo con el comando:

$ /etc/init.d/opie restart

Creando una aplicación de ejemplo

Ahora crearemos una original aplicación de ejemplo: un botón con el texto "¡Hola Mundo!". La forma más sencilla de compilarla es colocándola dentro del directorio de OPIE. Para este ejemplo, usaremos noncore/apps/hola:

$ mkdir noncore/apps/hola
$ cd noncore/apps/hola

Ahora abrimos nuestro editor favorito y creamos el fichero hola.cpp:

#include <qpe/qpeapplication.h>
#include <qpushbutton.h>
int main( int argc, char **argv )
{
QPEApplication app( argc, argv );
QPushButton hola( "¡Hola Mundo!", 0 );
hola.resize( 100, 30 );
app.setMainWidget( &hola );
hola.show();
return app.exec();
}

El siguiente paso es crear un fichero que indique como construir la aplicación, llamado hola.pro:

TEMPLATE = app
CONFIG += qt warn_on release
DESTDIR = $(OPIEDIR)/bin
HEADERS =
SOURCES = hola.cpp
TARGET = hola
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
LIBS += -lqpe
include ( $(OPIEDIR)/include.pro )

También es necesario un fichero que indique al menú de configuración las dependencias de la aplicación, así como si debe estar seleccionada por defecto. Este fichero debe llamarse obligatoriamente config.in.

config HOLA
boolean "opie-myhello (really cool application which says 'Hello' to the World)"
default "y"
depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE

El último paso para añadir es colocar una línea como esta en el fichero packages, situado en el directorio raíz de OPIE:

CONFIG_HOLA noncore/apps/hola hola.pro

El sistema de construcción genera varios ficheros de configuración y dependencias durante la construcción. Para que se tenga en cuenta la nueva aplicación debemos eliminar los existentes, de manera que en la próxima compilación se reconstruyan. Para ello ejecutamos el comando make clean-configs en el directorio de OPIE.

Una vez realizados todos los pasos, ejecutamos make y la nueva aplicación se construirá. Para ejecutarla simplemente habría que lanzarla usando su nombre, en este caso hola.

Desarrollando una aplicación real

Siguiendo los mismos pasos que para el ejemplo, sería posible desarrollar prácticamente cualquier aplicación. El único cambio necesario en cuanto al sistema de construcción, sería ajustar las dependencias acorde lo que necesite. Evidentemente, también habría que cambiar el código fuente ;).

A modo de ejemplo, aquí podemos ver una captura de una aplicación que he estado desarrollando en las últimas semanas:

Captura de OpieStumbler

Esta aplicación, llamada OpieStumbler, detecta redes inalámbricas de forma activa, basándose en las extensiones wireless del kernel. Su código fuente está disponible bajo la licencia GPL y se encuentra alojado en el CVS de OPIE, más concretamente en el directorio noncore/net/opiestumbler.

Referencias

Logotipo de Creative Commons Este trabajo utiliza una licencia Creative Commons.