serialserver/c32serialserver/CCOMM/CC_CLI.CPP
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serialserver/c32serialserver/CCOMM/CC_CLI.CPP	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,1675 @@
+// Copyright (c) 1997-2009 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:
+//
+
+#include <e32std.h>
+#include <c32comm.h>
+#include <e32panic.h>
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <c32comm_internal.h>
+#endif
+
+#include "CS_STD.H"
+#include "C32LOG.H"
+
+/** @file
+ *
+ * Implements the client side code of C32, including RCommServ and RComm
+ */
+
+
+const TUint KDefaultMessageSlots = 16;    //< number of slots in the Client/Server message buffer
+
+
+//
+// implementation of RCommServ
+//
+
+
+EXPORT_C RCommServ::RCommServ()
+/** Default constructor. 
+@capability None
+*/
+	{
+	}
+
+
+EXPORT_C TInt RCommServ::Connect()
+/** Connects a client process to the comms server.
+
+Use this function to open a session to the Comms server.
+Default number of message slots is defined in KDefaultMessageSlots.
+
+Notes:
+
+1. RHandleBase 
+   provides the necessary Close() function, which should be called when the server 
+   session is no longer required. Note that the kernel completes the Close() function immediately
+   and so RCommServ resources still used by this client may not yet have been released at the time
+   the Close() returns. A consequence of this is that an attempt to open a port previously opened
+   for exclusive use in a session that is still closing might fail.
+2. Older versions of Symbian OS specified that a call to "StartC32" was required before a call to
+   this Connect(). However, C32 Serial server is now started automatically during device boot
+   so this is not necessary unless the application is to run in a non-standard GUI environment.
+
+
+@return System-wide error code 
+@capability None
+*/
+    {
+    TInt r = CreateSession(KCommServerName(), Version(), KDefaultMessageSlots);
+	if (r==KErrNotFound)
+		{
+		// attempt to start the comms system. This is normally done on device boot but to support
+		// any old test environments we still try here as well. This is a deprecated behaviour that
+		// results in warnings in the log file
+		r = StartC32();
+		if (r==KErrNone)
+			r=CreateSession(KCommServerName(), Version(), KDefaultMessageSlots);
+		}
+    return(r); 
+    }
+
+
+EXPORT_C TVersion RCommServ::Version() const
+/** Returns the client side version number.
+
+Use this function to get the version number. The version number may be
+incremented in future releases of the comms server. If extra features are
+added in such releases, the version number may be used by application programs
+as a basis for assessing the capabilities of the comms server. Version-specific
+functions will be marked as such in the SDK documentation.
+
+@return Version number. 
+@capability None
+*/
+    {
+    return(TVersion(KEC32MajorVersionNumber, KEC32MinorVersionNumber, KEC32BuildVersionNumber));
+    }
+
+EXPORT_C TInt RCommServ::LoadCommModule(const TDesC& aFileName)
+/** Loads a comms module.
+
+Use this function to load a CSY comms module. These are protocol modules that C32 Serial Server uses to
+understand how to handle a particular port.
+
+Notes:
+
+1. There is no need for an extension, as ".CSY" is automatically appended by 
+   this function.
+
+2. This function only loads CSYs that have been installed correctly into one of the system's /sys/bin directories
+   
+3. If the module has already been loaded by another client, this function will increment
+   the reference to the module.
+   
+4. It is not an error to load the same module twice or more, although there is no practical
+   application for this ability. On each subsequent load for the same module the reference count
+   is simply incremented. When the session is closed, all module references are removed including
+   references from repeated loading of the same module.
+   
+5. There is no limit to the number of modules that can be loaded from within a single session.
+
+With the exception of some hardware configurations, four modules are normally available as standard:
+
+  ECUART is used to address appropriate serial ports in RS232 mode. It is normally customised for a device.
+
+  IRCOMM drives the infrared port in infrared mode.
+ 
+  BTCOMM drives the Bluetooth emulated serial port.
+  
+  ECACM drives the USB port(s).
+
+@param aFileName Name of the file to load as a module, optionally containing the ".CSY" extension.
+The filename may include the full path including drive letter for the CSY.
+@return KErrNone if the load operation is successful; KErrServerTerminated if the server no longer present;
+ KErrServerBusy if there are no message slots available; KErrNoMemory if there is insufficient memory available;
+ KErrBadLibraryEntryPoint if the CSY fails the consistency check; KErrNotFound if the CSY or other component
+ or service required to load it is not found; other return codes are possible from the CSY itself.
+@capability None
+*/
+    {
+    // No means to insert a 16-bit string into an 8-bit string, so all is 16-bit
+	C32_STATIC_LOG2(KC32Client,_L("RCommServ::LoadCommModule() : %S"), &aFileName);
+
+	TIpcArgs args(&aFileName);
+	return SendReceive(ECommLoadCommModule, args);
+    }
+
+
+EXPORT_C TInt RCommServ::UnloadCommModule(const TDesC& aName)
+/** Remove this client's reference to the named communications module. If this is the
+last client to reference the communications module, the module is unloaded.
+
+Note:
+
+There is no need to unload a comms module when the connection to the
+server is closed, as this is done automatically by the C32 Server. For example, the following code will not result in a leak:
+@code
+		_LIT(KCSYName,"ECUART");
+		RCommServ commSession;
+		if (commSession.Connect() == KErrNone)
+			{
+			TInt ret = commSession.LoadCommModule(KCSYName);
+			commSession.Close();
+			}
+@endcode
+
+@param aName Name of the module to unload described in Port Prefix format. This may not necessarily be
+the same name as that used to load the module.
+Examples:
+The ECUART module, where supplied, is loaded via "ECUART" or "ECUART.CSY" but unloaded via "COMM".
+The infrared module, where supplied, is loaded via "IRCOMM.CSY" or "IRCOMM" but unloaded only via "IRCOMM".
+@return System wide error code.
+
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L("RCommServ::UnloadCommModule() : %S"), &aName);
+	
+	TIpcArgs args(&aName);
+	return SendReceive(ECommCloseCommModule, args);
+    }
+
+
+EXPORT_C TInt RCommServ::NumPorts(TInt& aCount)
+/** Get the number of unique comms modules (CSYs) loaded into C32.
+
+This number includes modules loaded by other sessions.
+
+@param aCount On return, holds the number of loaded CSYs
+@return System wide error code. 
+@capability None
+*/
+    {
+	TPckg<TInt> num(aCount);
+	TIpcArgs args(&num);
+	return SendReceive(ECommNumPorts,args);
+    }
+
+
+EXPORT_C TInt RCommServ::GetPortInfo(const TDesC& aName, TSerialInfo& aInfo)
+/** Gets static information about the available serial ports for a particular comms module.
+
+This variant enables the comms module to be specified in Port Prefix format or by filename. 
+
+There is no wildcard support.
+
+Notes:
+
+1. This API only returns static information about the available ports as they were when the module loaded, so
+ports listed as available may actually be in use exclusively by another client at the time of this call.
+
+2. The information returned does not account for any security restrictions on ports, and so does not check
+whether the client has the capabilities to open all the advertised ports.
+
+@param aName The name of the comms module in Port Prefix format (eg "COMM" for RS232), 
+or the filename of the CSY as supplied to LoadCommModule() excluding
+ the ".CSY" extension (eg "ECUART" for RS232). The supplied name will be truncated to be KMaxPortName (16) characters long.
+@param aInfo On return, contains information about the ports available, including 
+the high and low unit numbers and their name in Port Prefix format.
+@return KErrNone, if the send operation is successful; 
+KErrServerTerminated, if the server is no longer present; 
+KErrServerBusy, if there are no message slots available; 
+KErrNoMemory, if there is insufficient memory available.
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L("RCommServ::GetPortInfo() for comms module : %S"), &aName);
+	TPckg<TSerialInfo> portDesc(aInfo);
+	TIpcArgs args(&portDesc,&aName);
+	return SendReceive(ECommPortInfoByName, args);
+    }
+
+
+EXPORT_C TInt RCommServ::GetPortInfo(TInt aIndex, TDes& aModuleName, TSerialInfo& aInfo)
+/** Gets static information about the available serial ports for a particular comms module.
+
+This variant enables the comms module to be specified by an index number 
+from 0, enabling iteration through the loaded comms modules. Call NumPorts() to obtain
+the current number of loaded comms modules.
+
+Notes:
+
+1. This API only returns static information about the available ports as they were when the module loaded, so
+ports listed as available may actually be in use exclusively by another client at the time of this call.
+
+2. The information returned does not account for any security restrictions on ports, and so does not check
+whether the client has the capabilities to open all the advertised ports.
+
+3. If another C32 client unloads a CSY module, the index of each of 
+   the remaining modules may change. If
+   a client is attempting to iterate through all the open modules when this occurs, the iteration may miss
+   a module or receive KErrNotFound unexpectedly. This behaviour can be detected by 
+   observing that the value returned by NumPorts() changes.
+
+
+
+@param aIndex Index number of the comms module, starting at 0. 
+@param aModuleName On return, contains the name of the comms module referred 
+to by aIndex. This name is expressed as the filename without the path or extension, and the case is
+not specified since it is determined by the first request to LoadCommModule.
+
+@param aInfo On return, contains information about the ports available, including 
+the high and low unit numbers and their name. 
+@return KErrNone, if the send operation is successful; 
+KErrServerTerminated, if the server is no longer present; 
+KErrServerBusy, if there are no message slots available; 
+KErrNoMemory, if there is insufficient memory available.
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RCommServ::GetPortInfo() for comms module of index number : %d"), aIndex);
+	TPckg<TSerialInfo> portDesc(aInfo);
+	TIpcArgs args(&portDesc,&aModuleName,aIndex);
+	return SendReceive(ECommPortInfoByNumber, args);
+    }
+	
+
+EXPORT_C TInt RCommServ::__DbgMarkHeap()
+/** Sets a heap mark in the comm server
+
+Only valid for Debug builds.
+
+@return System wide error code. 
+@capability None
+*/
+    {
+#ifdef _DEBUG
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommDbgMarkHeap, args);
+#else
+    return KErrNone;
+#endif
+    }
+
+
+EXPORT_C TInt RCommServ::__DbgCheckHeap(TInt aCount)
+/** Checks the heap mark in the comm server
+
+Only valid for Debug builds. 
+@capability None
+*/
+    {
+#ifdef _DEBUG
+	TIpcArgs args(aCount);
+	return SendReceive(ECommDbgCheckHeap, args);
+#else
+	(void)aCount; // not used for Release builds
+    return KErrNone;
+#endif
+    }
+
+
+EXPORT_C TInt RCommServ::__DbgMarkEnd(TInt aCount)
+/** Sets the heap mark end in the comm server
+
+Only valid for Debug builds. 
+@capability None
+*/
+    {
+#ifdef _DEBUG
+	TIpcArgs args(aCount);
+	return SendReceive(ECommDbgMarkEnd, args);
+#else
+	(void)aCount; // not used for Release builds
+    return KErrNone;
+#endif
+    }
+
+
+EXPORT_C TInt RCommServ::__DbgFailNext(TInt aCount)
+/** Emulates a single fail next heap allocation in the comm server.
+If C32 is running multiple threads the same request is passed to each thread. Each C32 thread
+will only act on this request if it has not already been configured for heap failures via CMI files.
+
+@param aCount Specifies that after aCount-1 successful allocations the failure will occur on the next
+allocation - ie the failure will occur on the aCount allocation attempt.
+ A value less than zero cancels any outstanding failure request. A value of zero is equivalent to a value
+ of one - ie, fail on the next attempt.
+ 
+Only valid for Debug builds. 
+@capability None
+*/
+    {
+#ifdef _DEBUG
+	TIpcArgs args(aCount);
+	return SendReceive(ECommDbgFailNext,args);
+#else
+	(void)aCount; // not used for Release builds
+    return KErrNone;
+#endif
+    }
+
+
+EXPORT_C TInt RCommServ::__DbgSetTraceMask(TC32Trace aMask)
+/** The functionality of this API has been removed.
+
+Where tracing is required, please refer to the Comms Infrastructure documentation
+on logging.
+
+@param aMask This value is not used.
+@return Always KErrNone.
+@capability None
+*/
+    {
+#ifdef _DEBUG
+	(void)aMask; // aMask is of no use
+	// At one time this function would send ECommDbgSetDebugPrintMask to the server, but
+	// the server hasn't supported this function since at least the last release of EPOC5.
+	return KErrNone;
+#else
+	(void)aMask; // not used for Release builds
+    return KErrNone;
+#endif
+    }
+
+EXPORT_C TInt RCommServ::CreateThreadInCommProc(const TDesC&, const TDesC&, TThreadFunction, TInt aStackSize, TInt aHeapMinSize, TInt aHeapMaxSize)
+/** This functionality has been withdrawn since the introduction of Platform Security.
+
+This API has been replaced with a more secure and controlled model for loading threads
+ into the Comms process, known as the Configurator. The Configurator requires a Comms Provider Module
+ (DLL) to be available that provides the code for the thread to execute, and a configuration file
+ that describes to the Configurator how to manage the Comms Provider Module.
+ Further information on this is only available in documentation libraries that include the Configurator documentation.
+
+@param aLibraryName This value is not used.
+@param aThreadName  This value is not used.
+@param aFunction    This value is not used.
+@param aStackSize   A negative value will result in a panic.
+@param aHeapMinSize A value less than KMinHeapSize will result in a panic.
+@param aHeapMaxSize A value less than aHeapMinSize will result in a panic.
+@return Always KErrNotSupported. 
+@capability CommDD (Deprecate)
+*/
+
+/*  Please refer to the Rootserver component documentation for more information.
+*/
+
+	{
+	C32_STATIC_LOG(KC32Warning,_L8("WARNING: Call to deprecated function CreateThreadInCommProc."));	
+	
+	_LIT(KCommClientPanic,"Comm client");	// panic the client here rather than panicking the C32 server
+        									// thread
+	__ASSERT_ALWAYS(aStackSize>=0,User::Panic(KCommClientPanic,EThrdStackSizeNegative));
+	__ASSERT_ALWAYS(aHeapMinSize>=KMinHeapSize,User::Panic(KCommClientPanic,EThreadHeapMinTooSmall));
+	__ASSERT_ALWAYS(aHeapMaxSize>=aHeapMinSize,User::Panic(KCommClientPanic,EThreadHeapMaxLessThanMin));
+
+	return KErrNotSupported;
+	}
+
+TBool RCommServ::IsServerThreadL()
+/**
+ * Return TRUE if this thread is the C32 main thread
+ *
+ * @note This function is not as water tight as it could be.  This is due to a limitation
+ *       in our ability to get the thread name.  Under non-WINS builds the thread name is
+ *       (even after we rename it) a combination of process name, OS data and thread name.
+ *       Therefore we search for a thread name ending in "CommServer" and belonging to
+ *       the C32 process.  If another process started a thread in C32 via the
+ *       CreateThreadInCommProc() call with a name ending in "CommServer" then this
+ *       function may start to produce incorrect results.
+ *
+ * @return ETrue if this is the C32 main server thread
+ */
+	{
+	TInt res = KErrNone;
+	TFullName name;
+
+	//
+	// Find the Process ID of the C32 process.  Note that WINS builds run the C32 'process'
+	// as a thread and not a separate process.
+	//
+#ifndef __WINS__
+	_LIT(KCommProcessName, "C32exe*");
+
+	RProcess cpProcess;
+	TFindProcess findCp(KCommProcessName);
+	res = findCp.Next(name);
+	__ASSERT_ALWAYS(res==KErrNone,User::Invariant());
+	res = cpProcess.Open(findCp); 
+	(void) User::LeaveIfError(res);
+
+	TProcessId cpid = cpProcess.Id();
+	cpProcess.Close();
+
+	//
+	// A quick short cut.  Is this process C32?  If not then this thread cannot be the
+	// server thread.
+	//
+	if (RProcess().Id() != cpid)
+		{
+		return (EFalse);
+		}
+#endif
+
+	//
+	// Search for the the C32 comm server thread.  For non-WINS builds get the Process
+	// ID of the thread and confirm it matches the C32 Process ID.
+	//
+	RThread ctThread;
+	//thread name comes from C32.cmi file.
+	_LIT(KCommThreadName, "CCommServer");
+	TFindThread findCt(KCommThreadName);
+	while((res=findCt.Next(name))==KErrNone)
+		{
+		(void)User::LeaveIfError(ctThread.Open(KCommThreadName)); // ignoring return value
+#ifdef __WINS__
+		break;
+#else
+		if((res=ctThread.Process(cpProcess))!=KErrNone)
+			{
+			ctThread.Close();
+			User::Leave(res);
+			}
+		TProcessId pid=cpProcess.Id();
+		cpProcess.Close();
+
+		//
+		// We already know that this process is the C32 process.  Does the found thread
+		// belong to C32?  If so then ctThread is the C32 main thread.
+		//
+		if(pid==cpid)
+			{
+			break;
+			}
+		ctThread.Close();
+#endif
+		}
+	if (res==KErrNotFound)
+		return EFalse;	// if the C32 thread is not running, then this thread cannot be it!
+	(void)User::LeaveIfError(res); // ignoring return value
+
+	//
+	// Is this thread the C32 Comm Server thread that we just found?
+	//
+	TBool match=(ctThread.Id()==RThread().Id());
+	ctThread.Close();
+	
+	return match;	// Return TRUE if this thread is the C32 main thread
+	}
+
+//
+// implementation of RComm
+//
+
+EXPORT_C RComm::RComm()
+/** Constructor */
+	: iSignalsNotification(NULL,0,0)
+	,iFlowNotification(NULL,0,0)
+	{
+	}
+
+
+EXPORT_C TInt RComm::Open(RCommServ& aServer, const TDesC& aName, TCommAccess aMode)
+/** Opens a serial port, for one of the three modes indicated by the TCommAccess 
+argument.
+
+The TCommAccess argument may dictate exclusive use of the RComm,
+shared use (thereby giving permission for the port to be shared by other RComm
+objects) or pre-emptable use (allowing another client to pre-empt this session
+with an open request in one of the other two modes). The request will fail if
+the port does not exist, or if it has been opened in exclusive mode elsewhere.
+If the port has been opened in shared mode elsewhere, the request will fail if
+a subsequent attempt is made to open it in exclusive mode.
+A client opening a port in pre-emptive mode must be prepared to have its
+outstanding requests errored with KErrCancel if another client opens the port
+in either ECommShared or ECommExclusive mode.  In this case the port handle
+will effectively be transferred from the pre-emptable client to the new client.
+
+The first variant (this) will open the port in DTE role, that is, the lines
+are configured as for a port of a computer. For instance, the signal lines
+DTR and RTS are outputs while the other signals (DCD,CTS,DSR,RING) are inputs.
+
+The second variant allows the port to be opened in either DTE role or DCE
+role. This latter role means that the lines are configured as for a port of
+a modem. DTR and RTS are inputs while the other signals are outputs.
+
+The request to open in either role will fail with KErrLocked if the port has
+already been opened in the opposite role elsewhere.
+
+@code
+Signal constant    DTE role     DCE role
+----------------------------------------
+KSignalCTS         input        output
+KSignalDSR         input        output
+KSignalDCD         input        output
+KSignalRNG         input        output
+KSignalRTS         output       input
+KSignalDTR         output       input
+@endcode
+
+Note:
+
+1. On some earlier versions of C32 the port number was limited to one digit,
+i.e. from 0 to 9. This restriction is now removed, and the number
+of ports is now only limited by the CSY and/or the Device Drivers up to a maximum
+of KMaxTUint ports.
+
+2. This API checks that the client has the correct capabilities to open the port, while
+the RCommServ APIs do not. So a CSY that allowed the client to interrogate it via RCommServ::GetPortInfo()
+and load it via RCommServ::LoadCommModule() may still reject the same client's call to this API.
+
+3. There are a number of distinct steps that must be performed
+before being able to issue an Open() request for a serial port.
+For convenience these are listed here:
+
+a. Load the physical device driver, which interacts directly with the hardware at the
+lowest level (usually via User::LoadPhysicalDevice()).
+
+b. Load the logical device driver, which provides the comms server with a consistent
+interface to the hardware (usually via User::LoadLogicalDevice()).
+
+c. Connect to the C32 Serial Server using RCommServ
+
+d. Load a specific Comms Module (.CSY) by filename via RCommServ::LoadCommModule.
+
+In some environments the physical and logical device drivers are loaded as part of device boot.
+
+
+
+@param aServer The comms server session.
+@param aName   The name of the port (e.g. "COMM::0")
+@param aMode   The mode in which the port is opened. There is no default.
+@return System-wide error code: KErrNone if successful; KErrPermissionDenied if 
+the port given in aName is wrong or if the request fails the CSY's own security check;
+ KErrNotSupported if this port is not 
+supported by the CSY or the hardware; KErrLocked if the port has already been 
+opened; KErrAccessDenied if the device driver encounteres a problem opening the hardware port.
+
+@capability Dependent
+*/
+    {
+	C32_STATIC_LOG5(KC32Client,_L("RComm::Open(), aServer 0x%x, (port) aName = %S, (port open) aMode = %d (%S)"), &aServer, &aName, aMode, &TC32Log::CommAccessStr16(aMode));
+	iSignalsNotification.Set(NULL,0,0);
+	iFlowNotification.Set(NULL,0,0);
+
+	TCommRole role = ECommRoleDTE;
+	TIpcArgs args(&aName,aMode,role);
+	RSessionBase& s = aServer;
+    return CreateSubSession(s,ECommOpen, args);
+    }
+
+//
+// Version 02 extension to the RComm API
+//
+
+EXPORT_C TInt RComm::Open(RCommServ& aServer, const TDesC& aName, TCommAccess aMode, TCommRole aRole)
+/** Opens a serial port, as described for the other Open() variant. 
+
+This variant allows the port to be opened in either DTE role or DCE role. DCE 
+role means that the lines are configured as for a port of a modem. DTR and RTS 
+are inputs while the other signals are outputs.
+
+@param aServer The comms server session 
+@param aName The name of the port 
+@param aMode The mode in which the port is opened. There is no default. 
+@param aRole DTE/DCE role 
+@return System-wide error code: KErrNone if successful; KErrPermissionDenied if 
+the port given in aName is wrong; KErrNotSupported if this port is not supported 
+by the CSY or the hardware; KErrLocked if the port has already been opened 
+in the opposite role elsewhere. 
+@capability Dependent
+*/
+    {
+	C32_STATIC_LOG7(KC32Client,_L("RComm::Open(), aServer 0x%x, (port) aName %S, (port open) aMode = %d (%S), (port) aRole = %d (%S)"), &aServer, &aName, aMode, &TC32Log::CommAccessStr16(aMode), aRole, &TC32Log::CommRoleStr16(aRole));
+	TIpcArgs args(&aName,aMode,aRole);
+	RSessionBase &s = aServer;
+	return CreateSubSession(s,ECommOpen, args);
+    }
+
+
+//
+// Version 02 extension to the RComm API
+//
+
+
+EXPORT_C void RComm::OpenWhenAvailable(TRequestStatus& aStatus, RCommServ& aServer, const TDesC& aName)
+/** Opens a serial port when it is freed by another client.
+
+When a client has a port open in either exclusive or shared mode, another
+client may use this function to gain access to the port when the owning
+client closes its handle.  Upon closure, the asynchronous OpenWhenAvailable()
+function will complete.  The port role, DTE or DCE, will not be changed by
+this request and so the role will be inherited from the previous session.
+Furthermore, the port will automatically opened in ECommPreemptable mode.
+This can be subsequently upgraded to ECommShared or ECommExclusive mode
+using the SetAccessMode() function.
+
+If client submits an OpenWhenAvailable() request and then attempts
+to execute an action, for example a read or write request, before the
+OpenWhenAvailable has completed, the action will fail with the KErrNotReady
+error code.
+
+The server can only support one OpenWhenAvailable request per port. For
+example, if client A has a port open in exclusive mode and client B has
+an OpenWhenAvailable request pending, then client C's OpenWhenAvailable
+request will fail with the KErrAccessDenied error code.
+
+The server is designed to support the OpenWhenAvailable request dispatched
+from a different RCommServ session than the one actively using the port.
+This is not viewed as a major disadvantage since, in practice, the two
+clients will normally be running in different threads, and quite probably
+different processes.
+
+If the port is available immediately, it will be opened with DTE role.
+
+@param aStatus The request status used to contain completion information for the function.
+@param aServer The comms server session.
+@param aName   The name of the port.
+@return System wide error code: see return values of RComm::Open().
+@capability Dependent
+*/
+	{
+	OpenWhenAvailable(aStatus, aServer, aName, ECommRoleDTE);
+	}
+
+
+EXPORT_C void RComm::OpenWhenAvailable(TRequestStatus& aStatus, RCommServ& aServer, const TDesC& aName, TCommRole aRole)
+/** Opens a serial port when freed.
+
+Same as the other OpenWhenAvailable() but here you can specify the preferred
+role in case the port is free when you want to open it. If the port is already
+opened by another client, you will get the same role when it becomes available.
+
+@param aStatus The request status used to contain completion information for 
+			   the function.
+@param aServer The comms server session.
+@param aName   The name of the port.
+@param aRole   Preferred role (DTE or DCE).
+@return TInt   A system wide error code: see return values of RComm::Open(). 
+@capability Dependent
+*/
+	{
+
+	C32_STATIC_LOG5(KC32Client,_L("RComm::OpenWhenAvailable(), aServer 0x%x, (port) aName = %S, (port) aRole = %d (%S)"), &aServer, &aName, aRole, &TC32Log::CommRoleStr16(aRole));
+	TIpcArgs args(&aName,TIpcArgs::ENothing,aRole);
+	RSessionBase& s = aServer;
+	TInt ret = CreateSubSession(s, ECommOpenWhenAvailable, args);
+
+	if(ret != KErrNone)
+		{
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, ret);
+		return;
+		}
+
+	args.Set(0,ECommPreemptable);
+	SendReceive(ECommSetAccess, args, aStatus);
+	}
+
+
+EXPORT_C void RComm::OpenWhenAvailableCancel()
+/** Cancels an OpenWhenAvailable() pending request. 
+@capability None
+*/
+    {
+    if (SendReceive(ECommOpenWhenAvailableCancel) == KErrNone)
+    	{
+    	Close();
+    	}
+    }
+
+
+EXPORT_C void RComm::Read(TRequestStatus& aStatus, TDes8& aDes)
+/** Reads data from a serial port. 
+
+All reads from the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The length of the TDes8 is set to zero on entry, which means that buffers 
+can be reused without having to be zeroed first.
+
+The number of bytes to read is set to the maximum length of the descriptor.
+
+If a read is issued with a data length of zero the Read() completes immediately 
+with the side effect that the serial hardware is powered up.
+
+If a read terminates with KErrTimedOut and the descriptor is not empty, 
+it will contain valid data. Its length should therefore be tested.
+
+The behaviour of this API after a call to NotifyDataAvailable() is not prescribed
+and so different CSY's behave differently. IrComm will allow a successful completion of this API
+after a call to NotifyDataAvailable(), while ECUART and ECACM will complete the request with KErrInUse.
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code.
+@param aDes A buffer to store the incoming data. The maximum length of the 
+descriptor is the number of bytes to be read. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::Read(), Request to read max number of bytes %d"), aDes.MaxLength());
+	aDes.SetLength(0);
+	TIpcArgs args(&aDes,aDes.MaxLength(),0);
+	SendReceive(ECommRead, args, aStatus);
+    }
+
+
+EXPORT_C void RComm::Read(TRequestStatus& aStatus, TDes8& aDes, TInt aLength)
+/** Reads a specified number of bytes from a serial port.
+
+Overloaded version of Read() with explicit length.
+
+All reads from the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The length of the TDes8 is set to zero on entry, which means that buffers 
+can be reused without having to be zeroed first.
+
+The number of bytes to read is set to aLength.
+
+If a read is issued with a data length of zero (aLength=0) the Read() completes 
+immediately with the side effect that the serial hardware is powered up.
+
+If a read terminates with KErrTimedOut and the descriptor is not empty, 
+it will contain valid data. Its length should therefore be tested.
+
+The behaviour of this API after a call to NotifyDataAvailable() is not prescribed
+and so different CSY's behave differently. IrComm will allow a successful completion of this API
+after a call to NotifyDataAvailable(), while ECUART and ECACM will complete the request with KErrInUse.
+
+@param aStatus 	The request status used to contain completion information for 
+				the function. On completion, contains a system-wide error code.
+@param aDes 	A buffer to store the incoming data. 
+@param aLength	An explicit length of data to be read. This length must be 
+				between 0 and the MaxLength of the descriptor both included. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG3(KC32Client,_L8("RComm::Read(), bytes to read = %d, given buffer's max length %d"), aLength, aDes.MaxLength());
+	if((aLength <= aDes.MaxLength()) && (aLength >= 0))
+		{
+		aDes.SetLength(0);
+		TIpcArgs args(&aDes,aLength,0);
+		SendReceive(ECommRead, args, aStatus);
+	}
+	else
+		{//Complete the request due to invalid length
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, KErrArgument);
+		}
+    }
+
+
+EXPORT_C void RComm::Read(TRequestStatus& aStatus, TTimeIntervalMicroSeconds32 aTimeOut, TDes8& aDes)
+/** Reads data from a serial port only if it arrives before a specified time-out.
+
+Overloaded version of Read() with timeout.
+
+All reads from the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The length of the TDes8 is set to zero on entry, which means that buffers 
+can be reused without having to be zeroed first.
+
+The number of bytes to read is set to the maximum length of the descriptor. 
+
+If a read is issued with a data length of zero the Read() completes immediately 
+but with the side effect that the serial hardware is powered up.
+
+When a Read() terminates with KErrTimedOut, different protocol modules can 
+show different behaviours. Some may write any data received into the aDes 
+buffer, while others may return just an empty descriptor. In the case of a 
+returned empty descriptor use ReadOneOrMore() to read any data left in the 
+buffer.
+
+The behaviour of this API after a call to NotifyDataAvailable() is not prescribed
+and so different CSY's behave differently. IrComm will allow a successful completion of this API
+after a call to NotifyDataAvailable(), while ECUART and ECACM will complete the request with KErrInUse.
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code.
+@param aTimeOut The time-out value for reads in microseconds. If data fails 
+to arrive before the specified number of microseconds, a KErrTimedOut status 
+is returned.
+@param aDes A buffer to store the incoming data. The maximum length of the 
+descriptor is the default for the number of bytes to be read. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG3(KC32Client,_L8("RComm::Read(), aTimeOut = %d, Max Length = %d"), aTimeOut.Int(), aDes.MaxLength());
+	aDes.SetLength(0);
+	TIpcArgs args(&aDes,aDes.MaxLength(),aTimeOut.Int());
+	SendReceive(ECommRead, args, aStatus);
+    }
+
+
+EXPORT_C void RComm::Read(TRequestStatus& aStatus, TTimeIntervalMicroSeconds32 aTimeOut, TDes8& aDes, TInt aLength)
+/** Read data from a serial port (before the time-out).
+
+Reads a specified number of bytes from a serial port only if they arrive before 
+a specified time-out. Overloaded version of Read() with timeout and explicit 
+length.
+
+All reads from the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The length of the TDes8 is set to zero on entry, which means that buffers 
+can be reused without having to be zeroed first.
+
+The number of bytes to read is set to aLength.
+
+If a read is issued with a data length of zero the Read() completes immediately 
+but with the side effect that the serial hardware is powered up.
+
+When a Read() terminates with KErrTimedOut, different protocol modules can 
+show different behaviours. Some may write any data received into the aDes 
+buffer, while others may return just an empty descriptor. In the case of a 
+returned empty descriptor use ReadOneOrMore() to read any data left in the 
+buffer.
+
+The behaviour of this API after a call to NotifyDataAvailable() is not prescribed
+and so different CSY's behave differently. IrComm will allow a successful completion of this API
+after a call to NotifyDataAvailable(), while ECUART and ECACM will complete the request with KErrInUse.
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code.
+@param aTimeOut The time-out value for reads in microseconds. If data fails 
+to arrive before the specified number of microseconds, a KErrTimedOut status 
+is returned. 
+@param aDes A buffer to store the incoming data. 
+@param aLength An explicit length of data to be read This length must be 
+between 0 and the MaxLength of the descriptor both included.
+
+@capability None
+*/
+    {
+	C32_STATIC_LOG4(KC32Client,_L8("RComm::Read(), aTimeOut = %d, bytes to read = %d, Max Length of buffer = %d"), aTimeOut.Int(), aLength, aDes.MaxLength());
+	if((aLength <= aDes.MaxLength()) && (aLength >= 0))
+		{
+		aDes.SetLength(0);
+		TIpcArgs args(&aDes,aLength,aTimeOut.Int());
+		SendReceive(ECommRead, args, aStatus);
+		}
+	else
+		{//Complete the request due to invalid length
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, KErrArgument);
+		}
+    }
+
+
+EXPORT_C void RComm::ReadOneOrMore(TRequestStatus& aStatus, TDes8& aDes)
+/** Read any bytes in the buffer or wait until one arrives.
+
+Reads data from a serial port, but with slightly different behaviour to Read(). 
+If there is data in the serial driver's buffer when ReadOneOrMore() is called, 
+it will read as much data as possible (up to the maximum length of the supplied 
+buffer) and return immediately. If there is no data in the buffer, the request 
+will complete as soon as one or more bytes arrive at the serial hardware.
+
+The behaviour of this API after a call to NotifyDataAvailable() is not prescribed
+and so different CSY's behave differently. IrComm will allow a successful completion of this API
+after a call to NotifyDataAvailable(), while ECUART and ECACM will complete the request with KErrInUse.
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code 
+@param aDes A buffer to store the incoming data. The maximum length of the descriptor
+is the default for the number of bytes to be read. When the request completes this will 
+hold data read from the input buffer. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::ReadOneOrMore(), buffer's max length = %d"), aDes.MaxLength());
+	TIpcArgs args(&aDes,-aDes.MaxLength(),0);
+	// Note: specifying negative length here to indicate OneOrMore
+	//       see RMaxComm::ReadOneOrMore in ECUART.CPP
+	SendReceive(ECommRead, args, aStatus);
+    }
+
+
+EXPORT_C TInt RComm::ReadCancel()
+/** Cancels any pending Read() or ReadOneOrMore() operations.
+
+The cancelled request will still terminate with its TRequestStatus set to 
+any value other than KErrPending. While this is most likely to be KErrCancel, 
+it is nevertheless possible for the cancellation to have been issued after 
+the asynchronous request had already terminated for some other reason. 
+@capability None
+*/
+
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommReadCancel, args);
+    }
+
+
+EXPORT_C TInt RComm::QueryReceiveBuffer() const
+/** Gets the number of bytes currently waiting in the driver's input buffer. 
+A return value of zero means the buffer is empty.
+
+It is not possible to find out exactly how many bytes are currently in the 
+driver's output buffer waiting to be transmitted. However, this is not an 
+issue since it is easy to ensure that the output buffer is empty. If 
+the KConfigWriteBufferedComplete bit (set via the TCommConfigV01 structure's iHandshake field) is clear,
+then all write requests will delay 
+completion until the data has completely cleared the driver's output buffer. 
+If the KConfigWriteBufferedComplete bit is set, a write of zero bytes to a port 
+which has data in the output buffer is guaranteed to delay completion until 
+the buffer has been fully drained.
+
+@return The number of bytes currently waiting to be read from the receive 
+buffer. 
+@capability None
+*/
+{
+	TUint bufferSize;
+	TPtr8 s((TUint8 *)&bufferSize, sizeof(bufferSize));
+	TIpcArgs args(&s);
+	TInt ret = SendReceive(ECommQueryReceiveBuffer,args);
+	if(ret != KErrNone)
+		{
+		return ret;
+		}
+	else
+		{
+		return bufferSize;
+		}
+}
+
+
+EXPORT_C TInt RComm::ResetBuffers(TUint aFlags)
+/** Resets the transmit and receive serial port buffers independently.
+
+aFlags is a bitmask, so setting KCommResetRx|KCommResetTx (the default) resets 
+both buffers and all data in them is lost. This is the default value, so this 
+is what happens if the function is called without a parameter.
+
+This function should not be called when there are pending reads or writes.
+
+@param aFlags KCommResetRx to reset the receive buffer KCommResetTx to reset 
+the transmit buffer 
+@capability None
+*/
+    {
+	TIpcArgs args(aFlags);
+	return SendReceive(ECommResetBuffers, args);
+    }
+
+
+EXPORT_C void RComm::Write(TRequestStatus& aStatus, const TDesC8& aDes)
+/** Writes data to a serial port. 
+
+All writes to the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The number of bytes to write is set to the maximum length of the descriptor.
+
+When a Write() is issued with a data length of zero it cannot complete until 
+the current handshaking configuration and the state of input control lines 
+indicate that it is possible for data to be immediately written to the serial 
+line, even though no data is to be written. This functionality is useful when 
+determining when serial devices come on line, and checking that the output 
+buffer is empty (if the KConfigWriteBufferedComplete bit is set).
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code. 
+@param aDes A descriptor containing the data to be written to the serial port. 
+@capability None
+*/
+    {
+	TIpcArgs args(&aDes,aDes.Length(),0);
+	SendReceive(ECommWrite,args,aStatus);
+    }
+
+
+EXPORT_C void RComm::Write(TRequestStatus& aStatus, const TDesC8& aDes, TInt aLength)
+/** Writes a specified number of bytes to a serial port. 
+
+All writes to the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The number of bytes to write is set to aLength.
+
+When a Write() is issued with a data length of zero it cannot complete until 
+the current handshaking configuration and the state of input control lines 
+indicate that it is possible for data to be immediately written to the serial 
+line, even though no data is to be written. This functionality is useful when 
+determining when serial devices come on line, and checking that the output 
+buffer is empty (if the KConfigWriteBufferedComplete bit is set).
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code.
+@param aDes A descriptor containing the data to be written to the serial port.
+@param aLength The number of bytes to write. This length must be between 0 
+and the length of the descriptor both included.
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::Write(), (bytes to write) aLength = %d"), aLength);
+	if((aLength <= aDes.Length()) && (aLength >= 0))
+		{
+		TIpcArgs args(&aDes,aLength,0);
+		SendReceive(ECommWrite, args, aStatus);
+		}
+	else
+		{//Complete the request due to invalid length
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, KErrArgument);
+		}
+    }
+
+
+EXPORT_C void RComm::Write(TRequestStatus& aStatus, TTimeIntervalMicroSeconds32 aTimeOut, const TDesC8& aDes)
+/** Writes data to a serial port within a specified time-out.
+
+All writes to the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The number of bytes to write is set to the maximum length of the descriptor.
+
+When a Write() is issued with a data length of zero it cannot complete until 
+the current handshaking configuration and the state of input control lines 
+indicate that it is possible for data to be immediately written to the serial 
+line, even though no data is to be written. This functionality is useful when 
+determining when serial devices come on line, and checking that the output 
+buffer is empty (if the KConfigWriteBufferedComplete bit is set).
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code.
+@param aTimeOut The write will terminate after aTimeout microseconds if the 
+data requested has not been sent. A KErrTimedOut status is returned.
+@param aDes A descriptor containing the data to be written to the serial port. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::Write(), aTimeOut = %d (microseconds)"), aTimeOut.Int());
+	TIpcArgs args(&aDes,aDes.Length(),aTimeOut.Int());
+	SendReceive(ECommWrite,args, aStatus);
+    }
+
+
+EXPORT_C void RComm::Write(TRequestStatus& aStatus, TTimeIntervalMicroSeconds32 aTimeOut, const TDesC8& aDes, TInt aLength)
+/** Writes a specified number of bytes to a serial port within a specified 
+time-out.
+
+All writes to the serial device use 8-bit descriptors as data buffers, even 
+on a Unicode system.
+
+The number of bytes to write is set to aLength.
+
+When a Write() is issued with a data length of zero it cannot complete until 
+the current handshaking configuration and the state of input control lines 
+indicate that it is possible for data to be immediately written to the serial 
+line. This functionality is useful when determining when serial devices come 
+on line, and checking that the output buffer is empty (if 
+the KConfigWriteBufferedComplete bit is set).
+
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code 
+@param aTimeOut The write will terminate after aTimeout microseconds if the 
+data requested has not been sent. A KErrTimedOut status is returned.
+@param aDes A descriptor containing the data to be written to the serial port.
+@param aLength The number of bytes to write. This length must be between 0 
+and the maximum length of the descriptor both included. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG3(KC32Client,_L8("RComm::Write(), aTimeOut = %d (microseconds), (bytes to write) aLength = %d"), aTimeOut.Int(), aLength);
+	if((aLength <= aDes.Length()) && (aLength >= 0))
+		{
+		TIpcArgs args(&aDes,aLength,aTimeOut.Int());
+		SendReceive(ECommWrite, args, aStatus);
+		}
+	else
+		{//Complete the request due to invalid length
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, KErrArgument);
+		}
+    }
+
+
+EXPORT_C TInt RComm::WriteCancel()
+/** Cancels any pending Write() operations.
+
+The cancelled request will still terminate with its TRequestStatus set, to 
+any value other than KErrPending. While this is most likely to be KErrCancel, 
+it is nevertheless possible for the cancellation to have been issued after 
+the asynchronous request had already terminated for some other reason. 
+
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommWriteCancel, args);
+    }
+
+	
+EXPORT_C void RComm::Break(TRequestStatus& aStatus, TTimeIntervalMicroSeconds32 aTime)
+/** Sets a break condition for a specified time.
+
+A break condition on a line is when a data line is held permanently high for
+an indeterminate period which must be greater than the time normally taken
+to transmit two characters. It is sometimes used as an error signal between
+computers and other devices attached to them over RS232 lines.
+
+Notes:
+
+Setting breaks is not supported on the integral ARM serial hardware.
+EPOC has no support for detecting received breaks.
+There is no way to detects whether setting a break is supported using Caps().
+ 
+@param aStatus The request status used to contain completion information for 
+the function. On completion, contains a system-wide error code.
+@param aTime A timed break period in microseconds. 
+
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::Break(), for aTime = %d (microseconds)"), aTime.Int());
+	TIpcArgs args(aTime.Int());
+	SendReceive(ECommBreak, args, aStatus);
+    }
+
+
+EXPORT_C TInt RComm::BreakCancel()
+/** Cancels any pending Break() operations. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommBreakCancel,args);
+    }
+
+
+EXPORT_C TInt RComm::Cancel()
+/** Cancels any pending reads and writes.
+
+A panic will result if an attempt is made to reconfigure a port if there are 
+any pending reads or writes. Use this function before configuring a port if 
+there is any doubt as to whether it is safe to do so. It isn't necessary 
+to call Cancel() before closing a port as this is done automatically. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommCancel, args);	
+    }
+
+
+EXPORT_C TInt RComm::Config(TDes8& aConfig) const
+/** Reads the current configuration of the serial port.
+
+It isn't essential to read an existing configuration in order to set a new 
+one. However, calling this function is a useful way of initializing a TCommConfig 
+structure and thus avoiding the overhead of having to explicitly set every 
+member. If a port were being shared between difference processes, it would 
+also be good manners to save an existing configuration before using the port 
+in order than it might be restored when you have finished with it.
+
+@param aConfig On return, a TCommConfig package buffer holding the configuration 
+settings 
+@capability None
+*/
+    {
+	TIpcArgs args(&aConfig);
+	return SendReceive(ECommConfig, args);
+    }
+
+
+EXPORT_C TInt RComm::SetConfig(const TDesC8& aConfig)
+/** Sets the configuration of the serial port.
+
+It is not possible to reconfigure the capabilities of ports while they are 
+being used. In particular, if any client attempts to reconfigure a port when
+there are pending reads or writes a KErrInUse error code will be returned.
+
+@param aConfig New configuration settings packaged in a TCommConfig
+@return System-wide error code: KErrInUse if there is a pending read or write on 
+the port, otherwise system-wide error codes
+@capability None
+*/
+    {
+	TIpcArgs args(&aConfig);
+	return SendReceive(ECommSetConfig, args);
+    }
+
+
+EXPORT_C TInt RComm::Caps(TDes8& aCaps) const
+/** Reads the capabilities of the serial port.
+
+As the serial driver can control a range of different physical devices with 
+differing capabilities, it could be considered important from the point of 
+view of the operating system to be able to read these capabilities before 
+attempting to configure the port. In practice however, program development 
+is likely to be targeted at a specific hardware configuration, and interrogation 
+of a device to ascertain its capabilities isn't normally necessary.
+
+@param aCaps On return this descriptor will contain either a packaged TCommCapsV01 
+structure or a packaged TCommCapsV02 structure corresponding to the capabilities 
+of the serial device and of the CSY module, depending on the size of the descriptor 
+passed in to the function. 
+@capability None
+*/
+    {
+	TIpcArgs args(&aCaps);
+	return SendReceive(ECommCaps, args);
+    }
+
+
+EXPORT_C TInt RComm::Mode(TCommServerConfig& aConfig) const
+/** Gets server buffering mode.
+
+@param aConfig A packaged TCommServerConfigV01 structure which will hold the 
+required information on return. 
+@capability None
+*/
+    {
+	TIpcArgs args(&aConfig);
+	return SendReceive(ECommGetMode, args);
+    }
+
+
+EXPORT_C TInt RComm::SetMode(const TCommServerConfig& aConfig)
+/** Sets the server buffering mode.
+
+This function can be used to set either buffering mode, and if partial buffering
+is being used, it can also set the size of the buffer that the server will use.
+These items are packaged up into the TCommServerConfig descriptor.
+
+The default of full buffering is nearly always going to be the quicker option, 
+as only a single client-server data transfer is ever needed. The mode should 
+not be changed by an application without a very good reason (such as memory 
+constraints) otherwise performance is liable to suffer.
+
+@param aConfig A packaged TCommServerConfigV01 structure to be set.
+@return System-wide error code 
+@capability None
+*/
+    {
+	TIpcArgs args(&aConfig);
+	return SendReceive(ECommSetMode, args);
+    }
+
+
+EXPORT_C TUint RComm::Signals(TUint aSignalMask) const
+/** Reads the serial port control lines.
+
+Reads the status of the RS232 input and output lines (RTS, CTS, DSR, DCD, DTR). 
+They are bit-masked into a single integer and one or all of them can be read 
+at any time.
+
+Not all of the input lines are guaranteed to be available on all serial devices. 
+
+@param aSignalMask Bitmask of lines to read. It defaults to all lines (0x3f 
+as only the top six bits of this integer are valid). A different value can 
+be specified as aSignalMask if specific information is required: for instance, 
+Signals(KSignalDSR) could be used to find out if a modem were connected to 
+the serial port.
+@return An integer with the bits set to reflect the status of the handshaking 
+lines 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::Signals(), aSignalMask = %d"), aSignalMask);
+    TUint signals;
+    TPtr8 s((TUint8 *)&signals, sizeof(signals));
+	TIpcArgs args(&s);
+	SendReceive(ECommSignals, args);
+	return signals & aSignalMask;
+    }
+
+
+EXPORT_C TInt RComm::SetSignalsToMark(TUint aSignalMask)
+/** Sets the specified RS232 output lines.
+
+Using this function, either of the RS232 output lines (DTR and RTS) can be
+set manually.
+
+For many applications, these lines will be read and set under driver
+control as determined by the handshaking options selected.
+
+@param aSignalMask Bitmask of handshaking lines 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::SetSignalsToMark(), aSignalMask = %d"), aSignalMask);
+	TIpcArgs args(aSignalMask);
+	return SendReceive(ECommSetSignalsToMark, args);
+    }
+
+
+EXPORT_C TInt RComm::SetSignalsToSpace(TUint aSignalMask)
+/** Clears RS232 output lines.
+
+Using this function, either of the RS232 output lines (DTR and RTS) can be
+cleared manually.
+
+For many applications, these lines will be read and set under driver
+control as determined by the handshaking options selected.
+
+@param aSignalMask Bitmask of handshaking lines 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::SetSignalsToSpace(), aSignalMask = %d"), aSignalMask);
+	TIpcArgs args(aSignalMask);
+	return SendReceive(ECommSetSignalsToSpace, args);
+    }
+
+
+EXPORT_C TInt RComm::ReceiveBufferLength() const
+/** Gets the size of the serial port buffers. 
+
+Despite its name, this function returns the size of both the receive and 
+transmit buffers, which are (obviously) always the same size.
+
+@return The current size of both the receive and transmit buffers in bytes. 
+@capability None
+*/
+    {
+	TInt bufferSize;
+	TPtr8 s((TUint8 *)&bufferSize,sizeof(bufferSize));
+
+	TIpcArgs args(&s);
+	TInt ret = SendReceive(ECommReceiveBufferLength, args);
+	if(ret != KErrNone)
+		{
+		return ret;
+		}
+	else
+		{
+		return bufferSize;
+		}
+    }
+
+
+EXPORT_C TInt RComm::SetReceiveBufferLength(TInt aLength)
+/** Sets the size of the serial port receive and transmit buffers.
+
+Notes:
+
+There is no error code returned by this function. If the buffer is set to 
+too large a figure, the request is simply ignored. If you are in any doubt 
+about the success of a SetReceiveBufferLength request, you should examine 
+the returned value from ReceiveBufferLength. 
+
+It isn't always essential to set a buffer size as there is a generous default 
+of 1024. 
+
+Changing the size of the receive buffer is the only way to tailor the operation 
+of flow control in Symbian OS as the exact position of the high water mark 
+is not configurable.
+
+@param aLength The required size of the receive and transmit buffers in bytes. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG2(KC32Client,_L8("RComm::SetReceiveBufferLength(), aLength = %d"), aLength);
+	TIpcArgs args(aLength);
+	return SendReceive(ECommSetReceiveBufferLength,args);
+    }
+
+
+EXPORT_C void RComm::Close()
+/** Closes a serial port.
+If the session is closed without having closed all the open ports via calls to this function, then the session close
+will close all remaining ports opened by the session.
+@capability None
+*/
+    {
+    CloseSubSession(ECommClose);
+    }
+
+
+#ifdef _DEBUG_DEVCOMM
+EXPORT_C TInt RComm::DebugInfo(TDes8& aDes)
+/** Dump debug info.
+
+ @param aDes Description of the debug information.
+@capability None
+*/
+    {
+	TIpcArgs args(&aDes);
+	return SendReceive(ECommDbgDoDumpDebugInfo,args);
+    }
+#endif
+
+
+//
+// Extensions to the RComm API starts from here
+//
+
+
+EXPORT_C void RComm::NotifySignalChange(TRequestStatus& aStatus, TUint& aSignals, TUint aSignalMask)
+/** Notifies the client when one of the signals change.
+
+@param aStatus Asynchronous completion status 
+@param aSignals On return, the new set of signals. The bottom five bits contain 
+a mask of the signals that are set (using the Signal line constants). The 
+top four bits store which signal has changed (using the Signal line changed 
+constants).
+@param aSignalMask Bitmaks of the signals to monitor. The default is all signals. 
+See also KSignalDTEOutputs and KSignalDTEInputs. 
+@capability None
+*/
+    {
+	C32_STATIC_LOG3(KC32Client,_L8("RComm::NotifySignalChange(), aSignals = %d, aSignalMask = %d"), aSignals, aSignalMask);
+	iSignalsNotification.Set((TUint8*)&aSignals, sizeof(TUint), sizeof(TUint));
+	TIpcArgs args(&iSignalsNotification,aSignalMask);
+	SendReceive(ECommNotifySignals, args, aStatus);
+    }
+
+
+EXPORT_C TInt RComm::NotifySignalChangeCancel() const
+/** Cancels a NotifySignalChange() request. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommNotifySignalsCancel, args);
+    }
+
+
+EXPORT_C void RComm::NotifyConfigChange(TRequestStatus& aStatus, TDes8& aNewConfig) const
+/** Notifies the client when the port configuration (data rate, character width, 
+stop bits, handshaking, or parity) of the remote end changes.
+
+@param aStatus On return, system wide error code for asynchronous function.
+@param aNewConfig On completion, a packaged TCommNotificationV01. 
+@capability None
+*/
+    {
+	TIpcArgs args(&aNewConfig);
+	SendReceive(ECommNotifyConfigChange, args, aStatus);
+    }
+
+
+EXPORT_C TInt RComm::NotifyConfigChangeCancel() const
+/** Cancels a NotifyConfigChange() request. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommNotifyConfigChangeCancel, args);
+    }
+
+
+EXPORT_C void RComm::NotifyFlowControlChange(TRequestStatus& aStatus, TFlowControl& aFlowControl)
+/** Notifies the client when the flow control between the CSY and the external 
+device changes.
+
+@param aStatus On return, system wide error code for asynchronous function.
+@param aFlowControl On completion, new flow control status. 
+@capability None
+*/
+    {
+	iFlowNotification.Set((TUint8*)&aFlowControl, sizeof(TFlowControl), sizeof(TFlowControl));
+	TIpcArgs args(&iFlowNotification);
+	SendReceive(ECommNotifyFlowControl, args, aStatus);
+    }
+
+
+EXPORT_C TInt RComm::NotifyFlowControlChangeCancel() const
+/** Cancels a NotifyFlowControlChange() request. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommNotifyFlowControlCancel, args);
+    }
+
+
+EXPORT_C TInt RComm::GetFlowControlStatus(TFlowControl& aFlowControl) const
+/** Gets the current status of flow control between the port and the third party 
+(external PC or internal signalling stack).
+
+@param aFlowControl On return, flow control status 
+@return System-wide error code 
+@capability None
+*/
+    {
+	TPckg<TFlowControl> len(aFlowControl);
+	TIpcArgs args(&len);
+	return SendReceive(ECommGetFlowControl, args);
+    }
+
+
+
+
+EXPORT_C void RComm::NotifyBreak(TRequestStatus& aStatus) const
+/** Notifies the client when a break occurs: the remote end has held the communication 
+line high for a certain number of bits to indicate a break condition.
+
+@param aStatus On return, system wide error code for asynchronous function. 
+@capability None
+*/
+	{
+	TIpcArgs args(TIpcArgs::ENothing);
+	SendReceive(ECommNotifyBreak,args,aStatus);
+    }
+
+
+EXPORT_C TInt RComm::NotifyBreakCancel() const
+/** Cancels a NotifyBreak() request. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommNotifyBreakCancel, args);
+    }
+
+
+EXPORT_C TInt RComm::GetRole(TCommRole& aRole) const
+/** Gets current DCE/DTE role.
+
+@param aRole On return, current DCE/DTE role 
+@return System-wide error code 
+@capability None
+*/
+    {
+	TPckg<TCommRole> len(aRole);
+	TIpcArgs args(&len);
+	return SendReceive(ECommGetRole, args);
+    }
+
+
+EXPORT_C void RComm::NotifyDataAvailable(TRequestStatus& aStatus) const
+/** Notifies the client when data is available to be read from the input buffer.
+
+This API allows the client to delay creation of the buffer receiving the data until the data
+has arrived. This allows the client to query the size of the data waiting before creating the buffer,
+and simplifies the client's buffer management since it is only needed during the subsequent Read() calls.
+
+The behaviour of this API after a call to Read() or ReadOneOrMore() is not prescribed
+and so different CSY's behave differently. IrComm will allow a successful completion of this API
+after a call to Read() or readOneOrMore(), while ECUART and ECACM will complete the request with KErrInUse.
+
+@param aStatus On return, a system wide error code.
+@capability None
+*/
+	{
+	TIpcArgs args(TIpcArgs::ENothing);
+	SendReceive(ECommNotifyDataAvailable,args, aStatus);
+    }
+
+
+EXPORT_C TInt RComm::NotifyDataAvailableCancel() const
+/** Cancels a NotifyDataAvailable() request. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommNotifyDataAvailableCancel,args);
+    }
+
+
+EXPORT_C void RComm::NotifyOutputEmpty(TRequestStatus& aStatus) const
+/** Notifies the client when the transmit buffer is emptied.
+
+@param aStatus On return, system wide error code for asynchronous function. 
+@capability None
+*/
+	{
+	TIpcArgs args(TIpcArgs::ENothing);
+	SendReceive(ECommNotifyOutputEmpty,args,aStatus);
+    }
+
+
+EXPORT_C TInt RComm::NotifyOutputEmptyCancel() const
+/** Cancels a NotifyOutputEmpty() request. 
+@capability None
+*/
+    {
+	TIpcArgs args(TIpcArgs::ENothing);
+	return SendReceive(ECommNotifyOutputEmptyCancel,args);
+    }
+
+
+EXPORT_C TInt RComm::SetAccessMode(TCommAccess aNewMode)
+/** Upgrades the mode of a port handle from pre-emptive mode to shared or exclusive 
+mode.
+
+Notes:
+
+If a client attempts to change the mode of a port that is already in either 
+shared or exclusive modes, the request will fail with the KErrNotSupported 
+error code.
+
+Clients should not attempt to change the access mode to pre-emptive, the behaviour 
+in this case is unpredictable.
+
+@param aNewMode The value of the new port mode, either ECommShared or ECommExclusive.
+@return System-wide error code. 
+@capability None
+*/
+	{
+	C32_STATIC_LOG3(KC32Client,_L8("RComm::SetAccessMode(), aNewMode = %d (%S)"), aNewMode, &TC32Log::CommAccessStr(aNewMode));
+	TIpcArgs args(aNewMode);
+	return SendReceive(ECommSetAccess, args);
+	}
+
+#ifdef _DEBUG
+EXPORT_C TInt RComm::DebugState( TCommDebugInfo& aInfo )
+/** Returns the debug state.
+
+@return aInfo debug info to be returned to. 
+@capability None
+*/
+	{
+	TPckg<TCommDebugInfo> x(aInfo);
+	TIpcArgs args(&x);
+	return SendReceive(ECommDebugState, args);
+	}
+#else
+EXPORT_C TInt RComm::DebugState( TCommDebugInfo& /*aInfo*/ )
+/** Debug state information. Only implemented for DEBUG builds. */
+	{
+	return 0;
+	}
+#endif
+
+
+// EOF - CC_CLI.CPP