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;
}

Reply via email to