Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/11-7
11-7 ROM シリアルナンバー
Palm III 以降のハンドヘルドでは、ハンドヘルドを一意に識別する 12 桁の数字からなるシリアルナンバーを持っています(それより前のハンドヘルドにはこの識別子はありません)。シリアルナンバーは NULL 終端なしの表示可能なテキストバッファに格納されています。ユーザーはアプリケーションランチャでシリアルナンバーを見ることができます(ポップアップバージョンのランチャではシリアルナンバーは表示されません)。アプリケーションランチャは、シリアルナンバーのユーザーエントリを検証できるチェックサムディジットの表示もおこないます。
ROM シリアルナンバーをプログラムで取得するには、SysGetROMToken 関数に sysROMTokenSnum セレクタを渡します。SysGetROMToken 関数がエラーを返した場合やバッファを指すポインタとして NULL が返された場合、あるいは返されたテキストバッファの先頭バイトが 0xFF の場合、シリアルナンバーは利用できません。
リスト 11.9 に示す DrawSerialNumOrMessage 関数は、ROM シリアルナンバーを取得してチェックサムを算出し、その両方をディスプレイの特定の位置に表示します。ハンドヘルドがシリアルナンバーを持っていなければ、この関数は指定されたメッセージを表示します。この関数は入力として、出力を描画する座標とシリアルナンバーが利用できなかった場合に描画するメッセージのポインタを受け取ります。
リスト 11.9 DrawSerialNumOrMessage 関数
static void DrawSerialNumOrMessage(Int16 x, Int16 y, Char* noNumberMessage) { Char* bufP; UInt16* bufLen; Err retval; Int16 count; UInt8 checkSum; Char checksumStr[2]; // holds the dash and the checksum digit retval = SysGetROMToken (0, sysROMTokenSnum, (UInt8**) &bufP, &bufLen); if ((!retval) && (bufP) && ((UInt8) *bufP != 0xFF)) { // there's a valid serial number! // Calculate the checksum: Start with zero, add each digit, // then rotate the result one bit to the left and repeat. checkSum = 0; for (count=0; count<bufLen; count++) { checkSum += bufP[count]; checkSum = (checkSum<<1) | ((checkSum & 0x80) >> 7); } // Add the two hex digits (nibbles) together, +2 // (range: 2 - 31 ==> 2-9, A-W) // By adding 2 to the result before converting to ascii, // we eliminate the numbers 0 and 1, which can be // difficult to distinguish from the letters O and I. checkSum = ((checkSum>>4) & 0x0F) + (checkSum & 0x0F) + 2; // draw the serial number and find out how wide it was WinDrawChars(bufP, bufLen, x, y); x += FntCharsWidth(bufP, bufLen); // draw the dash and the checksum digit right after it checksumStr[0] = '-'; checksumStr[1] = ((checkSum < 10) ? (checkSum +'0'):(checkSum -10 +'A')); WinDrawChars (checksumStr, 2, x, y); } else // there's no serial number // draw a status message if the caller provided one if (noNumberMessage) WinDrawChars(noNumberMessage, StrLen(noNumberMessage),x, y); }