--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/comm/src.s60/nativecommconnection.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,606 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: ?Description
+ *
+*/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <usbman.h>
+#include <acminterface.h>
+#include "logger.h"
+#include "javacommonutils.h"
+#include "s60commonutils.h"
+#include "com_nokia_mj_impl_comm_CommConnectionImpl.h"
+#include "nativecommconnection.h"
+#include "fs_methodcall.h"
+
+
+#if defined (__WINS__)
+_LIT(PDD_NAME,"ECDRV");
+_LIT(LDD_NAME,"ECOMM");
+#else
+_LIT(PDD_NAME, "EUART1");
+_LIT(LDD_NAME, "ECOMM");
+#endif
+
+_LIT(KSymbianIRComm1, "IRComm");
+_LIT(KSymbianIRComm2, "IRCOMM");
+_LIT(KSymbianComm,"COMM");
+_LIT(KSymbianAcm,"ACM");
+_LIT(KSymbianBTComm1,"BTComm");
+_LIT(KSymbianBTComm2,"BTCOMM");
+_LIT(KSymbianECUART,"ECUART");
+
+enum TCOMMOPTIONSINDEX
+{
+ ECommBaudRateIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_BAUDRATE_INDEX,
+
+ ECommBitsPerCharIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_BITSPERCHAR_INDEX,
+
+ ECommStopBitsIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_STOPBITS_INDEX,
+
+ ECommParityIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_PARITY_INDEX,
+
+ ECommBlockingIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_BLOCKING_INDEX,
+
+ ECommAutoRtsIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_AUTORTS_INDEX,
+
+ ECommAutoCtsIndex = com_nokia_mj_impl_comm_CommConnectionImpl_COMM_AUTOCTS_INDEX
+};
+
+using namespace java::util;
+using namespace java::comm;
+
+NativeCommConnection::NativeCommConnection(FunctionServer *aFuncServ) : mConnectionIsOpen(false),mInternalBuf(NULL),mInternalBuflength(0)
+{
+ JELOG2(ESOCKET);
+ iFuncServ = aFuncServ;
+ mPortNames.insert(TPair("IR", "IRComm"));
+ mPortNames.insert(TPair("USB", "ACM"));
+ mPortNames.insert(TPair("COM", "COMM"));
+ mPortNames.insert(TPair("BT", "BTComm"));
+ mReadInProgress = false;
+ mWriteInProgress = false;
+}
+
+NativeCommConnection::~NativeCommConnection()
+{
+ JELOG2(ESOCKET);
+
+}
+
+int NativeCommConnection::doGetBaudRate()
+{
+ JELOG2(ESOCKET);
+ if (mConnectionIsOpen == false)
+ return -1;
+ return TBpsToTInt(mCommConfig.iRate);
+
+}
+int NativeCommConnection::getBaudRate()
+{
+ JELOG2(ESOCKET);
+ int rate = 0;
+ CallMethod(rate,this, &NativeCommConnection::doGetBaudRate,iFuncServ);
+ ILOG1(ESOCKET, "NativeCommConnection::getBaudRate(), returning %d",rate);
+ return rate;
+
+}
+
+int NativeCommConnection::doSetBaudRate(const int aBaudRate)
+{
+ JELOG2(ESOCKET);
+ int oldvalue = doGetBaudRate();
+ TBps tmpRate = mCommConfig.iRate; // store the old rate, in case the setConfig fails, restore back this old one
+
+ mCommConfig.iRate = TIntToTBps(aBaudRate);
+ TCommConfig configBuf;
+ TCommConfigV01& configRef = configBuf();
+ configRef = mCommConfig;
+ int ret = mComm.SetConfig(configBuf);
+ if (ret < 0)
+ {
+ ELOG1(ESOCKET, "NativeCommConnection::doSetBaudRate(), setConfig failed for input %d",aBaudRate);
+ /* value provided in aBaudRate is not supported, so restore back the old one */
+ mCommConfig.iRate = tmpRate;
+ }
+ return oldvalue;
+}
+
+int NativeCommConnection::setBaudRate(const int aBaudRate)
+{
+ int oldRate = 0;
+ CallMethod(oldRate,this, &NativeCommConnection::doSetBaudRate,aBaudRate,iFuncServ);
+ return oldRate;
+}
+
+int NativeCommConnection::writeBytes(JNIEnv& aJni, jbyteArray aJavaBuffer,
+ int aOffset, int aLength)
+{
+ JELOG2(ESOCKET);
+ TBuf8<512> writeBuffer;
+ int ret = S60CommonUtils::CopyToNative(aJni, aJavaBuffer, aOffset, aLength,
+ writeBuffer);
+ ILOG(ESOCKET, "NativeCommConnection::writeBytes(), copy to native completed");
+
+ //TDesC8 tmp = writeBuffer.
+ int handle = reinterpret_cast<int>(this);
+ int bufhandle = reinterpret_cast<int>(&writeBuffer);
+
+
+ //TRequestStatus status;
+ // mComm.Write(status, writeBuffer);
+ // User::WaitForRequest(status);
+
+ int retValue = 0;
+ CallMethod(retValue,this, &NativeCommConnection::doWrite,handle,bufhandle,iFuncServ);
+
+ if (retValue != KErrNone)
+ {
+ ELOG1(ESOCKET, "NativeCommConnection::writeBytes() failed, status = %d",retValue);
+ return retValue;
+ }
+ else
+ {
+ int tmp = writeBuffer.Length();
+ return aLength;
+ }
+
+}
+
+
+int NativeCommConnection::doWrite(int aNativeCommConnectionHandle, int aBufferHandle)
+{
+ JELOG2(ESOCKET);
+ mWriteInProgress = true;
+ NativeCommConnection *nativeObj = reinterpret_cast<NativeCommConnection*>(aNativeCommConnectionHandle);
+ //TBuf8<512> writeBuffer = reinterpret_cast<TBuf8<512>>(aBufferHandle);
+ TDesC8* writeBuffer = reinterpret_cast<TDesC8*>(aBufferHandle);
+ TBuf8<512> tmp;
+
+ TRequestStatus status;
+ nativeObj->mComm.Write(status,*writeBuffer);
+ User::WaitForRequest(status);
+ ILOG1(ESOCKET, "NativeCommConnection::doWrite(), status = %d",status.Int());
+ return status.Int();
+}
+
+int NativeCommConnection::doRead(JNIEnv& aJni, jbyteArray aJavaBuffer)
+{
+ JELOG2(ESOCKET);
+
+ if (mInternalBuf!=NULL)
+ {
+ TPtrC8 tmpPtr(mInternalBuf->Des());
+ /* available was called before read, so copy the data already read, which is store in internal buffer */
+ S60CommonUtils::CopyToJava(aJni, tmpPtr, aJavaBuffer, 0,
+ mInternalBuflength);
+ mInternalBuf = NULL;
+ ILOG1(ESOCKET, "--NativeCommConnection::doRead(), copied from internal buffer ,len = %d",mInternalBuflength);
+ return mInternalBuflength;
+ }
+
+ mReadInProgress = true;
+ ILOG(ESOCKET, "NativeCommConnection::doRead(), continuing");
+ TRequestStatus status;
+ TBuf8<512> readBuffer;
+ mComm.ReadOneOrMore(status, readBuffer); // block until at least 1 byte of data is read
+ User::WaitForRequest(status);
+ int length = readBuffer.Length();
+ TPtrC8 receiveBufferPtr = readBuffer.Ptr();
+
+
+ if (status.Int() == KErrNone)
+ {
+
+ S60CommonUtils::CopyToJava(aJni, readBuffer, aJavaBuffer, 0,
+ length);
+ }
+ if (status.Int() != KErrNone)
+ {
+ return status.Int(); // error code
+ }
+ else
+ {
+ ILOG1(ESOCKET, "NativeCommConnection::doRead(), read successfully, length = %d",length);
+ return length;
+ }
+
+}
+
+int NativeCommConnection::readBytes(JNIEnv& aJni, jbyteArray aJavaBuffer)
+{
+ JELOG2(ESOCKET);
+ int ret = 0;
+ CallMethod(ret,this,&NativeCommConnection::doRead,aJni,aJavaBuffer,iFuncServ);
+ return ret;
+}
+
+void NativeCommConnection::initializePortSettings(int *aNumericOptions)
+{
+ JELOG2(ESOCKET);
+ // mCommConfig holds the current configuration, update it with new values
+ TParity parity;
+ if (aNumericOptions[ECommParityIndex] == 1)
+ {
+ parity = EParityOdd;
+ mCommConfig.iParity = parity;
+ }
+ else if (aNumericOptions[ECommParityIndex] == 2)
+ {
+ parity = EParityEven;
+ mCommConfig.iParity = parity;
+ }
+
+ if (aNumericOptions[ECommAutoCtsIndex] == 1)
+ mCommConfig.iHandshake |= KConfigObeyCTS; // option: autocts
+ else
+ mCommConfig.iHandshake &= ~KConfigObeyCTS;
+
+ if (aNumericOptions[ECommAutoRtsIndex] == 1)
+ mCommConfig.iHandshake |= KConfigFreeRTS; // option: autorts
+ else
+ mCommConfig.iHandshake &= ~KConfigFreeRTS;
+
+ if (aNumericOptions[ECommBaudRateIndex] != -1)
+ doSetBaudRate(aNumericOptions[ECommBaudRateIndex]); // option: baudrate
+
+ if (aNumericOptions[ECommBitsPerCharIndex] == 7)
+ mCommConfig.iDataBits = EData7; // option: bitsperchar
+ else
+ mCommConfig.iDataBits = EData8;
+
+ if (aNumericOptions[ECommStopBitsIndex] == 1)
+ mCommConfig.iStopBits = EStop1; // option: stopbits
+ else
+ mCommConfig.iStopBits = EStop2;
+
+ TCommConfig configBuf1;
+ TCommConfigV01& configRef = configBuf1();
+ configRef = mCommConfig;
+ mComm.SetConfig(configBuf1); // set the new configuration
+
+}
+
+std::basic_string<char> NativeCommConnection::mapToSymbianPortName(
+ const std::string aJavaPortName)
+{
+ JELOG2(ESOCKET);
+ std::map<std::string, std::string>::iterator itr = mPortNames.find(
+ aJavaPortName);
+ if (itr != mPortNames.end())
+ {
+ return itr->second; // take the value string <name,value>
+ }
+ return NULL;
+}
+
+int NativeCommConnection::openPortConnection(std::string aJavaPortName, int aPortNumber, int *aNumericOptions)
+{
+ int ret = 0;
+ CallMethod(ret,this,&NativeCommConnection::openCommPortConnection,aJavaPortName,aPortNumber,aNumericOptions,iFuncServ);
+ return ret;
+}
+
+int NativeCommConnection::openCommPortConnection(
+ const std::string aJavaPortName, int aPortNumber, int *aNumericOptions)
+{
+ JELOG2(ESOCKET);
+ mNativePortName = mapToSymbianPortName(aJavaPortName);
+ int ret = connectToCommServer();
+ if (ret != KErrNone)
+ {
+ return ret; // error occurred
+ }
+
+ // RComm.Open() takes the argument port id in the form "IR::0" (or) "ACM::1" ,...
+ // The java port number always starts from 1( MIDP spec).
+ // So convert this java port number to actual native port number using the base index stored previously.
+
+ std::basic_string<char> prtname;
+ char portNumberString[50];
+ sprintf(portNumberString, "%d", (aPortNumber + mPortLowIndex) - 1);
+ prtname = mNativePortName + "::" + portNumberString;
+
+ /* convert from string to TBuf16 */
+ TBuf8<50> portNameUTF;
+ TBuf16<50> portname;
+ TPtrC8 portNamePtr((TText8*) prtname.c_str());
+ portNameUTF.Copy(portNamePtr);
+ portname.Copy(portNameUTF); // convert from TBuf8 to TBuf16, because RCommServer.open() accepts only TDesc16 type
+
+ char* t5 = (char *)prtname.c_str();
+
+ ret = mComm.Open(mCommServer, portname, ECommExclusive);
+ if (ret == KErrNone)
+ {
+ ILOG(ESOCKET, "openCommPortConnection() success");
+ mConnectionIsOpen = true;
+ TCommConfig cBuf;
+ TCommConfigV01& c = cBuf();
+ mComm.Config(cBuf);
+ mCommConfig = c;
+ initializePortSettings(aNumericOptions);
+ }
+ ELOG1(ESOCKET, "--NativeCommConnection::openCommPortConnection()",2);
+ return ret;
+}
+
+void NativeCommConnection::doOpenConnnection(int portNameHandle)
+{
+ JELOG2(ESOCKET);
+ char *t2 = reinterpret_cast<char*>(portNameHandle);
+ TBuf8<50> portNameUTF;
+ TBuf16<50> portname;
+ TPtrC8 portNamePtr((TText8*) t2);
+ portNameUTF.Copy(portNamePtr);
+ portname.Copy(portNameUTF);
+
+
+ int rc = mComm.Open(mCommServer, portname, ECommExclusive);
+ if (rc != KErrNone)
+ {
+ ELOG1(ESOCKET, "NativeCommConnection open failed: %d", rc);
+ }
+}
+
+void NativeCommConnection::doStopReading()
+{
+ mComm.ReadCancel(); // cancel the read
+ mReadInProgress = false;
+ if (!mWriteInProgress)
+ {
+ ILOG(ESOCKET, "++NativeCommConnection::doStopReading(), releasing the connection");
+ /* if there is no write going on, then release the comm port */
+ mComm.Close();
+ mCommServer.Close();
+ mConnectionIsOpen = false;
+ }
+}
+
+void NativeCommConnection::stopReading()
+{
+ JELOG2(ESOCKET);
+ CallMethod(this, &NativeCommConnection::doStopReading,iFuncServ);
+ // cancel any pending read operation
+}
+
+void NativeCommConnection::doStopWriting()
+{
+ mComm.WriteCancel();
+ mWriteInProgress = false;
+}
+
+void NativeCommConnection::stopWriting()
+{
+ // cancel any pending write operation
+ JELOG2(ESOCKET);
+ CallMethod(this, &NativeCommConnection::doStopWriting,iFuncServ);
+}
+
+int NativeCommConnection::doAvailable()
+{
+ TRequestStatus status;
+ TBuf8<512> readBuffer;
+ mComm.ReadOneOrMore(status, readBuffer); // block until at least 1 byte of data is read
+ User::WaitForRequest(status);
+ int length = readBuffer.Length();
+ TPtrC8 receiveBufferPtr = readBuffer.Ptr();
+ if (status.Int() == KErrNone)
+ {
+ TRAPD(err,mInternalBuf = HBufC8::NewL(length));
+ if (err < 0)
+ {
+ return err;
+ }
+ TPtr8 tmpPtr(mInternalBuf->Des());
+ tmpPtr.Copy(readBuffer);
+ mInternalBuflength = length;
+ return length;
+ }
+ else
+ return 0;
+
+}
+
+int NativeCommConnection::available()
+{
+ JELOG2(ESOCKET);
+ int ret;
+ CallMethod(ret,this, &NativeCommConnection::doAvailable,iFuncServ);
+ ILOG1(ESOCKET, "NativeCommConnection::available(), returning %d",ret);
+ return ret;
+}
+
+int NativeCommConnection::connectToCommServer()
+{
+ JELOG2(ESOCKET);
+ int ret = 0;
+ User::LoadPhysicalDevice(PDD_NAME); // load physical device drivers
+ User::LoadLogicalDevice(LDD_NAME); // load logical device drivers
+
+ ret = mCommServer.Connect();
+ if (ret != KErrNone)
+ return -ret;
+
+ /* convert from std::string * to TBuf16 */
+ TBuf8<50> portNameUTF;
+ TBuf16<50> portname;
+ TPtrC8 portNamePtr((TText8*) mNativePortName.c_str()); // covert c-style char* to symbian specific TPtr8
+ portNameUTF.Copy(portNamePtr);
+ portname.Copy(portNameUTF);
+
+ /* Load the comm module corresponding to the name */
+ if (portname.Match(KSymbianIRComm1) != KErrNotFound)
+ ret = mCommServer.LoadCommModule(KSymbianIRComm2);
+ else if (portname.Match(KSymbianComm) != KErrNotFound)
+ ret = mCommServer.LoadCommModule(KSymbianECUART);
+ else if (portname.Match(KSymbianBTComm1) != KErrNotFound)
+ ret = mCommServer.LoadCommModule(KSymbianBTComm2);
+ else if (portname.Match(KSymbianAcm) != KErrNotFound)
+ ret = mCommServer.LoadCommModule(KAcmCsyName);
+
+ if (ret != KErrNone)
+ return ret;
+
+ // Get base offsets of specified port.
+ TSerialInfo info;
+ ret = mCommServer.GetPortInfo(portname, info);
+ if (ret == KErrNone)
+ mPortLowIndex = info.iLowUnit;
+
+ ILOG1(ESOCKET, "NativeCommConnection::Lowunit = %d", mPortLowIndex);
+
+ return ret;
+}
+
+void NativeCommConnection::doClose()
+{
+ JELOG2(ESOCKET);
+ if (mConnectionIsOpen != false)
+ {
+ mComm.Close();
+ mCommServer.Close();
+ mConnectionIsOpen = false;
+ }
+}
+
+void NativeCommConnection::close()
+{
+ CallMethod(this, &NativeCommConnection::doClose,iFuncServ);
+
+}
+
+// convert a baud rate passed as a TBps into an integer,
+int NativeCommConnection::TBpsToTInt(TBps aRate)
+{
+ JELOG2(ESOCKET);
+ switch (aRate)
+ {
+ case EBps50:
+ return 50;
+ case EBps75:
+ return 75;
+ case EBps110:
+ return 110;
+ case EBps134:
+ return 134;
+ case EBps150:
+ return 150;
+ case EBps300:
+ return 300;
+ case EBps600:
+ return 600;
+ case EBps1200:
+ return 1200;
+ case EBps1800:
+ return 1800;
+ case EBps2000:
+ return 2000;
+ case EBps2400:
+ return 2400;
+ case EBps3600:
+ return 3600;
+ case EBps4800:
+ return 4800;
+ case EBps7200:
+ return 7200;
+ case EBps9600:
+ return 9600;
+ case EBps19200:
+ return 19200;
+ case EBps38400:
+ return 38400;
+ case EBps57600:
+ return 57600;
+ case EBps115200:
+ return 115200;
+ case EBps230400:
+ return 230400;
+ case EBps460800:
+ return 460800;
+ case EBps576000:
+ return 576000;
+ case EBps1152000:
+ return 1152000;
+ case EBps4000000:
+ return 4000000;
+ case EBps921600:
+ return 921600;
+ default:
+ return -1;
+ }
+}
+
+// convert a baud rate passed as an int into a TBps enum value,
+// rates are rounded down to the next rate, anything less than 75 is set to 50
+TBps NativeCommConnection::TIntToTBps(const TInt aRate)
+{
+ JELOG2(ESOCKET);
+ if (aRate > 4000000)
+ return EBpsSpecial;
+ if (aRate == 4000000)
+ return EBps4000000;
+ if (aRate >= 1152000)
+ return EBps1152000;
+ if (aRate >= 921600)
+ return EBps921600;
+ if (aRate >= 576000)
+ return EBps576000;
+ if (aRate >= 460800)
+ return EBps460800;
+ if (aRate >= 230400)
+ return EBps230400;
+ if (aRate >= 115200)
+ return EBps115200;
+ if (aRate >= 57600)
+ return EBps57600;
+ if (aRate >= 38400)
+ return EBps38400;
+ if (aRate >= 19200)
+ return EBps19200;
+ if (aRate >= 9600)
+ return EBps9600;
+ if (aRate >= 7200)
+ return EBps7200;
+ if (aRate >= 4800)
+ return EBps4800;
+ if (aRate >= 3600)
+ return EBps3600;
+ if (aRate >= 2400)
+ return EBps2400;
+ if (aRate >= 2000)
+ return EBps2000;
+ if (aRate >= 1800)
+ return EBps1800;
+ if (aRate >= 1200)
+ return EBps1200;
+ if (aRate >= 600)
+ return EBps600;
+ if (aRate >= 300)
+ return EBps300;
+ if (aRate >= 150)
+ return EBps150;
+ if (aRate >= 134)
+ return EBps134;
+ if (aRate >= 110)
+ return EBps110;
+ if (aRate >= 75)
+ return EBps75;
+ return EBps50;
+}
+