Read-only archive of the All About Symbian forum (2001–2013) · About this archive

Data Call (sening/recieving data)

2 replies · 7,652 views · Started 27 September 2004

Hi!

I have a few problem with sending/recieving data between two phones using a data call.

1) I can get the phones to connect and loan the port (RCall::LoanDataPort), however, on the phone that initiates the call it takes much loger... on the recieving one it takes no time at all, but on the other it takes more than 20 seconds to get to the same point! What am I missing?

2) After the call is established and I try to write data, nothing happens. I first do a NotifyDataAvailable on the recieving end and a Write followd by a NotifyOutputEmpty on the sendeing end. On the recieving end it stops at NotifyDataAvailable... no data arrives. On the sending end the write completes, but it then stops on NotifyOutputEmpty. I have no idea what`s wrong as I do as they do in all examples... (Note: I have tried without the Notify... on both sides with no luck).

What am I doing wrong? Do I need to configure something to make it work?
Thanks for any help!!! (and sorry for all the code!)

Parts of the code:

Code:

/* CDataCall.cpp */

User::LeaveIfError(iTelServer.Connect());
User::LeaveIfError(iTelServer.LoadPhoneModule(_L("erigsm"😉));
User::LeaveIfError(iTelServer.EnumeratePhones(iNbrOfPhones));
User::LeaveIfError(iTelServer.GetPhoneInfo(0,iPhoneInfo));
User::LeaveIfError(iPhone.Open(iTelServer,iPhoneInfo.iName));

TInt line;
if (GetLineL(RLine::KCapsData,line)) // found a data line
{
User::LeaveIfError(iPhone.GetLineInfo(line,iLineInfo));
User::LeaveIfError(iDataLine.Open(iPhone,iLineInfo.iName));
}
else User::InfoPrint(_L("Data call not supported..."😉);

iDataCallHandler = CDataCallHandler::NewL(&iDataLine, &iCall);

GetLineL(const TInt& capability, TInt& line)
{
TInt nbrOfLines = 0;
User::LeaveIfError(iPhone.EnumerateLines(nbrOfLines));

for (line = 0; line < nbrOfLines; line++)
{
User::LeaveIfError(iPhone.GetLineInfo(line,iLineInfo));
// Choose the first available line
if (static_cast<TInt>(iLineInfo.iLineCapsFlags) == capability)
break;
}
return line < nbrOfLines;
}

/* CDataCallHandler.cpp */
void CDataCallHandler::Connect(const TDesC& aNumber)
{
if (iState == EListeningForIncomingCall) // can we make a call?
{
Cancel(); // cancel any requests
//
// Create a new call and dial number
//
iState = EDiallingNumber;
User::LeaveIfError(iCall->OpenNewCall(*iLine));
iCall->Dial(iStatus,aNumber);
SetActive();
}
else User::InfoPrint(_L("Device busy"😉);
}

void CDataCallHandler::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CDataCallHandler::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EListeningForIncomingCall :
//
// Answer the incoming call
//
iState = EAnsweringCall;
iConnection = EIncomingCall;
User::LeaveIfError(iCall->OpenExistingCall(*iLine, iName));
iCall->AnswerIncomingCall(iStatus);
SetActive();
return; // leave method

case EDiallingNumber:
iConnection = EOutgoingCall;
// fall through to EAnsweringCall

case EAnsweringCall :
//
// Loan data port
//
iState = EGettingPort;
iCall->LoanDataPort(iStatus,iCommPortInfo);
SetActive();
return; // leave method

case EGettingPort :
//
// Start the server if necessary, connect to the comm
// server and load the comm module
//
StartC32();
User::LeaveIfError(iCommServer.Connect());
User::LeaveIfError(iCommServer.LoadCommModule(
iCommPortInfo.iCsy));

//
// Open communication
//
iState = EOpeningPort;
iCommPort.OpenWhenAvailable(iStatus,iCommServer,
iCommPortInfo.iPort);
SetActive();
return; // leave method

case EOpeningPort :
//
// Will complete when the current handshaking configuration
// and the state of input control lines would allow any data
// to be immediately written to the serial line.
//
iCommPort.Write(iStatus,iDummy,0);
User::WaitForRequest(iStatus);
User::InfoPrint(_L("Connected"😉); // ****

//
// Read/send data
//
if (iConnection == EIncomingCall) iCommReader->ReadData();
else iCommWriter->WriteData();

//
// Listen for hook change
//
iState = EListeningForHookChange;
iLine->NotifyHookChange(iStatus, iHookStatus);
SetActive();
return; // leave method

case EListeningForHookChange : // listening for hook change
if (!iHookStatus == RCall::EHookStatusOn) // still connected
{
//
// Re-issue request
//
iLine->NotifyHookChange(iStatus, iHookStatus);
SetActive();
return; // leave method
}
// fall through to EHangingUp

case EHangingUp :
break; // release resources and Listen for incoming calls
}

//
// Stop reading sending data, release resources and listen for
// incoming calls
//
User::InfoPrint(_L("Disconnected"😉); // ****
iState = EListeningForIncomingCall;
CancelPendingRequests();
ReleaseResources();
iLine->NotifyIncomingCall(iStatus, iName);
SetActive();
}


//
// Request failed eg. failed to dail the number
//
else
{
User::InfoPrint(_L("DataCallHandler couldn`t complete request..."😉);
Disconnect();
}
}

/* CCommReader.cpp */
void CCommReader::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CCommReader::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EWaitingForData :
User::InfoPrint(_L("Reading data..."😉);
iState = EReadingData;
iCommPort->Read(iStatus,iData);
SetActive();
break;

case EReadingData :
User::InfoPrint(_L("Data read, waiting for data..."😉);
iState = EWaitingForData;
iCommPort->NotifyDataAvailable(iStatus);
SetActive();
break;
}
}

//
// Request failed eg. failed to dail the number
//
else
{
User::InfoPrint(_L("CommReader couldn`t complete request..."😉);
}
}

/* CCommWriter.cpp */
void CCommWriter::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CCommWriter::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EWritingData :
User::InfoPrint(_L("Data written, waiting for transmit..."😉);
iState = EWaitingForTransmit;
iCommPort->NotifyOutputEmpty(iStatus);
SetActive();
break;

case EWaitingForTransmit :
User::InfoPrint(_L("Writing data..."😉);
iState = EWritingData;
iCommPort->Write(iStatus,KDataToWrite);
SetActive();
break;

}
}
//
// Request failed eg. failed to dail the number
//
else
{
User::InfoPrint(_L("CommWriter couldn't complete request..."😉);
}
}

That was me by the way, and I really need help! :frown: I know it is possible, since there'a an app out there that does it...

Making the code easier to read:

/* CDataCall.cpp */

User::LeaveIfError(iTelServer.Connect());
User::LeaveIfError(iTelServer.LoadPhoneModule(_L("erigsm"😉));
User::LeaveIfError(iTelServer.EnumeratePhones(iNbrOfPhones));
User::LeaveIfError(iTelServer.GetPhoneInfo(0,iPhoneInfo));
User::LeaveIfError(iPhone.Open(iTelServer,iPhoneInfo.iName));

TInt line;
if (GetLineL(RLine::KCapsData,line)) // found a data line
{
User::LeaveIfError(iPhone.GetLineInfo(line,iLineInfo));
User::LeaveIfError(iDataLine.Open(iPhone,iLineInfo.iName));
}
else User::InfoPrint(_L("Data call not supported..."😉);

iDataCallHandler = CDataCallHandler::NewL(&iDataLine, &iCall);

GetLineL(const TInt& capability, TInt& line)
{
TInt nbrOfLines = 0;
User::LeaveIfError(iPhone.EnumerateLines(nbrOfLines));

for (line = 0; line < nbrOfLines; line++)
{
User::LeaveIfError(iPhone.GetLineInfo(line,iLineInfo));
// Choose the first available line
if (static_cast<TInt>(iLineInfo.iLineCapsFlags) == capability)
break;
}
return line < nbrOfLines;
}

/* CDataCallHandler.cpp */
void CDataCallHandler::Connect(const TDesC& aNumber)
{
if (iState == EListeningForIncomingCall) // can we make a call?
{
Cancel(); // cancel any requests
//
// Create a new call and dial number
//
iState = EDiallingNumber;
User::LeaveIfError(iCall->OpenNewCall(*iLine));
iCall->Dial(iStatus,aNumber);
SetActive();
}
else User::InfoPrint(_L("Device busy"😉);
}

void CDataCallHandler::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CDataCallHandler::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EListeningForIncomingCall :
//
// Answer the incoming call
//
iState = EAnsweringCall;
iConnection = EIncomingCall;
User::LeaveIfError(iCall->OpenExistingCall(*iLine, iName));
iCall->AnswerIncomingCall(iStatus);
SetActive();
return; // leave method

case EDiallingNumber:
iConnection = EOutgoingCall;
// fall through to EAnsweringCall

case EAnsweringCall :
//
// Loan data port
//
iState = EGettingPort;
iCall->LoanDataPort(iStatus,iCommPortInfo);
SetActive();
return; // leave method

case EGettingPort :
//
// Start the server if necessary, connect to the comm
// server and load the comm module
//
StartC32();
User::LeaveIfError(iCommServer.Connect());
User::LeaveIfError(iCommServer.LoadCommModule(
iCommPortInfo.iCsy));

//
// Open communication
//
iState = EOpeningPort;
iCommPort.OpenWhenAvailable(iStatus,iCommServer,
iCommPortInfo.iPort);
SetActive();
return; // leave method

case EOpeningPort :
//
// Will complete when the current handshaking configuration
// and the state of input control lines would allow any data
// to be immediately written to the serial line.
//
iCommPort.Write(iStatus,iDummy,0);
User::WaitForRequest(iStatus);
User::InfoPrint(_L("Connected"😉); // ****

//
// Read/send data
//
if (iConnection == EIncomingCall) iCommReader->ReadData();
else iCommWriter->WriteData();

//
// Listen for hook change
//
iState = EListeningForHookChange;
iLine->NotifyHookChange(iStatus, iHookStatus);
SetActive();
return; // leave method

case EListeningForHookChange : // listening for hook change
if (!iHookStatus == RCall::EHookStatusOn) // still connected
{
//
// Re-issue request
//
iLine->NotifyHookChange(iStatus, iHookStatus);
SetActive();
return; // leave method
}
// fall through to EHangingUp

case EHangingUp :
break; // release resources and Listen for incoming calls
}

//
// Stop reading sending data, release resources and listen for
// incoming calls
//
User::InfoPrint(_L("Disconnected"😉); // ****
iState = EListeningForIncomingCall;
CancelPendingRequests();
ReleaseResources();
iLine->NotifyIncomingCall(iStatus, iName);
SetActive();
}


//
// Request failed eg. failed to dail the number
//
else
{
User::InfoPrint(_L("DataCallHandler couldn`t complete request..."😉);
Disconnect();
}
}

/* CCommReader.cpp */
void CCommReader::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CCommReader::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EWaitingForData :
User::InfoPrint(_L("Reading data..."😉);
iState = EReadingData;
iCommPort->Read(iStatus,iData);
SetActive();
break;

case EReadingData :
User::InfoPrint(_L("Data read, waiting for data..."😉);
iState = EWaitingForData;
iCommPort->NotifyDataAvailable(iStatus);
SetActive();
break;
}
}

//
// Request failed eg. failed to dail the number
//
else
{
User::InfoPrint(_L("CommReader couldn`t complete request..."😉);
}
}

/* CCommWriter.cpp */
void CCommWriter::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CCommWriter::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EWritingData :
User::InfoPrint(_L("Data written, waiting for transmit..."😉);
iState = EWaitingForTransmit;
iCommPort->NotifyOutputEmpty(iStatus);
SetActive();
break;

case EWaitingForTransmit :
User::InfoPrint(_L("Writing data..."😉);
iState = EWritingData;
iCommPort->Write(iStatus,KDataToWrite);
SetActive();
break;

}
}
//
// Request failed eg. failed to dail the number
//
else
{
User::InfoPrint(_L("CommWriter couldn't complete request..."😉);
}
}

Ok, I've pinned down the problem, and it has nothing to do with RComm::Write but with the way I answer the incoming data call... setting up the call fails for some reason, and thats why I have problem 1:

1) I can get the phones to connect and loan the port (RCall::LoanDataPort), however, on the phone that initiates the call it takes much loger... on the recieving one it takes no time at all, but on the other it takes more than 20 seconds to get to the same point! What am I missing?

What am I missing?


void CDataCallHandler::RunL()
{
__ASSERT_ALWAYS(!IsActive(),
User::InfoPrint(_L("ERROR - CDataCallHandler::IsActive"😉));

//
// Request succeded
//
if (iStatus == KErrNone)
{
switch (iState)
{
case EListeningForIncomingCall :
//
// Answer the incoming call
//
iState = EAnsweringCall;
iConnection = EIncomingCall;
User::LeaveIfError(iCall->OpenExistingCall(*iLine, iName));
iCall->AnswerIncomingCall(iStatus);
SetActive();
return; // leave method

case EDiallingNumber:
iConnection = EOutgoingCall;
// fall through to EAnsweringCall

case EAnsweringCall :
//
// Loan data port
//
iState = EGettingPort;
iCall->LoanDataPort(iStatus,iCommPortInfo);
SetActive();
return; // leave method

...