Sunday, August 5, 2007

XCode Plugin for Symbian OS

I found a very interesting XCode plugin that allows for Symbian development on the Mac. Although I have Parallels, I find it really frustrating to have to constantly switch your IDE.

A compiled release of the plugin can be found on:
http://www.tomsci.com/xcodeplugin/

In version 1.1, there is a convenient utility called "installsdk.app" that extracts the SDK directories from the setup.exe for windows so you don't need a windows installation to unpack the necessary directory structure. I am currently using the "Series 60 2nd Edition, Feature Pack 3" to program for the Nokia N70. Extracting the SDK seemed to work pretty well.

However for python extension development, I also needed to download and extract the "Python for Series 60 1.2 for Series 60 2nd Edition Feature Pack 3 SDK". Unfortunately, the "installsdk.app" did not support extracting this SDK. In order to resolve this, I needed to install everything on a windows machine, then transfer the resulting SDK tree over to the mac. This is relatively easy if you have a VM running like Parallels. As mentioned in an earlier pyrex post, make sure that python-port-s60\symbian_python\symbian\pyconfig.h in the SDK directory has BAD_STATIC_FORWARD defined.

With the copied SDK tree, I was able to build my existing vanilla Symbian projects out of the box. One confusing thing for people who are used to develop on the Mac is that the build target is actually in the EPOCROOT path. For example, $EPOCROOT\epoc32\release\armi\urel\ (depending on your build settings).

After a little digging, I found that the "abld freeze" step required for DLLs is supported in XCode. Here is a snippet from the XCode readme:
"* DEF files are supported for DLLs - everything is specified in the build settings. To perform a freeze, change the "Freeze Settings" to "Freeze during next build" then perform a build. There is no separate command equivalent to "abld freeze", you just do a build with this setting on and it freezes as part of the build process."

The only problem remaining is that PETRAN (build 175) on the mac seems to be more sensitive to initialized data. I am able to successfully build a .pyd file on windows with PETRAN (build 192). However on the mac, I get the following error during the build:

PETRAN - PE file preprocessor V01.00 (Build 175)
Copyright (c) 1996-2001 Symbian Ltd.

NumberOfFunctions[1]
ERROR: Dll 'mylibrary.pyd' has initialised data.


I found an interesting article about the problem on NewLC. But I don't understand exactly why its only a problem on the mac. Perhaps it is a difference in the versions of PETRAN ...

Update: For the PETRAN problem, it turns out that the MMP importer for XCode does not properly process the following MMP commands:

EPOCDATALINKADDRESS 0x33300000
EPOCALLOWDLLDATA
EPOCCALLDLLENTRYPOINTS

That should result in the following parameters being added to the petran command:
-allow -datalinkaddress 0x33300000

I haven't figured out how to fix the XCode project to properly include these command-line parameters, until then you may have to add the commands manually from the command line.

Friday, August 3, 2007

Building s60 pyrex libraries

Pyrex is a great tool for building python extensions. Generally, pyrex libraries help you build a wrapper around a standard c++ library, which looks like any other c++ library, to allow accessing this library from python.

See the following Nokia forum post on pyrex To start, you need to make sure that the python SDK is installed. You need to make sure that python-port-s60\symbian_python\symbian\pyconfig.h in the SDK directory has BAD_STATIC_FORWARD defined.

When building s60pyrex libraries, it is important to freeze the library exports, otherwise only the .dll library (not the .lib) will be built:

Here are the sequence of commands
- abld reallyclean
- bldmake bldfiles
- abld build armi urel
- abld freeze armi (freeze exports for DLL)
- abld clean (*important - rebuild dll*)
- abld build armi urel

Thursday, August 2, 2007

Centering Text

One of the things that has been perplexing us is how to center text in Python.

The Canvas.text() api only allows for a specific X,Y location. We are still looking for a textbox object or something similar to allow for centered text. Does anyone know of a solution?

Monday, July 23, 2007

Updating firmware

We were experiencing many problems with the bluetooth stack that were actually due to problems in the firmware. Updating the firmware can save a lot of development headaches.

For Nokia phones, the Nokia Software Updater allows you to update the firmware through a USB connection.

Friday, May 25, 2007

S60 KeyCode dictionary

I've always found the key_codes module to be a bit kludgy. More elegant would be a (bidirectional) dictionary containing all the python series 60 key codes and their names.

Here's the code to generate the list:

import key_codes
list = dir(key_codes)
# cut away the default module members
keylist = list[:-4]
result = {}
for item in keylist:
value = getattr(key_codes, item)
result[value]= item
result[item] = value


And here's the list:
{0: 'EStdKeyNull',
1: 'EStdKeyBackspace',
2: 'EStdKeyTab',
3: 'EStdKeyEnter',
4: 'EStdKeyEscape',
5: 'EStdKeySpace',
6: 'EStdKeyPrintScreen',
7: 'EStdKeyPause',
8: 'EStdKeyHome',
9: 'EStdKeyEnd',
10: 'EStdKeyPageUp',
11: 'EStdKeyPageDown',
12: 'EStdKeyInsert',
13: 'EStdKeyDelete',
14: 'EStdKeyLeftArrow',
15: 'EStdKeyRightArrow',
16: 'EStdKeyUpArrow',
17: 'EStdKeyDownArrow',
18: 'EStdKeyLeftShift',
19: 'EStdKeyRightShift',
20: 'EStdKeyLeftAlt',
21: 'EStdKeyRightAlt',
22: 'EStdKeyLeftCtrl',
23: 'EStdKeyRightCtrl',
24: 'EStdKeyLeftFunc',
25: 'EStdKeyRightFunc',
26: 'EStdKeyCapsLock',
27: 'EStdKeyNumLock',
28: 'EStdKeyScrollLock',
32: 'EKeySpace',
35: 'EKeyHash',
42: 'EScancodeStar',
48: 'EScancode0',
49: 'EScancode1',
50: 'EScancode2',
51: 'EScancode3',
52: 'EScancode4',
53: 'EScancode5',
54: 'EScancode6',
55: 'EScancode7',
56: 'EScancode8',
57: 'EScancode9',
96: 'EStdKeyF1',
97: 'EStdKeyF2',
98: 'EStdKeyF3',
99: 'EStdKeyF4',
100: 'EStdKeyF5',
101: 'EStdKeyF6',
102: 'EStdKeyF7',
103: 'EStdKeyF8',
104: 'EStdKeyF9',
105: 'EStdKeyF10',
106: 'EStdKeyF11',
107: 'EStdKeyF12',
108: 'EStdKeyF13',
109: 'EStdKeyF14',
110: 'EStdKeyF15',
111: 'EStdKeyF16',
112: 'EStdKeyF17',
113: 'EStdKeyF18',
114: 'EStdKeyF19',
115: 'EStdKeyF20',
116: 'EStdKeyF21',
117: 'EStdKeyF22',
118: 'EStdKeyF23',
119: 'EStdKeyF24',
120: 'EStdKeyXXX',
121: 'EStdKeyComma',
122: 'EStdKeyFullStop',
123: 'EStdKeyForwardSlash',
124: 'EStdKeyBackSlash',
125: 'EStdKeySemiColon',
126: 'EStdKeySingleQuote',
127: 'EStdKeyHash',
128: 'EStdKeySquareBracketLeft',
129: 'EStdKeySquareBracketRight',
130: 'EStdKeyMinus',
131: 'EStdKeyEquals',
132: 'EStdKeyNkpForwardSlash',
133: 'EStdKeyNkpAsterisk',
134: 'EStdKeyNkpMinus',
135: 'EStdKeyNkpPlus',
136: 'EStdKeyNkpEnter',
137: 'EStdKeyNkp1',
138: 'EStdKeyNkp2',
139: 'EStdKeyNkp3',
140: 'EStdKeyNkp4',
141: 'EStdKeyNkp5',
142: 'EStdKeyNkp6',
143: 'EStdKeyNkp7',
144: 'EStdKeyNkp8',
145: 'EStdKeyNkp9',
146: 'EStdKeyNkp0',
147: 'EStdKeyNkpFullStop',
148: 'EStdKeyMenu',
149: 'EStdKeyBacklightOn',
150: 'EStdKeyBacklightOff',
151: 'EStdKeyBacklightToggle',
152: 'EStdKeyIncContrast',
153: 'EStdKeyDecContrast',
154: 'EStdKeySliderDown',
155: 'EStdKeySliderUp',
156: 'EStdKeyDictaphonePlay',
157: 'EStdKeyDictaphoneStop',
158: 'EStdKeyDictaphoneRecord',
159: 'EStdKeyHelp',
160: 'EStdKeyOff',
161: 'EStdKeyDial',
162: 'EStdKeyIncVolume',
163: 'EStdKeyDecVolume',
164: 'EStdKeyDevice0',
165: 'EStdKeyDevice1',
166: 'EStdKeyDevice2',
167: 'EStdKeyDevice3',
168: 'EStdKeyDevice4',
169: 'EStdKeyDevice5',
170: 'EStdKeyDevice6',
171: 'EStdKeyDevice7',
172: 'EStdKeyDevice8',
173: 'EStdKeyDevice9',
174: 'EStdKeyDeviceA',
175: 'EStdKeyDeviceB',
176: 'EStdKeyDeviceC',
177: 'EStdKeyDeviceD',
178: 'EStdKeyDeviceE',
179: 'EStdKeyDeviceF',
180: 'EStdKeyApplication0',
181: 'EStdKeyApplication1',
182: 'EStdKeyApplication2',
183: 'EStdKeyApplication3',
184: 'EStdKeyApplication4',
185: 'EStdKeyApplication5',
186: 'EStdKeyApplication6',
187: 'EStdKeyApplication7',
188: 'EStdKeyApplication8',
189: 'EStdKeyApplication9',
190: 'EStdKeyApplicationA',
191: 'EStdKeyApplicationB',
192: 'EStdKeyApplicationC',
193: 'EStdKeyApplicationD',
194: 'EStdKeyApplicationE',
195: 'EStdKeyApplicationF',
196: 'EStdKeyYes',
197: 'EStdKeyNo',
198: 'EStdKeyIncBrightness',
199: 'EStdKeyDecBrightness',
200: 'EStdKeyKeyboardExtend',
63488: 'EKeyPrintScreen',
63489: 'EKeyPause',
63490: 'EKeyHome',
63491: 'EKeyEnd',
63492: 'EKeyPageUp',
63493: 'EKeyPageDown',
63494: 'EKeyInsert',
63495: 'EKeyLeftArrow',
63496: 'EKeyRightArrow',
63497: 'EKeyUpArrow',
63498: 'EKeyDownArrow',
63499: 'EKeyLeftShift',
63500: 'EKeyRightShift',
63501: 'EKeyLeftAlt',
63502: 'EKeyRightAlt',
63503: 'EKeyLeftCtrl',
63504: 'EKeyRightCtrl',
63505: 'EKeyLeftFunc',
63506: 'EKeyRightFunc',
63507: 'EKeyCapsLock',
63508: 'EKeyNumLock',
63509: 'EKeyScrollLock',
63510: 'EKeyF1',
63511: 'EKeyF2',
63512: 'EKeyF3',
63513: 'EKeyF4',
63514: 'EKeyF5',
63515: 'EKeyF6',
63516: 'EKeyF7',
63517: 'EKeyF8',
63518: 'EKeyF9',
63519: 'EKeyF10',
63520: 'EKeyF11',
63521: 'EKeyF12',
63522: 'EKeyF13',
63523: 'EKeyF14',
63524: 'EKeyF15',
63525: 'EKeyF16',
63526: 'EKeyF17',
63527: 'EKeyF18',
63528: 'EKeyF19',
63529: 'EKeyF20',
63530: 'EKeyF21',
63531: 'EKeyF22',
63532: 'EKeyF23',
63533: 'EKeyF24',
63534: 'EKeyOff',
63535: 'EKeyIncContrast',
63536: 'EKeyDecContrast',
63537: 'EKeyBacklightOn',
63538: 'EKeyBacklightOff',
63539: 'EKeyBacklightToggle',
63540: 'EKeySliderDown',
63541: 'EKeySliderUp',
63543: 'EKeyDictaphonePlay',
63544: 'EKeyDictaphoneStop',
63545: 'EKeyDictaphoneRecord',
63546: 'EKeyHelp',
63547: 'EKeyDial',
63548: 'EKeyScreenDimension0',
63549: 'EKeyScreenDimension1',
63550: 'EKeyScreenDimension2',
63551: 'EKeyScreenDimension3',
63552: 'EKeyIncVolume',
63553: 'EKeyDecVolume',
63554: 'EKeyLeftSoftkey',
63555: 'EKeyRightSoftkey',
63556: 'EKeyDevice2',
63557: 'EKeySelect',
63558: 'EKeyDevice4',
63559: 'EKeyDevice5',
63560: 'EKeyDevice6',
63561: 'EKeyDevice7',
63562: 'EKeyDevice8',
63563: 'EKeyDevice9',
63564: 'EKeyDeviceA',
63565: 'EKeyDeviceB',
63566: 'EKeyDeviceC',
63567: 'EKeyDeviceD',
63568: 'EKeyDeviceE',
63569: 'EKeyDeviceF',
63570: 'EKeyMenu',
63571: 'EKeyApplication1',
63572: 'EKeyApplication2',
63573: 'EKeyApplication3',
63574: 'EKeyApplication4',
63575: 'EKeyApplication5',
63576: 'EKeyApplication6',
63577: 'EKeyApplication7',
63578: 'EKeyApplication8',
63579: 'EKeyApplication9',
63580: 'EKeyApplicationA',
63581: 'EKeyApplicationB',
63582: 'EKeyApplicationC',
63583: 'EKeyApplicationD',
63584: 'EKeyApplicationE',
63585: 'EKeyApplicationF',
63586: 'EKeyYes',
63587: 'EKeyNo',
63588: 'EKeyIncBrightness',
63589: 'EKeyDecBrightness',
'EKey0': 48,
'EKey1': 49,
'EKey2': 50,
'EKey3': 51,
'EKey4': 52,
'EKey5': 53,
'EKey6': 54,
'EKey7': 55,
'EKey8': 56,
'EKey9': 57,
'EKeyApplication0': 63570,
'EKeyApplication1': 63571,
'EKeyApplication2': 63572,
'EKeyApplication3': 63573,
'EKeyApplication4': 63574,
'EKeyApplication5': 63575,
'EKeyApplication6': 63576,
'EKeyApplication7': 63577,
'EKeyApplication8': 63578,
'EKeyApplication9': 63579,
'EKeyApplicationA': 63580,
'EKeyApplicationB': 63581,
'EKeyApplicationC': 63582,
'EKeyApplicationD': 63583,
'EKeyApplicationE': 63584,
'EKeyApplicationF': 63585,
'EKeyBacklightOff': 63538,
'EKeyBacklightOn': 63537,
'EKeyBacklightToggle': 63539,
'EKeyBackspace': 8,
'EKeyBell': 7,
'EKeyCapsLock': 63507,
'EKeyDecBrightness': 63589,
'EKeyDecContrast': 63536,
'EKeyDecVolume': 63553,
'EKeyDelete': 127,
'EKeyDevice0': 63554,
'EKeyDevice1': 63555,
'EKeyDevice2': 63556,
'EKeyDevice3': 63557,
'EKeyDevice4': 63558,
'EKeyDevice5': 63559,
'EKeyDevice6': 63560,
'EKeyDevice7': 63561,
'EKeyDevice8': 63562,
'EKeyDevice9': 63563,
'EKeyDeviceA': 63564,
'EKeyDeviceB': 63565,
'EKeyDeviceC': 63566,
'EKeyDeviceD': 63567,
'EKeyDeviceE': 63568,
'EKeyDeviceF': 63569,
'EKeyDial': 63547,
'EKeyDictaphonePlay': 63543,
'EKeyDictaphoneRecord': 63545,
'EKeyDictaphoneStop': 63544,
'EKeyDownArrow': 63498,
'EKeyEdit': 63499,
'EKeyEnd': 63491,
'EKeyEnter': 13,
'EKeyEscape': 27,
'EKeyF1': 63510,
'EKeyF10': 63519,
'EKeyF11': 63520,
'EKeyF12': 63521,
'EKeyF13': 63522,
'EKeyF14': 63523,
'EKeyF15': 63524,
'EKeyF16': 63525,
'EKeyF17': 63526,
'EKeyF18': 63527,
'EKeyF19': 63528,
'EKeyF2': 63511,
'EKeyF20': 63529,
'EKeyF21': 63530,
'EKeyF22': 63531,
'EKeyF23': 63532,
'EKeyF24': 63533,
'EKeyF3': 63512,
'EKeyF4': 63513,
'EKeyF5': 63514,
'EKeyF6': 63515,
'EKeyF7': 63516,
'EKeyF8': 63517,
'EKeyF9': 63518,
'EKeyFormFeed': 12,
'EKeyHash': 35,
'EKeyHelp': 63546,
'EKeyHome': 63490,
'EKeyIncBrightness': 63588,
'EKeyIncContrast': 63535,
'EKeyIncVolume': 63552,
'EKeyInsert': 63494,
'EKeyLeftAlt': 63501,
'EKeyLeftArrow': 63495,
'EKeyLeftCtrl': 63503,
'EKeyLeftFunc': 63505,
'EKeyLeftShift': 63499,
'EKeyLeftSoftkey': 63554,
'EKeyLineFeed': 10,
'EKeyMenu': 63570,
'EKeyNo': 63587,
'EKeyNull': 0,
'EKeyNumLock': 63508,
'EKeyOff': 63534,
'EKeyPageDown': 63493,
'EKeyPageUp': 63492,
'EKeyPause': 63489,
'EKeyPrintScreen': 63488,
'EKeyRightAlt': 63502,
'EKeyRightArrow': 63496,
'EKeyRightCtrl': 63504,
'EKeyRightFunc': 63506,
'EKeyRightShift': 63500,
'EKeyRightSoftkey': 63555,
'EKeyScreenDimension0': 63548,
'EKeyScreenDimension1': 63549,
'EKeyScreenDimension2': 63550,
'EKeyScreenDimension3': 63551,
'EKeyScrollLock': 63509,
'EKeySelect': 63557,
'EKeySliderDown': 63540,
'EKeySliderUp': 63541,
'EKeySpace': 32,
'EKeyStar': 42,
'EKeyTab': 9,
'EKeyUpArrow': 63497,
'EKeyVerticalTab': 11,
'EKeyYes': 63586,
'EScancode0': 48,
'EScancode1': 49,
'EScancode2': 50,
'EScancode3': 51,
'EScancode4': 52,
'EScancode5': 53,
'EScancode6': 54,
'EScancode7': 55,
'EScancode8': 56,
'EScancode9': 57,
'EScancodeBackspace': 1,
'EScancodeDownArrow': 17,
'EScancodeEdit': 18,
'EScancodeHash': 127,
'EScancodeLeftArrow': 14,
'EScancodeLeftSoftkey': 164,
'EScancodeMenu': 180,
'EScancodeNo': 197,
'EScancodeRightArrow': 15,
'EScancodeRightSoftkey': 165,
'EScancodeSelect': 167,
'EScancodeStar': 42,
'EScancodeUpArrow': 16,
'EScancodeYes': 196,
'EStdKeyApplication0': 180,
'EStdKeyApplication1': 181,
'EStdKeyApplication2': 182,
'EStdKeyApplication3': 183,
'EStdKeyApplication4': 184,
'EStdKeyApplication5': 185,
'EStdKeyApplication6': 186,
'EStdKeyApplication7': 187,
'EStdKeyApplication8': 188,
'EStdKeyApplication9': 189,
'EStdKeyApplicationA': 190,
'EStdKeyApplicationB': 191,
'EStdKeyApplicationC': 192,
'EStdKeyApplicationD': 193,
'EStdKeyApplicationE': 194,
'EStdKeyApplicationF': 195,
'EStdKeyBackSlash': 124,
'EStdKeyBacklightOff': 150,
'EStdKeyBacklightOn': 149,
'EStdKeyBacklightToggle': 151,
'EStdKeyBackspace': 1,
'EStdKeyCapsLock': 26,
'EStdKeyComma': 121,
'EStdKeyDecBrightness': 199,
'EStdKeyDecContrast': 153,
'EStdKeyDecVolume': 163,
'EStdKeyDelete': 13,
'EStdKeyDevice0': 164,
'EStdKeyDevice1': 165,
'EStdKeyDevice2': 166,
'EStdKeyDevice3': 167,
'EStdKeyDevice4': 168,
'EStdKeyDevice5': 169,
'EStdKeyDevice6': 170,
'EStdKeyDevice7': 171,
'EStdKeyDevice8': 172,
'EStdKeyDevice9': 173,
'EStdKeyDeviceA': 174,
'EStdKeyDeviceB': 175,
'EStdKeyDeviceC': 176,
'EStdKeyDeviceD': 177,
'EStdKeyDeviceE': 178,
'EStdKeyDeviceF': 179,
'EStdKeyDial': 161,
'EStdKeyDictaphonePlay': 156,
'EStdKeyDictaphoneRecord': 158,
'EStdKeyDictaphoneStop': 157,
'EStdKeyDownArrow': 17,
'EStdKeyEnd': 9,
'EStdKeyEnter': 3,
'EStdKeyEquals': 131,
'EStdKeyEscape': 4,
'EStdKeyF1': 96,
'EStdKeyF10': 105,
'EStdKeyF11': 106,
'EStdKeyF12': 107,
'EStdKeyF13': 108,
'EStdKeyF14': 109,
'EStdKeyF15': 110,
'EStdKeyF16': 111,
'EStdKeyF17': 112,
'EStdKeyF18': 113,
'EStdKeyF19': 114,
'EStdKeyF2': 97,
'EStdKeyF20': 115,
'EStdKeyF21': 116,
'EStdKeyF22': 117,
'EStdKeyF23': 118,
'EStdKeyF24': 119,
'EStdKeyF3': 98,
'EStdKeyF4': 99,
'EStdKeyF5': 100,
'EStdKeyF6': 101,
'EStdKeyF7': 102,
'EStdKeyF8': 103,
'EStdKeyF9': 104,
'EStdKeyForwardSlash': 123,
'EStdKeyFullStop': 122,
'EStdKeyHash': 127,
'EStdKeyHelp': 159,
'EStdKeyHome': 8,
'EStdKeyIncBrightness': 198,
'EStdKeyIncContrast': 152,
'EStdKeyIncVolume': 162,
'EStdKeyInsert': 12,
'EStdKeyKeyboardExtend': 200,
'EStdKeyLeftAlt': 20,
'EStdKeyLeftArrow': 14,
'EStdKeyLeftCtrl': 22,
'EStdKeyLeftFunc': 24,
'EStdKeyLeftShift': 18,
'EStdKeyMenu': 148,
'EStdKeyMinus': 130,
'EStdKeyNkp0': 146,
'EStdKeyNkp1': 137,
'EStdKeyNkp2': 138,
'EStdKeyNkp3': 139,
'EStdKeyNkp4': 140,
'EStdKeyNkp5': 141,
'EStdKeyNkp6': 142,
'EStdKeyNkp7': 143,
'EStdKeyNkp8': 144,
'EStdKeyNkp9': 145,
'EStdKeyNkpAsterisk': 133,
'EStdKeyNkpEnter': 136,
'EStdKeyNkpForwardSlash': 132,
'EStdKeyNkpFullStop': 147,
'EStdKeyNkpMinus': 134,
'EStdKeyNkpPlus': 135,
'EStdKeyNo': 197,
'EStdKeyNull': 0,
'EStdKeyNumLock': 27,
'EStdKeyOff': 160,
'EStdKeyPageDown': 11,
'EStdKeyPageUp': 10,
'EStdKeyPause': 7,
'EStdKeyPrintScreen': 6,
'EStdKeyRightAlt': 21,
'EStdKeyRightArrow': 15,
'EStdKeyRightCtrl': 23,
'EStdKeyRightFunc': 25,
'EStdKeyRightShift': 19,
'EStdKeyScrollLock': 28,
'EStdKeySemiColon': 125,
'EStdKeySingleQuote': 126,
'EStdKeySliderDown': 154,
'EStdKeySliderUp': 155,
'EStdKeySpace': 5,
'EStdKeySquareBracketLeft': 128,
'EStdKeySquareBracketRight': 129,
'EStdKeyTab': 2,
'EStdKeyUpArrow': 16,
'EStdKeyXXX': 120,
'EStdKeyYes': 196}

Friday, February 23, 2007

Asynchronous Sockets

I've looking at the pdis source directory and found an interesting module: async_socket.py

I think this might resolve our GPS thread issues as you can now perform a read in the background:

Here the python docstring:

class AsyncSocket:
"""
Defines an asynchronous socket interface. Implementors are not
required to inherit this class, but they must define the same
interface.

Note that only the thread that creates an instance of this class
may access the instance.

Note also that all the callbacks made by this object are
passed the following parameters, in the order listed:

1. event originator (an ``AsyncSocket`` handle)

2. event type (the name of the method used to make the request)

3. status (an ``Exception`` instance, or ``None`` if no error)

4. any request-specific payload (or ``None`` if none)

5. callback parameter, as specified when making the request
"""

And this is the docstring of the recieve command:

def recv(self, size, cb_func, cb_param):
"""
Makes a request to read at most ``size`` bytes from the
socket, and to call the ``cb_func`` callback function passing
the result as well as ``cb_param`` as function arguments.

The callback will not be made until the operation either
completes or fails. An empty string is returned as the
requested data to signal an EOF sent by the peer.

At most one ``recv`` request at a time may be outstanding.
"""
raise NotImplementedError

Tip of the day: Install python on the memory card

We made the fortunate decision to install python on the memory card. This has proved very beneficial since we develop a lot of python extensions that can be buggy and freeze the entire interface. If something goes wrong, simply opening up the memory card door automatically closes any applications running from it, and returns the phone to a normal state.