javaextensions/comm/src.s60/nativecommconnection.cpp
changeset 21 2a9601315dfc
child 87 1627c337e51e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/comm/src.s60/nativecommconnection.cpp	Mon May 03 12:27:20 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;
+}
+