1 /******************************************************************************
*
* Palm Interactive Boardroom ( PIB )
* Handheld presentation tool using a networked projector as a display.
*
* This source code is based on default IDE source as well as royalty-free
* samples provided with the IDE. This file shell was generated by the Palm OS
* Developer Suite IDE.
*
* Other royalty-free source code from HelloNetLib.c ( provided by
* Palm at www.palmsource.com ) to send TCP and UDP traffic to an IP
* address + port number was modified significanlty in support of
* the PIB requirements.
*
* Programming environment: Palm OS Developer Suite
*
* Created by Scott Armstrong for UIUC CS-427 Group 30, Fall 2005
* based on UML and requirements outlined by Group 30 members.
*
* File: AppMain.c
*
* Version 3.2.1
* - Work on integrating "Transfer" function set ( Project )
* - "Connect" ( connect to network ) is automatically started on the device
* based on a network call - an interactive function will be integrated
* in future iterations.
* - Issues connecting the Button trigger event to the Transfer form
*
*****************************************************************************/
#include <PalmOS.h>
//#include <StdIOPalm.h> // For console IO, link SdtIOPalm.c ( possible future use )
#include <INetMgr.h> // For managing device network settings
#include "AppResources.h" // Resources to associate forms to function calls
/***********************************************************************
*
* Internal Structures
*
***********************************************************************/
typedef struct // for Network IP address + Port
{
NetIPAddr addr;
UInt16 port;
} NetLibPreferenceType;
/***********************************************************************
*
* Globals
*
***********************************************************************/
NetLibPreferenceType gPrefs = {};
const UInt16 bufLen = 16; // for initial test string to send ( temporary )
char buf[16] = "testing 1-2\n"; // initial test string to send ( temporary )
/***********************************************************************
*
* Internal Constants, application-specific
*
***********************************************************************/
#define appFileCreator 'xPIB' // register your own at http://www.palmos.com/dev/creatorid/
// CRIDs xPIB and cPIB are reserved for our use at palmsource.com
#define appVersionNum 0x01 // - version set on:
#define appPrefID 0x00 // - prefID set on:
#define appPrefVersionNum 0x01 // - PrefVersion set on:
// Minimum OS version supported - Network issues
#define ourMinVersion sysMakeROMVersion( 3, 0, 0, sysROMStageRelease, 0 )
#define kPalmOS10Version sysMakeROMVersion( 1, 0, 0, sysROMStageRelease, 0 )
#define CLEAR_RESULT -1
#define PROCESSING_RESULT -2
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
// User Interface functions ( Transfer/Project Form )
88 static void ShowResult( UInt16 id, Err error );
89 static void ClearResults( void );
90 static Boolean GetValue( UInt16 objID, Int32 *valueP );
91 static Boolean SetValue( UInt16 objID, Int32 value );
92 static Boolean GetAddr( UInt16 AppNetRefnum, NetIPAddr *addrP, UInt16 *portP );
// Network function
95 static void SendTCP( void );
// static void SendUDP( void ); // Currently only using TCP - possible future
// UDP implementation
/***********************************************************************
*
* Internal Function Definitions
*
***********************************************************************/
/***********************************************************************
*
* FUNCTION: ShowResult ( part of Transfer / Project )
*
* DESCRIPTION: This routine updates the UI to show the results of each
* of the function calls involved in the current network
* operation.
* This information should be streamlined or possibly removed
* from the UI as we approach the final PIB releases.
* This is valuable information for testing and debugging for now.
*
* PARAMETERS: id - ID of the label to update
* error - error code returned by the corresponding
* function. If this is -1 the result is cleared
*
* RETURNED: none
*
***********************************************************************/
123 static void ShowResult( UInt16 id, Err error )
{
char resultString[11];
FormType *formPtr;
UInt16 objIndex;
// Prepare the result as a string
switch ( error ){
case CLEAR_RESULT:
StrCopy( resultString, " " );
break;
case PROCESSING_RESULT:
StrCopy( resultString, " .... " ); // indicates no results yet
break;
default:
StrPrintF( resultString, "0x%04X", error );
break;
}
// Update the specified field label
formPtr = FrmGetFormPtr( MainForm );
objIndex = FrmGetObjectIndex( formPtr, id );
FrmHideObject( formPtr, objIndex );
FrmCopyLabel( formPtr, id, resultString );
FrmShowObject( formPtr, objIndex );
}
/***********************************************************************
*
* FUNCTION: ClearResults
*
* DESCRIPTION: This routine clears all the results listed on the main
* form.
*
* PARAMETERS: none
*
* RETURNED: none
*
***********************************************************************/
162 static void ClearResults( void )
{
ShowResult( MainSysLibFindResultLabel, -1 );
ShowResult( MainNetLibOpenResultLabel, -1 );
ShowResult( MainNetLibOpenIFResultLabel, -1 );
ShowResult( MainNetLibSocketOpenResultLabel, -1 );
ShowResult( MainNetLibSocketConnectResultLabel, -1 );
ShowResult( MainNetLibSendResultLabel, -1 );
ShowResult( MainBytesSentResultLabel, -1 );
ShowResult( MainNetLibSocketCloseResultLabel, -1 );
ShowResult( MainNetLibCloseResultLabel, -1 );
}
/***********************************************************************
*
* FUNCTION: GetValue
*
* DESCRIPTION: This routine gets the numeric value of the specified
* text field.
*
* PARAMETERS: objID - ID of the field on the main form
* valueP - pointer to memory where value is returned
*
* RETURNED: True if successful, false otherwise.
*
***********************************************************************/
188 static Boolean GetValue( UInt16 objID, Int32 *valueP )
{
FormType *formPtr;
UInt16 objIndex;
FieldType *fieldPtr;
Char *text;
formPtr = FrmGetFormPtr( MainForm );
if ( !formPtr ) return false;
objIndex = FrmGetObjectIndex( formPtr, objID );
fieldPtr = ( FieldType* )FrmGetObjectPtr( formPtr, objIndex );
if ( !fieldPtr ) return false;
text = FldGetTextPtr( fieldPtr );
if ( !text ) return false;
*valueP = StrAToI( text );
return true;
}
/***********************************************************************
*
* FUNCTION: SetValue
*
* DESCRIPTION: This routine sets the numeric value of the specified
* text field.
*
* PARAMETERS: objID - ID of the field on the main form
* value - the value to insert
*
* RETURNED: True if successful, false otherwise.
*
* NOTES: Determines the maximum length to use based upon the ID
*
***********************************************************************/
226 static Boolean SetValue( UInt16 objID, Int32 value )
{
FormType *formPtr;
UInt16 objIndex;
FieldType *fieldPtr;
MemHandle h, oldHandle;
Char *text;
formPtr = FrmGetFormPtr( MainForm );
if ( !formPtr ) return false;
objIndex = FrmGetObjectIndex( formPtr, objID );
fieldPtr = ( FieldType* )FrmGetObjectPtr( formPtr, objIndex );
if ( !fieldPtr ) return false;
if ( MainPortField == objID ) {
h = MemHandleNew( 6 );
} else {
h = MemHandleNew( 4 );
}
if ( !h ) return false;
text = MemHandleLock( h );
if ( MainPortField == objID ) {
StrPrintF( text, "%u", ( UInt16 )value );
} else {
StrPrintF( text, "%u", ( UInt8 )value );
}
MemHandleUnlock( h );
oldHandle = FldGetTextHandle( fieldPtr );
FldSetTextHandle( fieldPtr, h );
if ( oldHandle ) MemHandleFree( oldHandle );
return true;
}
/***********************************************************************
*
* FUNCTION: GetAddr
*
* DESCRIPTION: This routine gets the IP address and port that the user
* has entered.
*
* PARAMETERS: AppNetRefnum - Reference number of NetLib
* addrP - pointer to memory where address is
* returned
* portP - pointer to memory where port is
* returned
*
* RETURNED: True if the IP address and port are valid, false
* otherwise.
*
* NOTES: The only check peformed is to see whether the values
* are in the appropriate numeric ranges. This doesn't
* check whether the specified host exists or is listening
* on the specified port.
* If host is not found, the system stops processing and
* pauses until a timeout period.
* - Future releases should include a "host not found" check.
*
***********************************************************************/
287 static Boolean GetAddr( UInt16 AppNetRefnum, NetIPAddr *addrP, UInt16 *portP )
{
UInt8 i;
Int32 ip[4];
Int32 port;
Char textIP[16];
// Get the values
for ( i = 0; i < 4; i++ ) {
if ( !GetValue( MainIP1Field + i, &( ip[i] ) ) ||
ip[i] > 255 ||
ip[i] < 0 ) {
return false;
}
}
if ( !GetValue( MainPortField, &port ) ||
port > 65535 ||
port < 1 ) {
return false;
}
StrPrintF( textIP, "%u.%u.%u.%u", ( UInt8 )ip[0], ( UInt8 )ip[1], ( UInt8 )ip[2], ( UInt8 )ip[3] );
*addrP = NetLibAddrAToIN( AppNetRefnum, textIP );
*portP = ( UInt16 )port;
return true;
}
/***********************************************************************
*
* FUNCTION: SendTCP
*
* DESCRIPTION: This routine uses NetLib to send TCP data.
* The user needs to enter the appropriate IP address and Port.
* Future versions should include selectable Ports depending on
* the Wireless projector configuation or a default ( if one exists ).
*
* PARAMETERS: none
*
* RETURNED: none
*
***********************************************************************/
330 static void SendTCP( void )
{
Err error;
UInt16 AppNetRefnum;
UInt16 ifErrs;
NetSocketRef socket;
Int16 result;
NetSocketAddrINType destAddr;
// const UInt16 bufLen = 15;
// char buf[bufLen] = "xxxxxx\n"; // will need to substitute a file
// earlier attempts to compile this with
// a locally scoped Char array wouldn't compile.
// this function currently uses a globally
// scoped Char array for testing
UInt16 sentBytes = 0;
ClearResults( );
// Find the network library and activate the currenlty configured network.
ShowResult( MainSysLibFindResultLabel, PROCESSING_RESULT );
error = SysLibFind( "Net.lib", &AppNetRefnum );
ShowResult( MainSysLibFindResultLabel, error );
if ( error ) return;
// Get and validate the destination
if ( !GetAddr( AppNetRefnum, &gPrefs.addr, &gPrefs.port ) ) {
FrmAlert( InvalidDestAlert );
return;
}
// Open the network library
ShowResult( MainNetLibOpenResultLabel, PROCESSING_RESULT );
ShowResult( MainNetLibOpenIFResultLabel, PROCESSING_RESULT );
error = NetLibOpen( AppNetRefnum, &ifErrs );
ShowResult( MainNetLibOpenResultLabel, error );
ShowResult( MainNetLibOpenIFResultLabel, ifErrs );
if ( ifErrs || ( error && error != netErrAlreadyOpen ) ) goto CloseNetLib;
// Open a socket
ShowResult( MainNetLibSocketOpenResultLabel, PROCESSING_RESULT );
socket = NetLibSocketOpen( AppNetRefnum, // Network library
netSocketAddrINET, // Address domain
netSocketTypeStream, // Socket type
netSocketProtoIPTCP, // Protocol
-1, // Timeout
&error // Error result
);
ShowResult( MainNetLibSocketOpenResultLabel, error );
if ( error ) goto CloseNetLib;
// Connect the socket to its destination
MemSet( &destAddr, sizeof( destAddr ), 0 );
destAddr.family = netSocketAddrINET; // This should match the second argument to NetLibSocketOpen
destAddr.port = gPrefs.port;
destAddr.addr = gPrefs.addr;
error = 0;
ShowResult( MainNetLibSocketConnectResultLabel, PROCESSING_RESULT );
result = NetLibSocketConnect( AppNetRefnum, // Network library
socket, // Socket reference
( NetSocketAddrType* )&destAddr, // Destination address
sizeof( destAddr ), // Length of destAddr
-1, // Timeout
&error // Error result
);
if ( result == -1 ) {
ShowResult( MainNetLibSocketConnectResultLabel, error );
goto CloseSocket;
} else {
ShowResult( MainNetLibSocketConnectResultLabel, 0 );
}
// Send data
ShowResult( MainBytesSentResultLabel, PROCESSING_RESULT );
while ( sentBytes < bufLen ) {
ShowResult( MainNetLibSendResultLabel, PROCESSING_RESULT );
result = NetLibSend ( AppNetRefnum, // Network library
socket, // Socket reference
buf + sentBytes, // Buffer to send
bufLen - sentBytes, // Bytes to send from buffer
0, // Flags
NULL, // Destination address -- does not apply to TCP sockets
0, // Length of destination address
-1, // Timeout
&error // Error result
);
if ( result == -1 ) {
ShowResult( MainNetLibSendResultLabel, error );
goto CloseSocket;
}
sentBytes += result;
ShowResult( MainBytesSentResultLabel, sentBytes );
}
ShowResult( MainNetLibSendResultLabel, 0 );
// Close the socket
CloseSocket:
ShowResult( MainNetLibSocketCloseResultLabel, PROCESSING_RESULT );
result = NetLibSocketClose ( AppNetRefnum, // Network Library
socket, // Socket reference
-1, // Timeout
&error // Error result
);
if ( result == -1 ) {
ShowResult( MainNetLibSocketCloseResultLabel, error );
} else {
ShowResult( MainNetLibSocketCloseResultLabel, 0 );
}
// Close the network library
CloseNetLib:
ShowResult( MainNetLibCloseResultLabel, PROCESSING_RESULT );
error = NetLibClose( AppNetRefnum, false );
ShowResult( MainNetLibCloseResultLabel, error );
}
/***********************************************************************
*
* FUNCTION: GetObjectPtr
*
* DESCRIPTION: This routine returns a pointer to an object in the current
* form.
*
* PARAMETERS: formId - id of the form to display
*
* RETURNED: void *
*
* REVISION HISTORY:
* - V3.2 - Defined but not used
*
*
***********************************************************************/
461 static void * GetObjectPtr( UInt16 objectID )
{
FormPtr frmP;
frmP = FrmGetActiveForm( );
return FrmGetObjectPtr( frmP, FrmGetObjectIndex( frmP, objectID ) );
}
/***********************************************************************
*
* FUNCTION: MainFormInit
*
* DESCRIPTION: This routine initializes the MainTransferForm form.
*
* PARAMETERS: frm - pointer to the MainTransferForm form.
*
* RETURNED: nothing
*
* REVISION HISTORY:
*
*
***********************************************************************/
485 static void MainFormInit( FormPtr frmP )
{
ClearResults( );
}
// =================================================================
/***********************************************************************
*
* FUNCTION: MainTransferFormHandleEvent
*
* DESCRIPTION: This routine is the event handler for the
* "MainTransferForm" of this application.
*
* PARAMETERS: eventP - a pointer to an EventType structure
*
* RETURNED: true if the event has handle and should not be passed
* to a higher level handler.
*
* REVISION HISTORY:
* - V3.2 - Defined byt not used
* - Need to standardize the pointers used within the functions to
* match the Palm defaults pEvent, pForm
* ( Semantically, "p"ointer to Form, not form"p"ointer )
*
***********************************************************************/
511 static Boolean MainTransferFormHandleEvent( EventPtr eventP )
{
Boolean handled = false;
FormPtr frmP;
switch ( eventP->eType ) {
case frmOpenEvent:
frmP = FrmGetActiveForm( );
MainFormInit( frmP );
// Load initial values from prefs
SetValue( MainIP1Field, ( gPrefs.addr & 0xFF000000 ) >> 24 );
SetValue( MainIP2Field, ( gPrefs.addr & 0x00FF0000 ) >> 16 );
SetValue( MainIP3Field, ( gPrefs.addr & 0x0000FF00 ) >> 8 );
SetValue( MainIP4Field, gPrefs.addr & 0x000000FF );
SetValue( MainPortField, gPrefs.port );
FrmDrawForm ( frmP );
handled = true;
break;
case frmUpdateEvent:
break;
case ctlSelectEvent:
switch ( eventP->data.ctlSelect.controlID ) {
case MainSendTCPButton:
SendTCP( );
break;
// case MainSendUDPButton: // possible future use
// SendUDP( );
// break;
default:
break;
}
break;
default:
break;
}
return handled;
}
// =================================================================
/***********************************************************************
*
* FUNCTION: MainFormDoCommand
*
* DESCRIPTION: This routine performs the menu command specified.
*
* PARAMETERS: command - menu item id
*
* RETURNED: nothing
*
* REVISION HISTORY: ( default menu item selector )
* V3.0 - added "ConnectForm" stub form to Options menu
* v3.1 - introduced network Send menu
* V3.2 - removed "ConnectForm" stub form from Options menu
*
*
***********************************************************************/
575 static Boolean MainFormDoCommand( UInt16 command )
{
Boolean handled = false;
FormType * pForm;
switch ( command ) {
case MainOptionsAboutStarterApp:
pForm = FrmInitForm( AboutForm );
FrmDoDialog( pForm ); // Display the About Box.
FrmDeleteForm( pForm );
handled = true;
break;
case MainOptionsSelectFileStarterApp:
pForm = FrmInitForm( SelectFileForm );
FrmDoDialog( pForm ); // Display the Select File Box.
FrmDeleteForm( pForm );
handled = true;
break;
case MainOptionsTransferSettingsStarterApp:
pForm = FrmInitForm( MainTransferForm );
FrmDoDialog( pForm ); // Display the Transfer Video Box.
FrmDeleteForm( pForm );
handled = true;
break;
}
return handled;
}
/***********************************************************************
*
* FUNCTION: MainFormHandleEvent
*
* DESCRIPTION: This routine is the event handler for the
* "MainForm" of this application.
*
* PARAMETERS: pEvent - a pointer to an EventType structure
*
* RETURNED: true if the event has handle and should not be passed
* to a higher level handler.
*
* REVISION HISTORY: ( default main form event handler )
*
*
***********************************************************************/
621 static Boolean MainFormHandleEvent( EventType* pEvent )
{
Boolean handled = false;
FormType* pForm;
switch ( pEvent->eType ) { // Level 1
case menuEvent:
return MainFormDoCommand( pEvent->data.menu.itemID );
case frmOpenEvent:
pForm = FrmGetActiveForm( );
FrmDrawForm( pForm );
handled = true;
break;
// --location of the Trigger event from the main page using the Project
// button. The functionality is currently separated as its own application
// but can be re-integrated once the button trigger event works correctly.
// --challenge: unfamiliar programming environment, how to correctly
// handle various triggers on a form.
// --the form itself is now accessible using the Options menu but has no
// functionality.
//
// case ctlSelectEvent:
// switch ( pEvent->data.ctlSelect.controlID ) { // Level 2
// case xxxxxx:
//
// handled = true;
// break;
// default:
// break;
// } // Level 2
break;
default:
break;
} // Level 1
return handled;
}
/***********************************************************************
*
* FUNCTION: AppHandleEvent
*
* DESCRIPTION: This routine loads form resources and set the event
* handler for the form loaded.
*
* PARAMETERS: pEvent - a pointer to an EventType structure
*
* RETURNED: true if the event has handle and should not be passed
* to a higher level handler.
*
* REVISION HISTORY:
*
*
***********************************************************************/
679 static Boolean AppHandleEvent( EventType* pEvent )
{
UInt16 formId;
FormType* pForm;
Boolean handled = false;
if ( pEvent->eType == frmLoadEvent ) {
// Load the form resource.
formId = pEvent->data.frmLoad.formID;
pForm = FrmInitForm( formId );
FrmSetActiveForm( pForm );
// Set the event handler for the form. The handler of the currently
// active form is called by FrmHandleEvent each time is receives an
// event.
switch ( formId ) {
case MainForm:
FrmSetEventHandler( pForm, MainFormHandleEvent );
break;
default:
break;
}
handled = true;
}
return handled;
}
/***********************************************************************
*
* FUNCTION: AppStart
*
* DESCRIPTION: Get the current application's preferences.
*
* PARAMETERS: nothing
*
* RETURNED: Err value errNone if nothing went wrong
*
* REVISION HISTORY:
*
*
***********************************************************************/
724 static Err AppStart( void )
{
FrmGotoForm( MainForm );
return errNone;
}
/***********************************************************************
*
* FUNCTION: AppStop
*
* DESCRIPTION: Save the current state of the application.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
*
*
***********************************************************************/
745 static void AppStop( void )
{
// Close all the open forms.
FrmCloseAllForms( );
}
/***********************************************************************
*
* FUNCTION: AppEventLoop
*
* DESCRIPTION: This routine is the event loop for the application.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
*
*
***********************************************************************/
766 static void AppEventLoop( void )
{
Err error;
EventType event;
do {
EvtGetEvent( &event, evtWaitForever );
if ( SysHandleEvent( &event ) )
continue;
if ( MenuHandleEvent( 0, &event, &error ) )
continue;
if ( AppHandleEvent( &event ) )
continue;
FrmDispatchEvent( &event );
} while ( event.eType != appStopEvent );
}
/***********************************************************************
*
* Entry Points
*
***********************************************************************/
/***********************************************************************
*
* FUNCTION: PilotMain
*
* DESCRIPTION: This is the main entry point for the application.
*
* PARAMETERS: cmd - word value specifying the launch code.
* cmdPB - pointer to a structure that is associated with the launch code.
* launchFlags - word value providing extra information about the launch.
* RETURNED: Result of launch
*
* REVISION HISTORY: 3rd major revision ( attempt ) to get Interface
* functionality from the forms. -sra
*
*
***********************************************************************/
811 UInt32 PilotMain( UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags )
{
Err error = errNone;
switch ( cmd ) {
case sysAppLaunchCmdNormalLaunch:
if ( ( error = AppStart( ) ) == 0 ) {
AppEventLoop( );
AppStop( );
}
break;
default:
break;
}
return error;
}