Logged in as Guest   Fri, Mar. 12th, 4:55 AM.      
Visitor Map
Recent Entries:
My Dev Setup Lately
Three Ways To Randomize on the iPhone
How to Remove .svn Directories On a Mac
How To Detect The iPhone Simulator
iPhoneMom Likes Doodle Games!
Updates To the Doodle Games Line
Three Jacks Now Tweets
Second iPhone App Submitted For Approval!
Pinch Media Analytics for iPhone
New iPhone Game Coming Soon!

Archive:
January - 2010
November - 2009
October - 2009
September - 2009
August - 2009
July - 2009
June - 2009
April - 2009
March - 2009
January - 2009
May - 2008
April - 2008
March - 2008
October - 2007
August - 2007
July - 2007
June - 2007
May - 2007
April - 2007
December - 2006
November - 2006
September - 2006
August - 2006
July - 2006
March - 2006
February - 2006
January - 2006
December - 2005
November - 2005
October - 2005
September - 2005
August - 2005
July - 2005
June - 2005
May - 2005
April - 2005
February - 2005
January - 2005
December - 2004
November - 2004
October - 2004
September - 2004
August - 2004
July - 2004
June - 2004
May - 2004
April - 2004
March - 2004

Running as a Background Process on the PalmOS
Overview:
At its core, the PalmOS is multithreaded. However, for all intents and purposes it is generally considered a single threaded OS for application developers. The OS itself is licensed/derived from the KADAK AMX kernel, which has support for threads, however there are no APIs to utilize them. (My guess is because of licensing restrictions, but I don't know for sure.)
One of the questions that repeatedly comes up on the Palm Developer Forums is how to accomplish multi-threading. However, when the question comes up, most developers really just want to know how to run a task in the background, and while there isn't an API to create threads, there are a few ways to implement tasks that run in the background. In this article, I present a high level overview of four of the different techniques that I have used successfully in the past.

Alarms:
Perhaps the easiest way to run a task in the background is to register an event to occur. In order to do that, you must use AlmSetAlarm to create your alarm, and then handle either the sysAppLaunchCmdAlarmTriggered or the sysAppLaunchCmdDisplayAlarm launch codes in your application. A couple caveats exist with these, however. If your application isn't the current application when it receives the alarm events, you don't have access to global variables. Furthermore, you can only use code that is in your first segment. (There are various articles elsewhere on the web detailing these limitations, so I won't go into them here.) The other limitation on this is that the latency on the alarms can be fairly high: it's probably not a good idea to use this method if you need to run more frequently than about every 5 seconds. However, this method is very appropriate if your background task's function is to wake up every so often, look around and then go back to sleep. For more "active" solutions, read on.

Registering For sysNotifyEventDequeuedEvent:
If you need lower latency in your functionality, and you are planning on running only on OS 5 and greater devices, you can register your application to receive sysNotifyEventDequeuedEvent notifications using the SysNotifyRegister function. As with any good solution, there are upsides and downsides. The upside is that you get called back every time any event gets dequeued by any application anywhere in the system. That in itself pretty much guarantees that you will get notified when something significant happens. The other big upside of this method is that since your callback will get called for all events (including NULL events), you can use EvtSetNullEventTick to control the maximum latency of your function without having to insert 'rogue' events into another application's event queue. (Although you can if you want to, but that's another article all together.)
The two downsides of this method are that 1. it is limited to OS5 and greater, and 2. depending on how much work you are doing in your callback, it could diminish the performance of the OS perceptibly. That being said, I have used this method in the past without any noticible degradation in performance.

Setting Traps:
One method that is very similar to registering for sysNotifyEventDequeuedEvent notifications, is setting a system function trap using the SysSetTrapAddress function. This is an older method of overriding the function for a system defined function. However, this functionality has been removed in OS 5, and I won't go into it in detail here since it has been depricated. (If you are looking for a good overview on this, try here.) The basic method would apply as explained in the previous section on using sysNotifyEventDequeuedEvent notifications, however, the execution would be slightly different.

The Sound Streaming Thread:
Another method for running as a background process is to queue up a streaming sound and run in the callback for that streaming sound. The most obvious limitation with this method is that it is only supported by devices that support the streaming sound API. Those are mostly limited to OS 5 devices, but to be safe, make sure to check for the .
There are various other references on the Internet how to do this, but the high level overview is that you create a variable length sound stream by calling
SndStreamCreateExtended . You then must define a callback that conforms to the SndStreamVariableBufferCallback function definition. It is in this callback that you can insert your code to work as a background process.
In case you are wondering, you don't actually have to play a sound. We're just exploiting the Streaming Sound Manager's API for callbacks to provide the functionality that you need.
One thing to note about this method is that in your callback, you don't have access to any of the symbols (i.e. global variables) that you create in your application, so use this with care.

Summary:
The PalmOS is filled with many ways to get around all the different limitations that handheld devices create for developers. The above four methods for running background tasks work very well for a very specific task. There probably are other ways to solve the same problem. These four methods are simply means to an end that I have used successfully in the past. As in any instance, YMMV. If you have used any of these methods or if you have found a different way to accomplish the same task, I'd love to hear about it.

-Jon
Submitted by bosshogg on Friday the 29th of April 2005, at 02:29 pm


Six Sigma DFSS Blackbelt Training
Well, I was down in the San Jose area (Newark specifically) for Six Sigma DFSS Blackbelt training last week, and I had a very interesting experience. If you're new to Six Sigma, it is a process that was originally created by Motorola, but since then has been adopted by many large companies, most notably GE, Xerox and 3M. It is an engineering development/design process whose general principal is to define a product or process that is measurable and can be said to be "in control". In order to say that your "process" is in control, there can only be three standard deviations from your mean when you map out
the quality of the things you produce in relation to their upper and lower spec. All that is really just "math-speak" to say that you need to have a quantifiable way to measure your successes and your failures for a "thing". In my particular case, my "thing" is software. It could be an application, or a web service, etc.
The tricky part for software engineers is that DFSS Six Sigma was originally created for hardware and manufacturing processes. As you can probably imagine, there are some things that just have no direct/obvious mapping from mechanical engineering to software engineering. I'll try and post more as I get into it and figure out exactly how to apply the techniques to software development. If you have experience with DFSS and software, I'd love to hear about it. Oh, and the picture is me eating a sundae in Ghiradelli Square. A little touristy I know, but a very fine sundae none-the-less!

-Jon
Submitted by bosshogg on Saturday the 23rd of April 2005, at 04:50 pm


Checking For the Patched NVFS Implementation
The standard way to query the OS version on the PalmOS is to use a snippet of code that looks something like this:
UInt32 romVersion = 0;
FtrGet(sysFtrCreator,sysFtrNumROMVersion, &romVersion);
After calling this, your romVersion variable will be filled with the version of the OS that is running in the format of 0xMMmfsbbb. Expanding on this, the MM is the major version, the m is the minor version and the f is the "fix" version. Here's an example: if the version of the PalmOS that your PDA was running was 4.1.2, the value returned from this function would be something like 0x04120000. (The 0's might be something else, but for all intents and purposes, the only ones you care about are the MM, the m and the f.)
If you are looking for a feature that is specific to a particular OS, it is more advisable to check for that feature inidividually, rather than check the OS version. However, there certainly are examples where the only way to check for a feature is by checking the OS version. One current example of this has presented itself with the advent of NVFS. I won't go into the details of NVFS in this article, however, suffice it to say that the original implementation of NFVS was lacking. In response to this perceived deficiency, palmOne has released a newer version that is available as a ROM update to Sprint Treo 650s and comes by default in the new Tungsten E2.
According to the documentation, the way to check for the presence of NVFS is to use something like this:
FtrGet(sysFtrCreator, sysFtrNumDmAutoBackup, &returnVal);

If returnVal is 1, then the device uses NVFS. Now, with two different NVFS implementations, we are presented with the problem of knowing which version of NVFS we have. There are many projects (including my own) that have implemented "special" workarounds for NVFS. With the newer implementation, developers may not want to use those workarounds if the updated version of NVFS is present.
Here is where we come to the real meat of the article. As I was digging around looking at the two different Sprint Treo 650s that I have, I noticed that the unpatched device is running PalmOS version 5.4.5 and the patched device is running 5.4.7. I then checked my E2 which comes with the updated NVFS implementation and it also is running 5.4.7. So, armed with this knowledge, I have been able to deduce that the way to check whether a device has the updated NVFS implementation is to check that the OS version is greater than or equal to 5.4.7. Easy enough right? Well, as usual there's a wrinkle. On the Tungsten T5, the Treo 650 and the Tungsten E2, the code that I presented at the beginning of the article doesn't quite work. These devices all return 0x05400000. That seemed very strange because the finder displays the correct version. So, I went digging to see if there are other ways to query for the OS version. This led me to the SysGetROMTokenString function. To be honest, I had never used this function before because it returns a string value instead of a numeric value. However, as it turns out, this function returns the correct information on the new devices.
I could probably write more about this, but the moral of this story is that the only way to check for the updated NVFS implementation is to call SysGetROMTokenString() and parse the returned string to check for OS version 5.4.7 or greater.
As always, I hope this helps you in your journeys, and if you find it helpful, I always like to know.

-Jon
Submitted by bosshogg on Sunday the 17th of April 2005, at 09:44 pm


Registered for PalmSource 2005
I'm now registered and have my travel accomodations set up for this year's PalmSource DevCon. I managed to get into the Fairmont (which is where the conference is being held) so I'm pretty excited about that. Last year I had to stay at the Hilton which is a few blocks away, and I spent a good part of my time hoofing it back and forth between the conference and my room.
So, now I just need to schedule the fun stuff! If you're going to be at the conference, send me an email and we can try and hook up during the conference. If the timing works out right, maybe I'll even spring for dinner! :-)
Hope to see you there!

-Jon
Submitted by bosshogg on Wednesday the 06th of April 2005, at 10:57 am


Inspecting Network Connection Settings On The PalmOS
Sometimes, you need to know a bit about the connection that you've established with NetLibOpen, especially if it was established with DHCP. Perhaps you need to do some debugging of the DNS server, or perhaps you need to see what gateway your application actually connected to. Even more likely, you might need to know what IP address your device was assigned. You might use this address to establish a P2P service or a multiplayer game connection. There are many reasons why your application might need to do this, but I'm sure you can come up with your own ideas as well.
All of these settings can be found in NetMgr.h, but for the sake of simplicity, I present the settings that I have found invaluable when trying to debug network connectivity issues:

UInt32 dhcpPPPAddress;
UInt32 subnetMask;
UInt32 serverPPPAddress;
UInt32 primaryDNS;
UInt32 secondaryDNS;
UInt16 size = sizeof(UInt32);

//This will return the IP address of the gateway server that 
//was assigned to the device...
Err err = NetLibSettingGet(netLibRef, 
                           netIFSettingServerIPAddr, 
                           &serverPPPAddress, 
                           &size);

//This will return the IP address that was assigned to the 
//device itself...
err = NetLibSettingGet(netLibRef, 
                       netIFSettingActualIPAddr,  
                       &dhcpPPPAddress, 
                       &size);

//This will return the subnet mask that was assigned to the 
//device itself...
err = NetLibSettingGet(netLibRef, 
                       netIFSettingSubnetMask, 
                       &subnetMask, 
                       &size);

//This will return the IP address of the primary DNS server 
//that was assigned to the device...
err = NetLibSettingGet(netLibRef, 
                       netSettingRTPrimaryDNS, 
                       &primaryDNS, 
                       &size);

//This will return the IP address of the secondary DNS 
//server that was assigned to the device...
err = NetLibSettingGet(netLibRef, 
                       netSettingRTSecondaryDNS, 
                       &secondaryDNS, 
                       &size);


As usual, this code is presented as-is, but if you find it helpful, I always like to know.

-Jon
Submitted by bosshogg on Friday the 01st of April 2005, at 10:42 pm


A Translucent Palm VII and the Obsoleted INetLib Interface
Discovery
I was digging through some things at work the other day, and I came across this beauty. It's an old Palm VII, but the body is made of clear plastic so you can see the innards. Nobody at work seemed to know where it came from, and looking at the stylus branded with symbol.com, I was even more confused. I figured that it was probably non-operational, but on a whim, decided to put new batteries into it, and wouldn't you know it, but it still works!
History
Of course, that started me thinking about the VII in general. Here's the history as I know it:
Back in May of 1999, when palmOne was still part of 3Com, the Palm VII was released in New York City to much fanfare. The VII was basically a Palm III with a Mobitex modem integrated into it. (I'm sure there were other differences, but to end users that's what it was.) The Mobitex modem connected to a proprietary wireless network known as Palm.Net, and cost $9.99 per month to subscribers. The kicker for the VII was that it introduced what is now know as "Web Clipping". The idea behind Web Clipping was that websites would create custom components known as PQAs (Palm Query Apps) that would be downloaded and installed onto users' devices. The concept was that the PQA would provide a frontend for websites and that only transient/changing data would have to be transmitted over the network to the VII. The Mobitex network that the VIIs used is/was originally designed for pagers and really isn't suitable for large amounts of data. At the time, Web Clipping seemed like a pretty good idea.

Epilogue
As you have probably deduced, the VII (and its successor the i705) didn't catch fire, and eventually the Palm.Net network was deactivated and now is no longer in existence. As they say, hindsight is always 20/20, so I won't spend time dwelling on the failure. What I would like to mention is that the VII (and the i705) introduced a whole secondary network library generally referred to as INetLib. This interface was only ever intended for the Palm.Net network, and therefore is completely obsolete. Unfortunately, the INetLib.h header is still included in the SDKs, so many developers that are new to the Palm networking interfaces stumble upon them and try to use them. It is understandable why they try; among the INetLib functions are high level (HTTP) transmision functionality. For example, there is an INetLib function called INetLibURLOpen. The help file on INetLibURLOpen doesn't mention that it has been obsoleted and in fact describes the purpose of the function as "Accesses a URL on the Internet or in the cache." That is a pretty cool sounding function, and if you search the rest of the SDK, you won't find an equivalent function in the standard NetLib interfaces. I'm not sure why PalmSource hasn't created a high level interface for sending/receiving HTTP requests. It seems like it would be a pretty useful library. In fact, I could see a whole library of functionality that could send/receive on a number of higher level protocols. Imagine a library that could setup and handle a telnet session, or an SSH session. What about a simple FTP or SFTP transfer? What about an SMTP or a POP3 session? My wish list could go on and on. I would envision that the library could take care of the lower level details of establishing a network connection and abstract away the implementation details of the higher level protocols, thereby making Palm developer's lives much easier.
Ah well. It's all just a wish right now. Maybe someday we'll see it. Until then, we all can just keep reinventing the wheel. =)

-Jon
Submitted by bosshogg on Friday the 01st of April 2005, at 10:41 pm