Linux Palm Programmierung

Palm Pilots sind der de-facto Standard, wenn Daten mobil erfasst und verarbeitet werden sollen. Trotz des unüberschaubaren Angebots an Palm Pilot Software wird man in vielen Fällen keine vorgefertigten Lösungen für eine konkretes Problem finden, sondern sie selbst entwickeln müssen. Hierfür stehen verschiedene Programmiersprachen zur Verfügung, von denen die gängigste C ist. Neben dem kommerziellen CodeWarrior-Compiler, der in den Versionen für Windows und den Macintosh Palm Programme erzeugen kann, können auch die Tools um den GNU-Compiler GCC zur Erstellung von Palm Pilot Programmen verwendet werden.

Vor allem in Unternehmen, die ihre Datenbestände auf Unix-Servern vorrätig halten, hat die Entwicklung mit dem GCC unter Unix eine Reihe von Vorteilen. So kann die Client-Applikation für den Palm Pilot auf der gleichen Plattform entwickelt werden, auf der der Server läuft. Unix Programmierer müssen nicht eine neue Entwicklungsumgebung lernen, sondern können die ihnen bekannten, bewährten Tools verwenden, die ein Unix-System mitbringt. Gerade für die Entwicklung von Netzwerk-Applikationen macht es der Palm Pilot Unix-Entwicklern einfach. Die Netzwerk-API des Palm Pilot implementiert die von Unix bekannte Berkeley-Socket-API. Dadurch kann Netzwerk-Code, der unter Unix entwickelt und debugged wurde, mit nur geringfügigen Änderungen auf den Palm Pilot übertragen werden.

Im folgenden werden anhand einer kleinen Beispiel-Applikation die Tools vorgestellt, mit denen unter Linux/Unix Applikationen für den Palm Pilot entwickelt werden können.

Tools

Bevor man mit der Entwicklung von Palm Pilot Applikationen anfangen kann, muß der Palm Pilot mit dem Rechner verbunden werden. Physikalisch ist das - zumindest wenn man eine Cradle mit serieller Schnittstelle hat - schnell erledigt. Die Kommunikation mit dem Palm Pilot übernimmt das Paket PILOT-LINK. PILOT-LINK ist eine Sammlung von Kommandozeilentools für den Datenaustausch zwischen Palm Pilot und Unix-Rechner. Für unsere Zwecke braucht man nur das Herzstück des PILOT-LINK Pakets, das Programm PILOT-XFER, mit dem kommandozeilengesteuert Dateien zwischen Desktop-Rechner und Palm ausgetauscht werden können.

Wer bereits unter Linux entwickelt hat, muß sich bezüglich der Tools nicht umgewöhnen. Eine der großen Stärken des von Linux standardmäßig verwendete GCC Compiler ist, daß er Code für fast jeden verfügbaren Mikroprozessor erzeugen kann. Er unterstützt auch den Motorola Dragonball, der im Palm Pilot Dienst tut. Die zentralen Entwicklungstools GCC, BINUTILS und GDB braucht man in Versionen, die Maschinencode für den Palm Pilot erzeugen bzw. verarbeiten. Man nennt diese Art von Compilern "Crosscompiler", da sie auf der einen Plattform (Linux) laufen, aber Code für eine andere Plattform (Palm Pilot) erzeugen. Hierfür werden die Source-Pakete von GCC, BINUTILS und GDB benötigt, sowie das Paket PRC-TOOLS, das die nötigen Patches und einige Zusatzprogramme enthält. (Alle URLs zu den im Artikel genannten Programmen sind am Ende des Artikels aufgeführt) Unter Linux und anderen gängigen Unix-Systemen ist die Neukompilierung dieser Programme eine relativ schmerzlose Angelegenheit.

Wer mit einer der großen Linux-Distributionen arbeitet, hat es noch einfacher: Für sie gibt es fertig geschnürte PRC-TOOLS Binär-Pakete mit fast allem, was zur Palm-Entwicklung benötigt wird. SuSE liegen die RPMs sogar unter dem Namen "pilotsdk" der Distribution bei. RedHat hat auf der Powertools-CD ein Paket "prc-tools".

Zusätzlich benötigt man das direkt von Palm zur Verfügung gestellte "Software Development Kit" (SDK). Das SDK enthält die Header-Dateien und Libraries, die benötigt werden, um auf die Funktionen des PalmOS-Betriebssystems zuzugreifen. Die Installation des SDK erfordert etwas Handarbeit. Die aktuelle Version 3.5 wird im Verzeichnis /usr/local/palmdev entpackt. Nach dem entpacken müssen symbolische Links von "/usr/local/palmdev/Palm OS 3.5 Support/Incs" auf "/usr/local/palmdev/include" und von "/usr/local/palmdev/Palm OS 3.5 Support/GCC Libraries" nach "/usr/local/palmdev/lib" gesetzt werden. Im SuSE pilotsdk-Paket ist das SDK bereits vorhanden.

Zu beachten ist, dass es erhebliche Unterschied zwischen dem SDK 3.5 und seinen Vorgängern gibt! Programme, die mit einem früheren SDK entwickelt wurden, lassen sich in der Regel nicht direkt unter SDK 3.5 kompilieren, da sich u.a. die Bezeichnungen für die Datentypen geändert haben. In unserem Beispiel benutzen wir das älteren SDKs 3.1. Um das Beispielprogramm zu kompilieren, braucht man neben dem SDK 3.5, das die Libraries liefert, deshalb zusätzlich die Header-Dateien der älteren SDKs. Sie findet man im Paket palmos-1-2-3.1-sdks-1.tar.gz, das man - ebenso wie das SDK 3.5 - auf der Webseite von Palm Inc. findet. Hier ist das Verzeichnis sdk-3.1/include/ anstelle von "Palm OS 3.5 Support/Incs" nach /usr/local/palmdev/include zu linken.

Außerdem wird das Paket PILRC benötigt, das die Ressourcen-Dateien zu einem vom Palm ausführbaren prc-File zusammensetzt. Auf die Bedeutung der Ressource-Dateien wird im nächsten Abschnitt eingegangen.

Programmierung

Die Programmierung des Palm Pilots ist für jemanden, der die Programmierung von "großen" Systemen gewohnt ist, zunächst ungewohnt. Oberstes Primat bei der Programmierung für den Palm Pilot ist, mit den spärlichen Ressourcen, vor allem dem begrenzten Speicher, sparsam umzugehen. Die Trennung in Hauptspeicher und Festplatte, wie man sie von ausgewachsenen Computern kennen, gibt es beim Palm Pilot in der Form nicht. Einem Programm steht nur äußerst wenig Heap-Speicher zur Verfügung. Alle größeren Datenobjekte befinden sich in einer Datenbank. Um zum Beispiel ein Array zu manipulieren, wird über einen Betriebssystemaufruf der entsprechende Datenbankeintrag für Zugriffe von anderen Programmen gesperrt und ein Pointer an das Programm geliefert, über das dieses das Array dann manipulieren kann. Wenn das Programm das Array bearbeitet hat, gibt es den entsprechenden Datenbankeintrag wieder frei. Die Programmierung für den Palm Pilot unterscheidet sich hier von der für Windows CE, das der klassischen Trennung in Haupt- und Festplattenspeicher folgt. Unter CE wird der zur Verfügung stehende Speicher in einen "Hautspeicher-"Teil und einen "Festplatten"-Teil unterteilt. Programme und Daten müssen zwischen diesen beiden Teilen hin und her kopiert werden. Dies erklärt zu einem Teil den größeren Ressourcen-Bedarf von Windows CE.

Das Beispielprogramm

Die Beispielapplikation implementiert ein klassisches Programm auf dem Palm Pilot: Nach dem Start zeigt es einen Bildschirm ("Form") mit dem Wort "Hello..." und einem Button. Wenn der Benutzer auf den Button drückt, erscheint ein Fenster mit dem Wort "...world!"

Zunächst wird eine Ressourcen-Datei angelegt, die die Elemente des Userinterface definiert. Die Ressource-Datenbank enthält Einträge für zwei Elemente. Das erste Element ist der Bildschirm mit dem Wort "Hello..." und einem Button, das zweite Element das Fenster mit dem Wort "...world". Als Bezeichner für die User Interface Element werden symbolische Namen wie "idMainForm" verwendet. In der zugehörigen Header-Datei "le.h", die in der ersten Zeile der Ressourcen-Datei eingebunden wird, werden diese symbolische Namen auf Nummern abgebildet.

Datei le.rcp:

#include "le.h"

FORM ID idMainForm AT (2 2 156 156)
  USABLE
  MODAL
  BEGIN
    TITLE "LE Demo Application"
    LABEL "Hello..." idLabelHello AT (33 50)
    BUTTON "Push me!" ID idPushButtonPushMe AT (5 140 AUTO AUTO)
  END

ALERT ID idAlertWorld
  INFORMATION
  BEGIN
    TITLE ""
    MESSAGE "...World!"
    BUTTONS "OK"
  END

In der Header Datei le.h werden den symbolischen Namen wie idMainForm Nummern zugewiesen:

Datei le.h:

 #define idMainForm         0
#define idLabelHello       1
#define idPushButtonPushMe 2
#define idAlertWorld       3

Die Definitionen sind in eine Header-Datei ausgelagert, weil wir sie auch in dem C-Programm verwenden werden. Dieses Programm schauen wir uns jetzt an, wobei wir bei der PilotMain()-Funktion anfangen:

Datei le.c:

#include 
#include "le.h"

Boolean MainFormHandleEvent(EventType *event){

  Boolean handled;

  handled=false;
  switch (event->eType) { 
  case frmOpenEvent:
    FrmDrawForm(FrmGetActiveForm());
    handled = true;
    break;
  case ctlSelectEvent:
    FrmAlert(idAlertWorld);
    break;
  }

  return handled;
}

Boolean ApplicationHandleEvent(EventType *event){

  Boolean handled;
  FormPtr frm;
  Word formId;
  
  handled=false;
  if(event->eType == frmLoadEvent) { 
    formId = event->data.frmLoad.formID;
    frm = FrmInitForm(formId);
    FrmSetActiveForm(frm);
    FrmSetEventHandler(frm, MainFormHandleEvent); 
    handled = true;
  }
  
 return handled;
}


void EventLoop(void){

  Word error;
  EventType event;
  
  do{
    EvtGetEvent(&event, evtWaitForever);
    if(!SysHandleEvent(&event))
	if(!ApplicationHandleEvent(&event))
	  FrmDispatchEvent(&event);
  }while(event.eType != appStopEvent);
}


DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags){

  if(cmd == sysAppLaunchCmdNormalLaunch){
    FrmGotoForm(idMainForm);
    EventLoop();
  }
  return 0;
}

Ein Palm Pilot Programm kann auf verschiedene Arten gestartet werden: Zum Beispiel manuell vom Benutzer, automatisch von der Weck-Funktion oder auch im Rahmen eines Hotsyncs. Je nachdem, wie das Programm gestartet wird, muß es sich unterschiedlich verhalten. Hat der Benutzer es gestartet, wird es seinen Start-Bildschirm aufbauen. Wenn es jedoch im Rahmen eines Hotsyncs gestartet wurde, wird es keinen Bildschirm aufbauen, sondern nur seine Daten mit der externen Applikation synchronisieren. Auf welche Art das Programm gestartet wurde, erfährt es über den "Launch Code". In PilotMain() wertet das Programm deshalb den "Launch Code" aus und starte nur, wenn es normal vom Benutzer aufgerufen wurde.

Palm Pilot Programme sind Event-gesteuert. Wenn immer etwas passiert, worauf das Programm reagieren sollte, zum Beispiel, wenn der Benutzer eine Eingabe macht, wird diese Information in Form eines "Events" vom Betriebssystem an das Programm übergeben. Das Palm Pilot Programm durchläuft eine "Event Loop", in der die einkommenden Events ausgewertet und bearbeitet werden, bis das Programm via "Close Event" aufgefordert wird, sich zu beenden. Als erstes holt unsere Event Loop den nächsten Event (EvtGetEvent()). Dann gibt es dem Betriebssystem (SysHandleEvent()) die Möglichkeit, diesen Event zu bearbeiten. Wenn sich der Event-Handler des Betriebssystems für nicht zuständig erklärt, wird der Event an die ApplicationHandleEvent()-Funktion unseres Programms übergeben. Ist auch das nicht zuständig, wandert es an den Event Handler des aktuellen Forms (FrmDispatchEvent()).

ApplicationHandleEvent() sorgt nur dafür, die richtige Bildschirmsicht ("Form") angezeigt wird. In unserem Beispiel haben wir nur ein Form. Das Form idMainForm, das einen leeren Bildschirm mit dem Wort "Hello" und einem Button zeigt. Nachdem ApplicationHandleEvent() dieses Form geladen hat, weist es ihm als Event-Handler die Funktion MainFormHandleEvent() zu. Das führt dazu, das bei Aufrufen von FrmDispatchEvent() in der EventLoop() die Funktion MainFormHandleEven()t aufgerufen wird.

MainFormHandleEvent() sorgt dafür, dass das Hauptfenster angezeigt wird (FrmDrawForm()). Ansonsten reagiert es nur, wenn der Button gedrückt wird (ctlSelectEvent). In diesem Fall zeigt es das Fenster mit dem User Interface Element idAlertWorld (FrmAlert()).

Nachdemnun alle Programmdateien beisammen sind, können wir unser kleines Palm-Programm übersetzen. Hier verwenden wir folgendes minimalistische Makefile:

Datei Makefile:

all:
	m68k-palmos-gcc le.c -o le
	m68k-palmos-obj-res le
	pilrc le.rcp
	build-prc le.prc "LE" LE1 *.grc *.bin
clean:
	rm le le.prc *.bin *.grc

Nachdem mit "make all" die Datei le.prc erzeugt wurde, kann sie mit dem Kommando "pilot-xfer -i le.prc" auf den Palm Pilot übertragen werden.

Debugging

Wenn man für Handheld-Devices wie den Palm Pilot programmiert, möchte man möglichst wenig direkt auf dem Gerät entwickeln, da es immer umständlich ist, direkt auf dem Gerät zu debuggen. Abhilfe schaffen hier Emulatoren, die es auch für Linux gibt. Der veralterte Emulator XCOPILOT hat in POSE einen würdigen Nachfolger gefunden. Die Screenshots in diesem Artikel wurden mit POSE erzeugt. Für das Debugging steht unter Linux der bewährte GDB zur Verfügung. Mit ihm können sowohl Programme debugged werden, die im Emulator ausgeführt werden, als auch Programme, die direkt auf einem über serielle Schnittstelle angeschlossenem Palm Pilot laufen.

Alternativen

Für diejenigen, die nicht in C-Programmieren wollen, stehen andere Sprachumgebungen zur Verfügung. Eine Reihe von Projekten versucht, Java auf den Palm Pilot zu bringen. Das Tool "Jump" setzt Java-Programme in Palm Pilot Binaries um. An Java Virtual Machines arbeiten die Projekte "Ghost Machine", KVM und Waba. Leider ist die Entwicklungsarbeit an KVM und "Ghost Machine" eingestellt worden. Außerdem bietet IBM Linux-Versionen seiner integrierte Entwicklungsumgebung VisualAge Micro Edition zum kostenlosen Download an, mit der Java Programme für den Palm Pilot entwickelt werden können.

Literatur

Wer nun neugierig geworden ist, findet im Netz und im Fachbuchhandel weitere Informationen zur Palm Pilot Programmierung. Den Einstieg in die Palm Pilot Programmierung findet man am besten mit dem bei O'Reilly erschienen Buch "Palm Pilot Programming Guide". Dieses Buch ist auch komplett im WWW abrufbar. Auch die Informationspolitik von Palm Hersteller 3Com kommt Linux-Benutzern entgegen - nicht nur das SDK ist kostenlos, der Hersteller geht auch sehr offen mit Informationen über die Programmierung des Systems um. (Wenn das Betriebssystem selbst auch leider weiterhin nicht komplett Open Source ist.) Weitere Einstiegsliteratur findet man daher beim Palm-Hersteller 3Com selbst an. Man sollte sich nicht davon abschrecken lassen, wenn Titel nur zum Download für Windows oder Macintosh angeboten werden. Zwar wird hier als Compiler der kommerzielle CodeWarrior vorausgesetzt, mit GCC kann man den Beispielen jedoch ebenso gut folgen. Als beliebte Übung für Unix-Programmierer müssen natürlich auch für die Entwicklung von Palm Applikationen Makefiles erstellt werden. Hier bietet es sich an, die im Internet vorfügbaren Beispiel-Applikationen entsprechend den eigenen Bedürfnissen anzupassen. SuSE Linux liegt ein Tutorial in Form des RPM-Pakets "psdktutr" bei.

Weiterhin gibt eine englischsprachige Mailinglist für Palm Pilot Programmierung unter Unix.

Links

Kasten: 100% Linux

Die Bedeutung von Linux wächst auch als Betriebssystem für Embedded Applications. Was liegt näher, als die Palm Pilot Hardware mit Linux als Betriebssystem für solche Applikationen zu nutzen? Möglich macht das das uCLinux (sprich "you see Linux") Projekt, das Linux für die gängigsten Mikroprozessoren der Kleinstrechnern portiert hat. Unterstützt wird auch der der Motorola Dragonball Prozessor des Palm Pilot. Mit uCLinux läuft fast die gewohnte Linux Umgebung auch auf dem Palm Pilot. Einen Schritt weiter getrieben haben das Projekt die Entwickler der koreanischen Firma OSK. Ihr System Windstone bietet innerhalb von uCLinux eine "Palm Box", in der das gewohnte PalmOS mit seinen Applikationen als Prozess in uCLinux läuft.

Die Installation von uCLinux auf dem Palm Pilot ist jedoch eher etwas für mutige Naturen. Um uCLinux auf dem Palm Pilot zu installieren, müssen die ROMs des Palms physisch ausgetauscht werden. Nur der Palm-Clone TRGPro kann auf Linux umgerüstet werden, ohne ihm umzubauen. Man braucht hierfür jedoch die spezielle Speichererweiterungskarte "TRG SuperPilot Memory Board".

Hoffnungen, ein weiteres Closed Source Betriebssystem aus seinem Leben verbannen zu können, muss ein weiterer Dämpfer erteilt werden. Zwar bietet OSK eine API, mit der zumindest Zeichen auf den Bildschirm ausgeben werden können, eine Texteingabemöglichkeit über den Touchscreen ist mit ucLinux jedoch in keinem Fall möglich. Es bleibt nur die serielle Schnittstelle für die Daten Ein- und Ausgabe. Damit eignet sich uCLinux auf dem Palm Pilot zwar für Embedded Applications, nicht aber für die tägliche Arbeit als Organizer. Ein Erlebnis ist es aber allemal, Linux auf dem Palm Pilot laufen zu sehen und per bash mit dem Palm Pilot zu kommunizieren. Verspielte Naturen sollten sich die auf den Webseite von OSK angebotenen ROMs downloaden und im Palm Pilot Emulator ausprobieren!