I am trying to connect to a device using Bluetooth. I am able to get a
connection, but after receiving about a megabyte from the device, SrmReceive
suddenly stops receiving data.
If I connect to the device using a Python script on my PC, I am able to receive
an unlimited amount of data with no problems.
The device is a WiTilt v3.0 accelerometer, made by SparkFun. The WiTilt uses a
Roving Networks RN-41 Bluetooth module. I am using a Palm Tungsten T for
testing.
I've been poking away at the problem for about a month now, but haven't figured
it out. I have discovered the following through testing:
1. My ReceiveBytes function, which is called regularly from the main loop,
continues to be called.
2. Calling SrmGetStatus from the ReceiveBytes function returns normal status
before and after the problem occurs.
3. After the problem occurs, if I attempt a HotSync operation, the Palm hangs
when "cleaning up". I take this to mean that something has become corrupted due
to the problem, but I can't see where that could be happening.
I've attached the main source code file from the project. The key functions are
reproduced below in simplified form.
If you need any additional information, please let me know. This problem has
been plaguing me for over a month now, so I would greatly appreciate any help.
Michael
static Err Connect(void)
{
Err error;
SrmOpenConfigType config;
char buf[3];
MemSet(&config, sizeof(config), 0);
error = SrmExtOpen(
sysFileCVirtRfComm,
&config,
sizeof(config),
&btPortId);
if (error) return error;
connected = true;
error = SrmReceiveFlush(btPortId, SysTicksPerSecond());
if (error) return error;
SrmSend(btPortId, " ", 1, &error);
if (error) return error;
error = SrmReceiveWait(btPortId, 2, SysTicksPerSecond());
if (error) return error;
SrmReceive(btPortId, buf, 2, 0, &error);
if (error) return error;
if (StrNCompare(buf, "OK", 2) != 0) return errNotWiTilt;
return errNone;
}
static Err ReceiveBytes(void)
{
Err error;
unsigned char buf[512];
UInt32 n;
UInt32 status;
UInt16 lineError;
cmd.cmd = sndCmdFreqDurationAmp;
cmd.param2 = 50;
cmd.param3 = sndMaxAmp / 2;
error = SrmReceiveCheck(btPortId, &n);
if (error) {
SrmReceiveFlush(btPortId, 0);
return error;
}
n = SrmReceive(btPortId, buf, Min(n, sizeof (buf)), 0, &error);
if (error) {
SrmReceiveFlush(btPortId, 0);
return error;
}
error = SrmGetStatus(btPortId, &status, &lineError);
if (error) return error;
if (lineError != 0) {
SrmReceiveFlush(btPortId, 0);
}
return errNone;
}
static void AppEventLoop(void)
{
Err error;
EventType event;
do {
if (connected) {
EvtGetEvent(&event, 0);
EvtResetAutoOffTimer();
} else {
EvtGetEvent(&event, evtWaitForever);
}
if (SysHandleEvent(&event)) continue;
if (MenuHandleEvent(0, &event, &error)) continue;
if (AppHandleEvent(&event)) continue;
FrmDispatchEvent(&event);
} while (event.eType != appStopEvent);
}
--
For information on using the ACCESS Developer Forums, or to unsubscribe, please
see http://www.access-company.com/developers/forums/#include <PalmOS.h>
#include "AppResources.h"
#define appFileCreator 'MCMC'
#define appVersionNum 0x01
#define appPrefID 0x00
#define appPrefVersionNum 0x01
#define errNotWiTilt (appErrorClass + 0)
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define Max(a, b) (((a) > (b)) ? (a) : (b))
static Boolean connected = false;
static UInt16 btPortId;
static UInt32 totalBytes;
static UInt32 receiveCount;
static void SetField(
UInt16 formID,
UInt16 fieldID,
MemPtr str)
{
FormPtr frm;
UInt16 obj;
FieldPtr fld;
MemHandle h;
Char *p;
frm = FrmGetFormPtr(formID);
obj = FrmGetObjectIndex(frm, fieldID);
fld = FrmGetObjectPtr(frm, obj);
h = FldGetTextHandle(fld);
if (!h) {
h = MemHandleNew(FldGetMaxChars(fld) + 1);
ErrFatalDisplayIf(!h, "Out of memory");
}
p = MemHandleLock(h);
StrCopy(p, str);
MemHandleUnlock(h);
FldSetTextHandle(fld, h);
FldDrawField(fld);
}
static Err Connect(void)
{
Err error;
SrmOpenConfigType config;
char buf[3];
MemSet(&config, sizeof(config), 0);
error = SrmExtOpen(
sysFileCVirtRfComm,
&config,
sizeof(config),
&btPortId);
if (error) return error;
connected = true;
error = SrmReceiveFlush(btPortId, SysTicksPerSecond());
if (error) return error;
SrmSend(btPortId, " ", 1, &error);
if (error) return error;
error = SrmReceiveWait(btPortId, 2, SysTicksPerSecond());
if (error) return error;
SrmReceive(btPortId, buf, 2, 0, &error);
if (error) return error;
if (StrNCompare(buf, "OK", 2) != 0) return errNotWiTilt;
return errNone;
}
static Err Disconnect(void)
{
Err error;
SrmSend(btPortId, " ", 1, &error);
if (error) return error;
error = SrmClose(btPortId);
if (error) return error;
connected = false;
return errNone;
}
static Err ReceiveBytes(void)
{
Err error;
unsigned char buf[512];
UInt32 n;
UInt32 status;
UInt16 lineError;
char str[80];
SndCommandType cmd;
static UInt32 prevStatus = 0;
cmd.cmd = sndCmdFreqDurationAmp;
cmd.param2 = 50;
cmd.param3 = sndMaxAmp / 2;
error = SrmReceiveCheck(btPortId, &n);
if (error) {
SrmReceiveFlush(btPortId, 0);
return error;
}
n = SrmReceive(btPortId, buf, Min(n, sizeof (buf)), 0, &error);
if (error) {
SrmReceiveFlush(btPortId, 0);
return error;
}
error = SrmGetStatus(btPortId, &status, &lineError);
if (error) return error;
if (status != prevStatus) {
if (status & srmStatusCtsOn) {
SetField(MainForm, MainStatusCTS, "CTS on");
} else {
SetField(MainForm, MainStatusCTS, "CTS off");
}
if (status & srmStatusRtsOn) {
SetField(MainForm, MainStatusRTS, "RTS on");
} else {
SetField(MainForm, MainStatusRTS, "RTS off");
}
if (status & srmStatusDsrOn) {
SetField(MainForm, MainStatusDSR, "DSR on");
} else {
SetField(MainForm, MainStatusDSR, "DSR off");
}
if (status & srmStatusBreakSigOn) {
SetField(MainForm, MainStatusBreak, "Break on");
} else {
SetField(MainForm, MainStatusBreak, "Break off");
}
cmd.param1 = 880;
SndDoCmd(NULL, &cmd, false);
prevStatus = status;
}
if (lineError != 0) {
cmd.param1 = 440;
SndDoCmd(NULL, &cmd, false);
SrmReceiveFlush(btPortId, 0);
}
receiveCount++;
totalBytes += n;
StrPrintF(str, "%lu", receiveCount);
SetField(MainForm, MainCount, str);
StrPrintF(str, "%lu", totalBytes);
SetField(MainForm, MainTotalBytes, str);
return errNone;
}
static Boolean MainFormDoCommand(
UInt16 command)
{
Boolean handled = false;
FormType *pForm;
switch (command) {
case MainOptionsAboutStarterApp:
pForm = FrmInitForm(AboutForm);
FrmDoDialog(pForm);
FrmDeleteForm(pForm);
handled = true;
break;
}
return handled;
}
static Boolean MainFormHandleEvent(
EventType *pEvent)
{
Boolean handled = false;
FormType *pForm;
UInt16 obj;
ControlType *pCtrl;
Err error;
switch (pEvent->eType) {
case menuEvent:
return MainFormDoCommand(pEvent->data.menu.itemID);
case frmOpenEvent:
pForm = FrmGetActiveForm();
FrmDrawForm(pForm);
handled = true;
break;
case ctlSelectEvent:
if (pEvent->data.ctlEnter.controlID == MainConnect) {
pForm = FrmGetActiveForm();
obj = FrmGetObjectIndex(pForm, MainConnect);
pCtrl = FrmGetObjectPtr(pForm, obj);
if (connected) {
error = Disconnect();
if (!error) {
CtlSetLabel(pCtrl, "Start");
}
} else {
error = Connect();
if (!error) {
totalBytes = 0;
receiveCount = 0;
CtlSetLabel(pCtrl, "Stop");
} else {
Disconnect();
}
}
handled = true;
}
break;
default:
break;
}
return handled;
}
static Boolean AppHandleEvent(
EventType *pEvent)
{
UInt16 formId;
FormType *pForm;
Boolean handled = false;
switch (pEvent->eType) {
case frmLoadEvent:
formId = pEvent->data.frmLoad.formID;
pForm = FrmInitForm(formId);
FrmSetActiveForm(pForm);
switch (formId) {
case MainForm:
FrmSetEventHandler(pForm,
MainFormHandleEvent);
break;
default:
break;
}
handled = true;
break;
case nilEvent:
if (connected) {
ReceiveBytes();
}
handled = true;
break;
default:
break;
}
return handled;
}
static Err AppStart(void)
{
FrmGotoForm(MainForm);
return errNone;
}
static void AppStop(void)
{
FrmCloseAllForms();
}
static void AppEventLoop(void)
{
Err error;
EventType event;
do {
if (connected) {
EvtGetEvent(&event, 0);
EvtResetAutoOffTimer();
} else {
EvtGetEvent(&event, evtWaitForever);
}
if (SysHandleEvent(&event)) continue;
if (MenuHandleEvent(0, &event, &error)) continue;
if (AppHandleEvent(&event)) continue;
FrmDispatchEvent(&event);
} while (event.eType != appStopEvent);
}
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;
}