code:
/*
 * QBtObjectExchangeClient.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGECLIENT_H_
#define QBTOBJECTEXCHANGECLIENT_H_

#include <QBtGlobal.h>
#include <QBtTypes.h>
#include <QBtServiceAdvertiser.h>
#include <QtCore/QObject>

QBT_NAMESPACE_BEGIN

//forward declaration
class QBtObjectExchangeClientPrivate;

/**
 * Class that provides the mechanism to connect to a remote
 * OBEX server and send or recieve files or raw data.
 *
 * After instantiation user can call connectToServer(QBtDevice&, QBtService&)
 * to connect to the remote server specified by the remoteDevice argument
 * to its service provide by remoteService argument.
 *
 *  P.S. At the remote service, one of the supported protocols must be
 * QBtConstants::OBEX. Suggestion, use a service whose class is equal to
 * QBtConstants::OBEXObjectPush or QBtConstants::OBEXFileTransfer.
 * Again, it is suggested to use QBtConstants::OBEXObjectPush.
 * Both options will work fine if the user wants to send a file to
 * the server, but at present further operations can be done using
 * QBtConstants::OBEXObjectPush.
 *
 * Signal connectedToServer() is emitted upon successfull connection to the OBEX server.
 *
 * After the successfull connection to the server, user can call putFile(const QString&)
 * to send to the remote server the file specified by the string passed as argument.
 * If successfull then objectSent() signal is emitted.
 *
 * Also user is able to send a request to get a file from the remote server specifing
 * the absolute path of the file to be fetched at the remote device's file system.
 * Also a local path must be set which is where the file will be stored after the
 * successfull transfer.
 * getFile(const QString& localPath, const QString& remoteFileNameFull)
 * If successfull then fileReceived(const QString) is emitted.
 *
 * getByteBuffer() and putByteBuffer() are implemented but not tested.
 * If successfull they emit dataReceived(const QByteArray) and objectSent() respectively.
 *
 * If connected to an OBEX FTP bluetooth service then setPath() can be called
 * to set the remote working directory. If successfull then remotePathSet(const QString)
 * will be emitted.
 *
 * User can abort any transmittion in progress by calling abort().
 *
 * User can disconnect from the server at any time or the disconnection will take place at
 * destruction time. Any transmittion in progress will be terminated instantly.
 * A successfull disconnection emits disconnectedFromServer() signal.
 */
class DLL_EXPORT QBtObjectExchangeClient : public QObject
{
    Q_OBJECT

public:
    enum ErrorCode{
        OBEXClientConnectionError,
        OBEXClientSendError,
        OBEXClientReceiveError,
        OBEXClientDisconnected,
        OBEXClientInUse,
        OBEXClientInternalError,
        OBEXClientNoSelectedDevice,
        OBEXClientNoSelectedService,
        OBEXClientUnableToSetPath,
		OBEXFeatureNotSupported,
		OBEXClientBrowseError
    };

public:
    QBtObjectExchangeClient(QObject* parent);
    ~QBtObjectExchangeClient();

    /**
     * connectToServer()
     *
     * Connect to a remote server defined by parameter 1 to its service
     * defined by parameter 2.
     *
     * P.S. At the remote service, one of the supported protocols must be
     * QBtConstants::OBEX. Suggestion, use a service whose class is equal to
     * QBtConstants::OBEXObjectPush or QBtConstants::OBEXFileTransfer.
     * Again, it is suggested to use QBtConstants::OBEXObjectPush.
     * Both options will work fine if the user wants to send a file to
     * the server, but at present further operations can be done using
     * QBtConstants::OBEXObjectPush.
     *
     * @param remoteDevice
     * @param remoteService
     */
    void connectToServer(const QBtDevice& remoteDevice, const QBtService& remoteService);

    /**
     * getFile()
     * Get a file from the remote Server
     *
     * @param localPath the path where the file will be saved
     * @param remoteFileNameFull the name of the file to be transfered
     *							containing the full path of its remote location
     */
    void getFile(const QString& remoteFileAbsolutePath, const QString& destinationFolder);

    /**
     * getByteBuffer(const QString& dataName)
     * Request from the server to GET the data buffer defined in the argument
     *
     * @param dataName The name of the buffer.
     */
    void getByteBuffer(const QString& dataName);

    /**
     * Send a specified file from the local file system to the remote
     * OBEX server.
     *
     * @param fileName The file name of the file to be sent. The absolute
     *                 path of the file is required.
     */
    void putFile(const QString& fileName);

    /**
     * putByteBuffer()
     *
     * send the server a byte sequence.
     * @param data,  the data of the buffer
     * @param bufferName, the name of the buffer (used for convenience on the data
     * 		processing of the server)
     */
    void putByteBuffer(const QByteArray& data, const QString& bufferName);

    /**
     * abort()
     *
     * abort any panding or running transmittion.
     */
    void abort();

    /**
     * setPath(const QString path)
     *
     * Set the current path of the remote device OBEX session.
     * @param path The remote folder to be set as current
     */
    void setPath(const QString & path);

	/**
	 * getWorkingPath
	 *
	 *	ONLY FOR WINDOWS
	 *
	 * Return as QString holding the absolute path of the current working directory
	 */
        QString getWorkingPath();

	/**
	 *	initiateFolderBrowsing()
	 *
	 *	ONLY FOR WINDOWS
	 *
	 *	Browse the files of a selected folder.
	 *
	 *  @param folder The folder path must either be absolute (e.g. \E:\Images), or it must be the name of the folder
	 *  you are going to browse as long as the folder is inside the current working directory of yours.
	 *
	 *  @return QList<QBtRemoteFileInfo*> a list of the files/folders found and their attributes
	 */
	QList<QBtRemoteFileInfo*> initiateFolderBrowsing(const QString& folderPath = "");

	/**
	 *	locateFiles
	 *
	 *	ONLY FOR WINDOWS
	 *
	 *	Locate files/folders that comply to the regex passed as arguments. For example can be used to isolate
	 *	files of specific type.
	 *
	 *	@param regex The regex that describes the files that are needed to be selected. If this parameter is not set, the default
	 *	operation is to select all the files in the specified folder.
	 *
	 *	@param folder The folder path must either be absolute (e.g. \E:\Images), or it must be the name of the folder
	 *  you are going to browse as long as the folder is inside the current working directory of yours. If this parameter is not set,
	 *	the default operation is to search in the current working directory.
	 */
	QList<QBtRemoteFileInfo*> locateFiles(QRegExp* regex=0, QString folder="");

	/**
	 *	batchFileRetrieval
	 *
	 *	ONLY FOR WINDOWS
	 *
	 *	Convenient method to retrieve multiple files in the row.
	 *
	 *	@param files The list of files to retrieve
	 *	@param destinationFolder The folder in the local file system where the files will be stored. The files are placed all
	 *	in that directory same directory so the structure in the remote file system is not preserved.
	 *	@param retrieveOnlyNewFiles If set true, then it first check if the file defined already exists in the
	 *	destination folder. If it does then it skips it. By default it is set to copy every file it founds.
	 */
	void batchFileRetrieval(const QList<QBtRemoteFileInfo*>& files,
		const QString destinationFolder,
		bool retrieveOnlyNewFiles = false);

    /**
     * Get info about the service connected to.
     * @return An object containing the service info
     */
    QBtService& getTransmittingService();

    /**
     * Get info about the server connected to.
     * @return An object containing the remote server device info.
     */
    QBtDevice& getServerDevice();

    /**
     * Checks if the client is performing some operation.
     */
    bool isBusy() const;

    /**
     * Checks if the client got a connection (it does not check *now* if the client is still connected).
     */
    bool isConnected() const;

public slots:
    void disconnect();

signals:

    /**
     * Emitted in case of error
     */
    void error(QBtObjectExchangeClient::ErrorCode code);

    /**
     * Emitted upon successfull connection to the OBEX server.
     */
    void connectedToServer();

    /**
     * Emitted upon disconnection from the server.
     */
    void disconnectedFromServer();

    /**
     * Emitted upon successfull transmittion of an object
     */
    void objectSent();

    /**
     * Emitted when a file is received from the server
     */

    void fileReceived (const QString & fileName);

    /**
     * Emitted when a byte buffer is received from the server
     */
    void dataReceived (const QByteArray & data);

    /**
     * Emitted upon successfull set of the remote current working directory.
     */
    void remotePathSet (const QString & pathName);

	/**
	 *	Emitted after calling initiateFolderBrowsing function for every result
	 *	found from browsing.
	 *
	 *	@param file The file info. See QBtRemoteFileInfo class for the info provided.
	 */
	void folderBrowsingResultElement(const QBtRemoteFileInfo& file);

private:
    friend class QBtObjectExchangeClientPrivate;
    QBtObjectExchangeClientPrivate* _implPtr;
};

QBT_NAMESPACE_END

//Q_DECLARE_METATYPE(QBT_PREPEND_NAMESPACE(QBtObjectExchangeClient))

#endif /* QBTOBJECTEXCHANGECLIENT_H_ */


code:
/*
 * QBtObjectExchangeClient_stub.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGECLIENT_STUB_H_
#define QBTOBJECTEXCHANGECLIENT_STUB_H_

class QBtObjectExchangeClientPrivate
{
public:

	QBtObjectExchangeClientPrivate(QBtObjectExchangeClient* publicClass);
	~QBtObjectExchangeClientPrivate();

	/**
	* ConnectToServer
	* Connect to the server
	* INFO: if remoteService has no handle information then the classId
	* field is used to connect. (Tested class id working QBtConstants::OBEXFileTransfer)
	*
	* @param remoteDevice the remote server to connect to
	* @param remoteServive the remote service of the server
	*/
	void ConnectToServer(const QBtDevice& remoteDevice, const QBtService& remoteService);

	/**
	* Disconnect
	* Disconnect from the remote machine, by sending an
	* OBEX disconnect, and closing the transport on (and
	* regardless of) response from the server.
	*/
	void Disconnect();

	/**
	* SendFile
	* Send a file to a service on a remote machine
	*/
	void SendFile(const QString& fileName);

	/**
	* SendData
	* Send a byte array to a service on a remote machine
	*/
	void SendData(const QByteArray& data, const QString& bufferName);

	/**
	* Abort
	* Send the OBEX aborts command to the remote machine
	*/
	void Abort();

	/**
	* IsConnected
	* @return true if the client is connected
	*/
	bool IsConnected();

	/**
	* IsBusy
	* @return true if the client is performing some operation.
	*/
	bool IsBusy();

	/**
	* SetPath()
	* Set the current path of the remote device OBEX session.
	*/
	bool SetPath(const QString & path);

	/**
	* GetFile
	*
	* Request from the server to GET the file defined in the argument
	*/
	void GetFile(const QString& localPath, const QString& remoteFileNameFull);

	/**
	* GetByteBuffer()
	*
	* Request from the server to GET the data buffer defined in the argument
	*/
	void GetByteBuffer(const QString& dataName);

private:
	QBtObjectExchangeClient* p_ptr;
};

#endif /* QBTOBJECTEXCHANGECLIENT_STUB_H_ */

repo_name: snapshot/qbluetooth

license: unknown


code:
/*
 * QBtObjectExchangeClient_symbian.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGECLIENT_SYMBIAN_H_
#define QBTOBJECTEXCHANGECLIENT_SYMBIAN_H_

#include <QBtObjectExchangeClient.h>

#include <f32file.h>
#include <e32base.h>
#include <obex.h>

class QBtObjectExchangeClientPrivate : public CActive
{

public: // Constructors and destructor.
    /**
     * NewL
     * Construct a QBtObjectExchangeClientPrivate
     * @param pointer to qt public class
     * @return a pointer to the created instance of
     * QBtObjectExchangeClientPrivate
     */
    static QBtObjectExchangeClientPrivate* NewL( QBtObjectExchangeClient* publicClass );

    /**
     * NewLC
     * Construct a QBtObjectExchangeClientPrivate
     * @param pointer to qt public class
     * @return a pointer to the created instance
     * of QBtObjectExchangeClientPrivate
     */
    static QBtObjectExchangeClientPrivate* NewLC( QBtObjectExchangeClient* publicClass );

    /**
     * ~QBtObjectExchangeClientPrivate
     * Destroy the object and release all memory objects.
     * Close any open sockets
     */
    virtual ~QBtObjectExchangeClientPrivate();

    /**
     * ConnectToServer
     * Connect to the server
     * @param remoteDevice the remote server to connect to
     * @param remoteServive the remote service of the server
     */
    void ConnectToServer(const QBtDevice& remoteDevice, const QBtService& remoteService);

    /**
     * Disconnect
     * Disconnect from the remote machine, by sending an
     * OBEX disconnect, and closing the transport on (and
     * regardless of) response from the server.
     */
    void Disconnect();

    /**
     * SendFile
     * Send a file to a service on a remote machine
     */
    void SendFile(const QString& fileName);

    /**
     * SendData
     * Send a byte array to a service on a remote machine
     */
    void SendData(const QByteArray& data, const QString& bufferName);

    /**
     * Abort
     * Send the OBEX aborts command to the remote machine
     */
    void Abort();

    /**
     * IsConnected
     * @return ETrue if the client is connected
     */
    TBool IsConnected();

    /**
     * IsBusy
     * @return ETrue if the client is performing some operation.
     */
    TBool IsBusy();

    /**
     * SetPath()
     * Set the current path of the remote device OBEX session.
     */
    void SetPath(const QString & path);

    /**
     * GetFile
     *
     * Request from the server to GET the file defined in the argument
     */
    void GetFile(const QString& localPath, const QString& remoteFileNameFull);

    /**
     * GetByteBuffer()
     *
     * Request from the server to GET the data buffer defined in the argument
     */
    void GetByteBuffer(const QString& dataName);

protected:    // from CActive

    /**
     * DoCancel
     * Cancel any outstanding requests
     */
    void DoCancel();

    /**
     * RunL
     * Respond to an event
     */
    void RunL();

private:    // Constructors

    TBool CheckServiceAvailability();

    /**
     * CMessageClient
     * @param pointer to qt public class
     */
    QBtObjectExchangeClientPrivate( QBtObjectExchangeClient* publicClass );

    /**
     * ConstructL
     * Perform second phase construction of this object
     */
    void ConstructL();

    ///////////////
    ///	Handles ///
    ///////////////
    void HandleServerConnection();
    void HandleObjectSent();
    void HandleDisconnection();
    void HandleObjectReceived();
    void HandleBrowsingFinsished();
    void HandleSettingPathCompletion();

private:    // data
    // This is set when a get operation is requested to the server.
    // Indicates where the file will be saved on the local machine
    // after successfull retrieving.
    QString tmpLocalPath;
    //the remote device server
    //QBtDevice* server;
    //the remote server service to connect to
    //QBtService* service;

    HBufC* iNewFile;

    /**
     * TState
     * The state of the active object, determines behaviour
     * within the RunL method.
     * EWaitingToGetDevice waiting for the user to select a device
     * EGettingDevice searching for a device
     * EGettingService searching for a service
     * EGettingConnection connecting to a service on a remote machine
     * EWaitingToSend sending a message to the remote machine
     * EDisconnecting disconnecting the server
     */
    enum TState
    {
        EGettingConnection,
        EWaitingToSend,
        EWaitingToReceiveFile,
        EWaitingToReceiveData,
        EDisconnecting,
        EBrowsing,
        ESettingPath,
        ENone
    };

    CObex::TSetPathInfo path;

    /**
     * iState the state of the active object,
     * determines behaviour within the RunL method.
     */
    TState iState;

    /**
     * iClient manages the OBEX client connection
     * Owned by QBtObjectExchangeClientPrivate
     */
    CObexClient* iClient;

    /**
     * iCurrObject the OBEX object to transfer
     * Owned by QBtObjectExchangeClientPrivate
     */
    CObexBaseObject* iCurrObject;
    CBufBase* buffer;
    CObex::TSetPathInfo pathInfo;

    QBtObjectExchangeClient* p_ptr;
};

#endif /* QBTOBJECTEXCHANGECLIENT_SYMBIAN_H_ */


code:
/*
 * QBtObjectExchangeClient_win32.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGECLIENT_WIN32_H_
#define QBTOBJECTEXCHANGECLIENT_WIN32_H_

#include <QBtObjectExchangeClient.h>
#include <QBtAuxFunctions.h>
#include <QList>

QBT_NAMESPACE_BEGIN

class QBtObjectExchangeClientPrivate : public QObject
{

Q_OBJECT

public:

    QBtObjectExchangeClientPrivate(QBtObjectExchangeClient* publicClass, QObject* parent=0);
    ~QBtObjectExchangeClientPrivate();

    /**
    * ConnectToServer
    * Connect to the server
    * INFO: if remoteService has no handle information then the classId
    * field is used to connect. (Tested class id working QBtConstants::OBEXFileTransfer)
    *
    * @param remoteDevice the remote server to connect to
    * @param remoteServive the remote service of the server
    */
    void ConnectToServer(const QBtDevice& remoteDevice, const QBtService& remoteService);

    /**
    * Disconnect
    * Disconnect from the remote machine, by sending an
    * OBEX disconnect, and closing the transport on (and
    * regardless of) response from the server.
    */
    void Disconnect();

    /**
    * SendFile
    * Send a file to a service on a remote machine
    */
    void SendFile(const QString& fileName);

    /**
    * SendData
    * Send a byte array to a service on a remote machine
    */
    void SendData(const QByteArray& data, const QString& bufferName);

    /**
    * Abort
    * Send the OBEX aborts command to the remote machine
    */
    void Abort();

    /**
    * IsConnected
    * @return true if the client is connected
    */
    bool IsConnected();

    /**
    * IsBusy
    * @return true if the client is performing some operation.
    */
    bool IsBusy();

    /**
    * SetPath()
    * Set the current path of the remote device OBEX session.
    */
    bool SetPath (const QString & path);

    /**
    * GetFile
    *
    * Request from the server to GET the file defined in the argument
    */
    void GetFile(const QString& localPath, const QString& remoteFileNameFull);

    /**
    * GetByteBuffer()
    *
    * Request from the server to GET the data buffer defined in the argument
    */
    void GetByteBuffer(const QString& dataName);

	/**
	 *	InitiateFolderBrowsing()
	 *
	 *	Browse the files of a selected folder.
	 *
	 *  @param folder The folder path must either be absolute (e.g. \E:\Images), or it must be the name of the folder
	 *  you are going to browse as long as the folder is inside the current working directory of yours.
	 *
	 *  @return QList<QBtRemoteFileInfo*> a list of the files/folders found and their attributes
	 */
	QList<QBtRemoteFileInfo*> InitiateFolderBrowsing(const QString folderPath="");

	/**
	 * GetRemoteWorkingDirectory
	 *
	 * Return as QString holding the absolute path of the current working directory
	 */
	QString GetRemoteWorkingDirectory();

	/**
	 *	locateFiles
	 *
	 *	Locate files/folders that comply to the regex passed as arguments. For example can be used to isolate
	 *	files of specific type.
	 *
	 *	@param regex The regex that describes the files that are needed to be selected. If this parameter is not set, the default
	 *	operation is to select all the files in the specified folder.
	 *
	 *	@param folder The folder path must either be absolute (e.g. \E:\Images), or it must be the name of the folder
	 *  you are going to browse as long as the folder is inside the current working directory of yours. If this parameter is not set,
	 *	the default operation is to search in the current working directory.
	 */
	QList<QBtRemoteFileInfo*> locateFiles(QRegExp* regex=0, QString folder="");

	/**
	 *	batchFileRetrieval
	 *
	 *	Convenient method to retrieve multiple files in the row.
	 *
	 *	@param files The list of files to retrieve
	 *	@param destinationFolder The folder in the local file system where the files will be stored. The files are placed all
	 *	in that directory same directory so the structure in the remote file system is not preserved.
	 */
	void batchFileRetrieval(const QList<QBtRemoteFileInfo*>& files,
		const QString destinationFolder,
		bool retrieveOnlyNewFiles = false);

private:
    // Callback containing file transfer info
    static void FTPStatusCallback(UCHAR ucFirst,
                            UCHAR ucLast,
                            UCHAR* ucFileName,
                            DWORD dwFilesize,
                            DWORD dwCursize);
	static void FTPBrowsingCallback(BTUINT8 *pFileInfo);
	static QDate convertToQDate(FILETIME& time);

signals:
	void folderBrowsingResultElement(const QBtRemoteFileInfo& file);
	void browsingFinished(QString folder, QList<QBtRemoteFileInfo> resutls);

private:
    static bool isBusy;
    size_t maxFileNameSize;
    BTDEVHDL connectionHandle;
    QBtDevice* server;
    QBtService* connectingService;
	QList<QBtRemoteFileInfo*> selectedFiles;

    QBtObjectExchangeClient* p_ptr;

	static QBtObjectExchangeClientPrivate* thisPtr;
	static QList<QBtRemoteFileInfo*>* files;
	static QString currentWorkingDirectory;
};
QBT_NAMESPACE_END

#endif /* QBTOBJECTEXCHANGECLIENT_WIN32_H_ */


code:
/*
 * QBtObjectExchangeServer.cpp
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtObjectExchangeServer.h"
#include <QBtAuxFunctions.h>

#if defined(Q_OS_SYMBIAN)
#include "../QBtObjectExchangeServer_symbian.h"
#elif defined(Q_OS_WIN32)
#include "../QBtObjectExchangeServer_win32.h"
#elif !defined(Q_OS_WIN32) && !defined(Q_OS_SYMBIAN)
#include "../QBtObjectExchangeServer_stub.h"
#endif

QBT_NAMESPACE_BEGIN

//////////////////////////////////////////////////////////
// QBtObjectExchangeServer::QBtObjectExchangeServer()	//
// Defaul constructor									//
//////////////////////////////////////////////////////////
QBtObjectExchangeServer::QBtObjectExchangeServer(QObject *parent) :
    QObject(parent), _advertiser(NULL), _service(NULL), _isConnected(false)
{
#ifdef Q_OS_SYMBIAN
    QT_TRAP_THROWING(_implPtr = QBtObjectExchangeServerPrivate::NewL(this));
#else
    _implPtr = new QBtObjectExchangeServerPrivate(this);
#endif
}

QBtObjectExchangeServer::~QBtObjectExchangeServer()
{
    SafeDelete(_service);

    if(_advertiser)
    {
        _advertiser->stopAdvertising();
        delete _advertiser;
        _advertiser = NULL;
    }

    SafeDelete(_implPtr);
}

void QBtObjectExchangeServer::startServer (const QBtUuid & serviceId, const QString& serviceName)
{
    QBtService service;
    service.setName (serviceName);
    service.setClass (serviceId);

    setTransmittingService (service);

    _implPtr->StartServer();
}

void QBtObjectExchangeServer::stopServer()
{
    _implPtr->Disconnect();
}

bool QBtObjectExchangeServer::isConnected()
{
    return _implPtr->IsConnected();
}

QBtService& QBtObjectExchangeServer::getTransmittingServiceInfo()
{
    if(_service)
        return *_service;
    else
        return *(new QBtService());
}

void QBtObjectExchangeServer::setTransmittingService(const QBtService& service)
{
    SafeDelete(_service);

    _service = new QBtService(service);
}

void QBtObjectExchangeServer::startAdvertisingService(const QBtService& service)
{
    setTransmittingService(service);
    _advertiser = new QBtServiceAdvertiser(this);
    _advertiser->startAdvertising(*_service);
}

void QBtObjectExchangeServer::stopAdvertisingService()
{
    if(_advertiser)
    {
        _advertiser->stopAdvertising();
        delete _advertiser;
        _advertiser = NULL;
    }
}

QBT_NAMESPACE_END


code:
/*
 * QBtObjectExchangeServer_stub.cpp
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtObjectExchangeServer_stub.h"

QBtObjectExchangeServerPrivate::QBtObjectExchangeServerPrivate(
		QBtObjectExchangeServer* publicClass) : p_ptr(publicClass)
{
}

QBtObjectExchangeServerPrivate::~QBtObjectExchangeServerPrivate()
{
}

bool QBtObjectExchangeServerPrivate::StartServer()
{
	return false;
}

void QBtObjectExchangeServerPrivate::Disconnect()
{
}

bool QBtObjectExchangeServerPrivate::IsConnected()
{
	return false;
}


code:
/*
 * QBtObjectExchangeServer_symbian.cpp
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// INCLUDE FILES
#include <es_sock.h>

#include "../QBtObjectExchangeServer_symbian.h"
#include <QBtAuxFunctions.h>

#include <btmanclient.h>
#include <bt_sock.h> // New for 8.0

#include <bautils.h>
#include <eikenv.h>

// ============================ MEMBER FUNCTIONS ==============================

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::NewL()
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
QBtObjectExchangeServerPrivate* QBtObjectExchangeServerPrivate::NewL(
        QBtObjectExchangeServer* publicClass )
{
    QBtObjectExchangeServerPrivate* self = QBtObjectExchangeServerPrivate::NewLC( publicClass );
    CleanupStack::Pop( self );
    return self;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::NewLC()
// Two-phased constructor.
// ----------------------------------------------------------------------------
//
QBtObjectExchangeServerPrivate* QBtObjectExchangeServerPrivate::NewLC(
        QBtObjectExchangeServer* publicClass)
{
    QBtObjectExchangeServerPrivate* self = new ( ELeave ) QBtObjectExchangeServerPrivate( publicClass );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::QBtObjectExchangeServerPrivate()
// Constructor.
// ----------------------------------------------------------------------------
//
QBtObjectExchangeServerPrivate::QBtObjectExchangeServerPrivate (QBtObjectExchangeServer* publicClass )
	:  iObexServer (NULL),
	   iObexBufData (NULL),
	   iTempFile (NULL),
	   iObexBufObject (NULL),
	   iObexBufObjectTransmit (NULL),
	   queueSize (4),
	   bufferGranularity (1024),
	   currentDir (""),
	   p_ptr (publicClass)
{
}

// -----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::ConstructL()
{
    // create file server session
    User::LeaveIfError(iFs.Connect());

    // Create temporarily file
    iTempFile = KTempFile().AllocL();
    //Make sure the file directory exists
    TFileName file = KTempFile();
    TParsePtr parsePtr ( file );
    TFileName filename = parsePtr.DriveAndPath();
    BaflUtils::EnsurePathExistsL( CEikonEnv::Static()->FsSession(), filename);
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::~QBtObjectExchangeServerPrivate()
// Destructor.
// ----------------------------------------------------------------------------
//
QBtObjectExchangeServerPrivate::~QBtObjectExchangeServerPrivate()
{
    if ( iObexServer && iObexServer->IsStarted() )
        iObexServer->Stop();

    SafeDelete(iObexServer);
    //This is used for temp purposes, see TransportDownIndication
    SafeDelete(iObexBufData);
    SafeDelete(iObexBufObject);
    SafeDelete(iTempFile);
    SafeDelete(iObexBufObjectTransmit);

    // parent class variables
    SafeDelete(p_ptr->_service);

    iFs.Delete( *iTempFile ); //Destroy temp file
    iFs.Close();
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::InitialiseServerL()
// Initialises the server.
// ----------------------------------------------------------------------------
//
TBool QBtObjectExchangeServerPrivate::InitialiseServerL()
{
    if ( iObexServer )
    {
        emit p_ptr->error(QBtObjectExchangeServer::QObexServerInUse);
        return false;
    }

    // Set the Socket's security with parameters,
    // Authentication, Encryption, Authorisation and Denied
    // Method also return the channel available to listen to.
    TInt channel (SetSecurityWithChannelL (EFalse, EFalse, ETrue, EFalse ) );

    // start the OBEX server
    TObexBluetoothProtocolInfo obexProtocolInfo;
    obexProtocolInfo.iTransport.Copy (KObexRfcommProtocol);
    obexProtocolInfo.iAddr.SetPort (channel);

    QBtService newService;

    newService.addProtocol (QBtUuid (QBtConstants::L2CAP) );
    newService.addProtocol (QBtUuid (QBtConstants::RFCOMM) );
    newService.addProtocol (QBtUuid (QBtConstants::OBEX) );
    newService.setName (p_ptr->_service->getName());
    newService.setClass (p_ptr->_service->getClass() );

    newService.setPort (channel);

    p_ptr->startAdvertisingService (newService);

    iObexServer = CObexServer::NewL (obexProtocolInfo);
    iObexServer->Start( this );

    return true;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::StartServer()
// Starts the server.
// ----------------------------------------------------------------------------
//
TBool QBtObjectExchangeServerPrivate::StartServer()
{
    TRAPD( err,InitialiseServerL() );

    if ( err != KErrNone )
    {
        emit p_ptr->error(QBtObjectExchangeServer::QObexServerFailedToInitialize);
        Disconnect();

        return false;
    }
    else
    {
        TParsePtrC parsePtr ( iTempFile->Des() );
        TPtrC dir = parsePtr.DriveAndPath();
        currentDir = QString::fromUtf16(dir.Ptr(), dir.Size());
        return true;
    }
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::Disconnect()
// Disconnects the server.
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::Disconnect()
{
    if ( iObexServer && iObexServer->IsStarted() )
        iObexServer->Stop();

    SafeDelete(iObexServer);

    p_ptr->stopAdvertisingService();
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::SetSecurityWithChannelL()
// Sets the security on the channel port and returns the available port.
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::SetSecurityWithChannelL( TBool aAuthentication,
        TBool aEncryption,
        TBool aAuthorisation,
        TBool aDenied )

{

    // Local variable channel to listen to.
    TInt channel = 0;

    RSocketServ socketServer;

    // Connect to SocetServer
    User::LeaveIfError( socketServer.Connect() );
    CleanupClosePushL( socketServer );

    RSocket socket;
    // Open the Socket connection
    User::LeaveIfError( socket.Open( socketServer, KObexRfcommProtocol ) );  // "RFCOMM"
    CleanupClosePushL( socket );

    // Retreive to one channel that is available.
    User::LeaveIfError( socket.GetOpt( KRFCOMMGetAvailableServerChannel,KSolBtRFCOMM, channel ) );

    // Set the Socket's Port.
    TBTSockAddr sockaddr;
    sockaddr.SetPort( channel );

    // Bind and start listeing the port with security setted,
    User::LeaveIfError(socket.Bind(sockaddr));
    User::LeaveIfError(socket.Listen(queueSize ) );

    // setup channel security
    /*TRequestStatus status;
    RBTMan secManager;

    RBTSecuritySettings secDatabase;
    TBTServiceSecurity secSettings;
    // connect to security manager
    User::LeaveIfError(secManager.Connect());
    CleanupClosePushL(secManager);
    User::LeaveIfError(secDatabase.Open(secManager));
    CleanupClosePushL(secDatabase);
    // setup security
    TUid settingsUID;
    settingsUID.iUid = KServiceClass;
    secSettings.SetUid(settingsUID);
    secSettings.SetChannelID(channel);
    secSettings.SetProtocolID(KSolBtRFCOMM);
    secSettings.SetAuthentication(aAuthentication);
    secSettings.SetAuthorisation(aAuthorisation);
    secSettings.SetEncryption(aEncryption);
    secSettings.SetDenied(aDenied);
    // register settings with security
    secDatabase.RegisterService(secSettings, status);
    User::WaitForRequest(status);
    CleanupStack::PopAndDestroy(2,&secManager);//SecDatabase, secManager
    */

    // now close the socket and the socket server
    CleanupStack::PopAndDestroy();  //  socket
    CleanupStack::PopAndDestroy();  //  socketServer

    return channel;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::IsConnected()
// Results true if the server is connected.
// ----------------------------------------------------------------------------
//
TBool QBtObjectExchangeServerPrivate::IsConnected()
{
    return iObexServer != NULL;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::SetListeningQueueSize()
// Set the size of the listening queue of the server.
// @param size
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::SetListeningQueueSize(TInt size)
{
    if(size > 0)
        queueSize = size;
}

QString QBtObjectExchangeServerPrivate::GetCurrentWorkingDirectory()
{
    return currentDir;
}

////////////////////////////////////////////
////	Obex Server Notify Handles		////
////////////////////////////////////////////

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::ErrorIndication()
// Receive error indication.
// It is only called for fatal errors that cause the OBEX connection to terminate.
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::ErrorIndication( TInt aError )
{
    switch(aError)
    {
        case KErrIrObexClientPutPeerAborted:
            emit p_ptr->error(QBtObjectExchangeServer::QObexServerClientAbortedTransfer);
            break;

        case KErrIrObexServerPutPeerAborted:
            emit p_ptr->error(QBtObjectExchangeServer::QObexServerAbortedTransmission);
            break;

        default:
            emit p_ptr->error(QBtObjectExchangeServer::QObexServerSessionError);

    }

    Disconnect();
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::TransportUpIndication()
// Called when the underlying socket transport connection is made from
// a remote client to the server
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::TransportUpIndication()
{
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::TransportDownIndication()
// Transport connection is dropped.
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::TransportDownIndication()
{
    if ( iObexBufObject )
    {
        //transfer cancelled, set temporary
        //buffer so obexobject doesn't create the file again
        SafeDelete(iObexBufData);

        try{
            QT_TRAP_THROWING(
            {
                iObexBufData = CBufFlat::NewL( bufferGranularity );
                iObexBufObject->SetDataBufL( iObexBufData );
            });
        }
        catch(char* str){}
    }

    if ( iTempFile )
        iFs.Delete( *iTempFile );
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::ObexConnectIndication()
// Invoked when an OBEX connection is made from a remote client.
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::ObexConnectIndication(
        const TObexConnectInfo&, const TDesC8& )
{
    emit p_ptr->serverStarted();
    return KErrNone;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::ObexDisconnectIndication()
// OBEX server has been disconnected.
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::ObexDisconnectIndication( const TDesC8& /*aInfo*/ )
{
    emit p_ptr->serverStopped();
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::PutRequestIndication()
// ----------------------------------------------------------------------------
//
CObexBufObject* QBtObjectExchangeServerPrivate::PutRequestIndication()
{
    SafeDelete(iObexBufObject);
    iFs.Delete( *iTempFile );

    //Can't leave here
    try{
        QT_TRAP_THROWING({
                iObexBufObject = CObexBufObject::NewL( NULL );
                //The file is created if it doesn't exist
                iObexBufObject->SetDataBufL( *iTempFile );
                objectSizeBuffer = iObexBufObject->Length();
        });
    }
    catch(char* str)
    {
        p_ptr->error(QBtObjectExchangeServer::QObexServerSessionPutRequestProblem);
        return NULL; // request denied
    }

    emit p_ptr->receivingStarted();
    return iObexBufObject;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::PutPacketIndication()
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::PutPacketIndication()
{
    emit p_ptr->receivingObjectInfo(objectSizeBuffer, iObexBufObject->BytesReceived());
    return KErrNone;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::PutCompleteIndication()
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::PutCompleteIndication()
{
    TFileName file = KTempFile();
    TParsePtr parsePtr ( file );
    TFileName filename = parsePtr.DriveAndPath();
    filename.Append(iObexBufObject->Name());

    SafeDelete(iObexBufObject);

    TInt err2 = BaflUtils::RenameFile(iFs, KTempFile, filename, CFileMan::EOverWrite);
    if( err2 )
    {
        emit p_ptr->error(QBtObjectExchangeServer::QObexServerSessionCopyFileError);
    }

    QString newFileStr = QString::fromUtf16(filename.Ptr(), filename.Size());
    emit p_ptr->receivingStopped(newFileStr);
    return KErrNone;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::GetRequestIndication()
// Called when a full get request has been received from the client.
// ----------------------------------------------------------------------------
//
CObexBufObject* QBtObjectExchangeServerPrivate
::GetRequestIndication( CObexBaseObject* aRequiredObject )
{
    TPtrC16 aName = TPtrC16(aRequiredObject->Name().Ptr());
    SafeDelete(iObexBufObjectTransmit);
    SafeDelete(iObexBufDataTransmit);

    try{
        QT_TRAP_THROWING(
        {
            iObexBufDataTransmit = CBufFlat::NewL( bufferGranularity );
            iObexBufObjectTransmit = CObexBufObject::NewL(NULL);
        });

        TParse parse;
        parse.Set(aName, NULL, NULL);
        TPtrC ptr = parse.NameAndExt();

        QT_TRAP_THROWING(
        {
            iObexBufObjectTransmit->SetNameL( ptr );
            iObexBufObjectTransmit->SetDataBufL(aName, iObexBufDataTransmit);
        });
    }
    catch(char * str)
    {
        emit p_ptr->transmittingRejected();
        return NULL;
    }

    emit p_ptr->transmittingStarted(QString::fromUtf16(aName.Ptr(), aName.Size()));
    return iObexBufObjectTransmit;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::GetPacketIndication()
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::GetPacketIndication()
{
    emit p_ptr->transmittingObjectInfo(0, iObexBufObjectTransmit->BytesSent());
    return KErrNone;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::GetCompleteIndication()
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::GetCompleteIndication()
{
    QString fileSent = "Unknown";
    if(iObexBufObjectTransmit)
        fileSent = QString::fromUtf16(iObexBufObjectTransmit->Name().Ptr(),
                                        iObexBufObjectTransmit->Name().Size());

    emit p_ptr->transmittingStopped(fileSent);
    return KErrNone;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::SetPathIndication()
// ----------------------------------------------------------------------------
//
TInt QBtObjectExchangeServerPrivate::SetPathIndication( const CObex
        ::TSetPathInfo& aPathInfo,
        const TDesC8& aInfo )
{
    try
    {
        QT_TRAP_THROWING(
            BaflUtils::EnsurePathExistsL( CEikonEnv::Static()->FsSession(), aPathInfo.iName));

        currentDir = QString::fromUtf16(aPathInfo.iName.Ptr(), aPathInfo.iName.Size());
    }
    catch(char* str)
    {
        currentDir = "";
        return KErrPathNotFound;
    }
    return KErrNone;
}

// ----------------------------------------------------------------------------
// QBtObjectExchangeServerPrivate::AbortIndication()
// ----------------------------------------------------------------------------
//
void QBtObjectExchangeServerPrivate::AbortIndication()
{
    emit p_ptr->clientAbortedTransmittion();
    SafeDelete(iObexBufObject);

    if(iTempFile)
        iFs.Delete( *iTempFile );
}

// End of File


code:
/*
 * QBtObjectExchangeServer_win32.cpp
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtObjectExchangeServer_win32.h"

QBT_NAMESPACE_BEGIN

QBtObjectExchangeServerPrivate::QBtObjectExchangeServerPrivate(
		QBtObjectExchangeServer* publicClass) : p_ptr(publicClass)
{
}

QBtObjectExchangeServerPrivate::~QBtObjectExchangeServerPrivate()
{
}

bool QBtObjectExchangeServerPrivate::StartServer()
{
	return false;
}

void QBtObjectExchangeServerPrivate::Disconnect()
{
}

bool QBtObjectExchangeServerPrivate::IsConnected()
{
	return false;
}

QBT_NAMESPACE_END


code:
/*
 * QBtObjectExchangeServer.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGESERVER_H_
#define QBTOBJECTEXCHANGESERVER_H_

#include <QBtGlobal.h>
#include <QBtTypes.h>
#include <QBtServiceAdvertiser.h>
#include <QtCore/QObject>

QBT_NAMESPACE_BEGIN

//Forward declaration
class QBtObjectExchangeServerPrivate;

// suggestion: (LV)
//
// use smart pointers for the service advertiser and reset it when
// 'startServer' is called

/**
 * This class is used to create an OBEX server.
 * After instantiation user can call startServer(const QString&)
 * to start the server. From the serviceName argument user can
 * specify the name of the OBEX service which is how the service will
 * be identified by other devices. By default the name is MyOBEX.
 *
 * If sever started successfully and is ready to use then serverStarted() signal is emitted.
 * At destruction time or if user calls stopServer(),terminates the service transmittion
 * and disconnects from any device connected and serverStopped() signal is emitted.
 *
 * All the remaining signals are only for feedback in case any action that is done.
 */
class DLL_EXPORT QBtObjectExchangeServer : public QObject
{
    Q_OBJECT

public:
    enum ErrorCode{
        QObexServerUndefined,
        QObexServerFailedToInitialize,
        QObexServerInUse,
        QObexServerClientAbortedTransfer,
        QObexServerAbortedTransmission,
        QObexServerSessionError,
        QObexServerSessionPutRequestProblem,
        QObexServerSessionCopyFileError
    };

public:
    QBtObjectExchangeServer(QObject* parent);
    ~QBtObjectExchangeServer();

    /**
     * Returns true if the server is connected.
     */
    bool isConnected();

    /**
     * If startServer() function is already called then using this function
     * the user can acquire the information of the transmitting service that
     * represents this server to the outside world.
     */
    QBtService& getTransmittingServiceInfo();

protected:
    void setTransmittingService(const QBtService& service);

    /**
     * Initializes a new advertiser and starts the transmitting of the
     * service passed as argument.
     */
    void startAdvertisingService(const QBtService& service);

    /**
     * Stops the transmittion of the service (if any)
     */
    void stopAdvertisingService();

public slots:
    /**
     *
     * Starts OBEX server by initializing the components needed
     * and by advertising the service by which the server will
     * be identified by other devices.
     */
    void startServer (const QBtUuid & serviceId, const QString& serviceName = "My OBEX Service");

    /**
     * Stops the server, terminates the service transmittion and disconnects
     * from any device connected
     */
    void stopServer();

signals:

    /**
     * Emitted when server is successfully started and ready to use.
     */
    void serverStarted();

    /**
     * Emitted when server is disconnected and stopped
     */
    void serverStopped();

    /**
     * Emitted in case of error
     */
    void error(ErrorCode code);

    /**
     * Emitted as a feedback of the running receive status of
     * any data (file or byte buffer)
     */
    void receivingObjectInfo(int overalDataSize, int bytesSent);

    /**
     * Emitted when the transmittion of a file or byte buffer is started from a remote client
     * to the local device.
     */
    void receivingStarted();

    /**
     * Emitted when a receiving of a file or byte buffer is stopped,
     * being successfull or not.
     *
     * @param receivedFileName
     */
    void receivingStopped (const QString & receivedFileName);

    /**
     * If the server (local device) sends a request to start a transmittion to the remote client
     * connected, the client reserves the right to deny the transmittion before it begins.
     * In that case transmittingRejected() is emitted.
     */
    void transmittingRejected();

    /**
     * Emitted as a feedback of the running transmittion status of
     * any data (file or byte buffer)	 *
     */
    void transmittingObjectInfo(int overalDataSize, int byteSent);

    /**
     * Emitted when a transmittion is started from the local device to a remote device.
     */
    void transmittingStarted (const QString & transmittingfileName);

    /**
     * Emitted upon successfull or not end of transmittion from
     * the local device to a remote client.
     */
    void transmittingStopped (const QString & transmittingfileName);

    /**
     * Emitted if during a transmittion the client aborts it.
     */
    void clientAbortedTransmittion();

private:
    QBtServiceAdvertiser* 			_advertiser;
    QBtService* 					_service;
    QBtObjectExchangeServerPrivate* _implPtr;
    bool 							_isConnected;

    friend class QBtObjectExchangeServerPrivate;
};

QBT_NAMESPACE_END

//Q_DECLARE_METATYPE(QBT_PREPEND_NAMESPACE(QBtObjectExchangeServer))

#endif /* QBTOBJECTEXCHANGESERVER_H_ */


code:
/*
 * QBtObjectExchangeServer_stub.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGESERVER_STUB_H_
#define QBTOBJECTEXCHANGESERVER_STUB_H_

#include "QBtObjectExchangeServer.h"

class QBtObjectExchangeServerPrivate
{
public:
	QBtObjectExchangeServerPrivate(QBtObjectExchangeServer* publicClass);
	~QBtObjectExchangeServerPrivate();

	bool StartServer();
	void Disconnect();
	bool IsConnected();

private:
	QBtObjectExchangeServer p_ptr;
};

#endif /* QBTOBJECTEXCHANGESERVER_STUB_H_ */


code:
/*
 * QBtObjectExchangeServer_symbian.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGESERVER_SYMBIAN_H_
#define QBTOBJECTEXCHANGESERVER_SYMBIAN_H_

#include <e32base.h>
#include <obex.h>
#include <btsdp.h>
#include <btmanclient.h>
#include <e32def.h>
#include <bt_sock.h>

#include "QBtObjectExchangeServer.h"

#ifdef __SERIES60_3X__
_LIT(KTempFile,"c:\\data\\temp.dat");
#else
_LIT(KTempFile,"c:\\system\\data\\temp.dat");
#endif

// CLASS DECLARATIONS
/**
 * QBtObjectExchangeServer
 * Handles the server interactions with the remote client, namely
 * the connection, receiving of messages and disconnection.
 */
class QBtObjectExchangeServerPrivate : public CBase, public MObexServerNotify
{
public: // Constructors and destructor.
	/**
	 * NewL()
	 * Construct a QBtObjectExchangeServerPrivate
	 * @param publicClass to the qt public class
	 * @return a pointer to the created instance of QBtObjectExchangeServerPrivate
	 */
	static QBtObjectExchangeServerPrivate* NewL( QBtObjectExchangeServer* publicClass );

	/**
	 * NewLC()
	 * Construct a QBtObjectExchangeServerPrivate
	 * @param publicClass the qt public class
	 * @return a pointer to the created instance of QBtObjectExchangeServerPrivate
	 */
	static QBtObjectExchangeServerPrivate* NewLC( QBtObjectExchangeServer* publicClass );

	/**
	 * ~QBtObjectExchangeServerPrivate()
	 * Destroy the object and release all memory objects
	 */
	virtual ~QBtObjectExchangeServerPrivate();

	/**
	 * StartServer()
	 * Starts the server
	 */
	TBool StartServer();

	/**
	 * Disconnect()
	 * Disconnects the server
	 */
	void Disconnect();

	/**
	 * IsConnected()
	 * @return ETrue if the server is connected.
	 */
	TBool IsConnected();

	/**
	 * SetListeningQueueSize()
	 * Set the size of the listening queue of the server.
	 * @param size
	 */
	void SetListeningQueueSize(TInt size);

	QString GetCurrentWorkingDirectory();

private:    // Functions from base classes

	/**
	 * QBtObjectExchangeServerPrivate
	 * Constructs this object
	 * @param publicClass the qt public class
	 */
	QBtObjectExchangeServerPrivate( QBtObjectExchangeServer* publicClass );

	/**
	 * ConstructL
	 * 2nd phase construction of this object
	 */
	void ConstructL();

	/**
	 * InitialiseServerL
	 * Initialises the server
	 */
	TBool InitialiseServerL();

	/**
	 * SetSecurityWithChannelL
	 * Sets the security on the channel port
	 * And returns the channel available.
	 * @param aAuthentication is authentication used
	 * @param aEncryption is encryption used
	 * @param aAuthorisation is authorisation used
	 * @param aDenied is denied used
	 * @return an available channel
	 */
	TInt SetSecurityWithChannelL ( TBool aAuthentication,
			TBool aEncryption,
			TBool aAuthorisation,
			TBool aDenied );

private:    // from MObexServerNotify (these methods are defined
	//as private in MObexServerNotify)

	/**
	 * ErrorIndication
	 * Receive error indication.
	 * It is only called for fatal errors that cause the OBEX connection to terminate.
	 * @param aError the error code
	 */
	void ErrorIndication( TInt aError );

	/**
	 * TransportUpIndication
	 * Called when the underlying socket transport connection is made from
	 * a remote client to the server
	 */
	void TransportUpIndication();

	/**
	 * TransportDownIndication
	 * Transport connection is dropped
	 */
	void TransportDownIndication();

	/**
	 * ObexConnectIndication
	 * Invoked when an OBEX connection is made from a remote client
	 * @param aRemoteInfo connection information supplied by
	 * the remote machine
	 * @param aInfo holds further information about the
	 * requested connection
	 * @return system wide error code
	 */
	TInt ObexConnectIndication( const TObexConnectInfo& aRemoteInfo,
			const TDesC8& aInfo );

	/**
	 * ObexDisconnectIndication
	 * OBEX server has been disconnected
	 * @param aInfo contains information about the disconnection
	 */
	void ObexDisconnectIndication( const TDesC8& aInfo );

	/**
	 * PutRequestIndication
	 * @return the CObexBufObject in which to store
	 * the transferred object
	 */
	CObexBufObject* PutRequestIndication();

	/**
	 * PutPacketIndication
	 * @return system wide error code
	 */
	TInt PutPacketIndication();

	/**
	 * PutCompleteIndication
	 * @return system wide error code
	 */
	TInt PutCompleteIndication();

	/**
	 * GetRequestIndication
	 * Called when a full get request has been received from the client
	 * @param aRequestedObject holds details about the requested object
	 * @return the CObexBufObject in which return to the client
	 */
	CObexBufObject* GetRequestIndication( CObexBaseObject* aRequestedObject );

	/**
	 * GetPacketIndication
	 * @return system wide error code
	 */
	TInt GetPacketIndication();

	/**
	 * GetCompleteIndication
	 * @return system wide error code
	 */
	TInt GetCompleteIndication();

	/**
	 * SetPathIndication
	 * @param aPathInfo the information received in a SETPATH command
	 * @return system wide error code
	 */
	TInt SetPathIndication( const CObex::TSetPathInfo& aPathInfo,
			const TDesC8& aInfo );

	/**
	 * AbortIndication
	 * Server has been aborted
	 */
	void AbortIndication();

private:    // data
	// iObexServer manages the OBEX client connection
	// Owned by QBtObjectExchangeServerPrivate
	CObexServer* iObexServer;

	// iObexBufData the raw data that has been transferred
	// Owned by QBtObjectExchangeServerPrivate
	CBufFlat* iObexBufData;

	// Destination where the received file will be stored
	HBufC* iTempFile;

	// iCurrObject the OBEX object that has been transferred
	// Owned by QBtObjectExchangeServerPrivate
	CObexBufObject* iObexBufObject;

	//File Server session
	RFs iFs;

	// iObexBufData the raw data that has been transferred
	// Owned by QBtObjectExchangeServerPrivate
	CBufFlat* iObexBufDataTransmit;

	// Used in Get operations where client requests to retrieve
	// a file from the filesystem of the server
	CObexBufObject* iObexBufObjectTransmit;

	// Size of the listening queue
	TInt queueSize;
	TInt bufferGranularity;
	TInt objectSizeBuffer;

	QString currentDir;

	//QT public parent class
	QBtObjectExchangeServer* p_ptr;
};

#endif /* QBTOBJECTEXCHANGESERVER_SYMBIAN_H_ */


code:
/*
 * QBtObjectExchangeServer_win32.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTOBJECTEXCHANGESERVER_WIN32_H_
#define QBTOBJECTEXCHANGESERVER_WIN32_H_

#include "QBtObjectExchangeServer.h"
#include <QBtAuxFunctions.h>

QBT_NAMESPACE_BEGIN

class QBtObjectExchangeServerPrivate
{
public:
	QBtObjectExchangeServerPrivate(QBtObjectExchangeServer* publicClass);
	~QBtObjectExchangeServerPrivate();

	bool StartServer();
	void Disconnect();
	bool IsConnected();

private:
	QBtObjectExchangeServer p_ptr;
};

QBT_NAMESPACE_END

#endif /* QBTOBJECTEXCHANGESERVER_WIN32_H_ */


code:
/*
 * QBtSerialPortClient.cpp
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtSerialPortClient.h"
#include <QBtAuxFunctions.h>

#if defined(Q_OS_SYMBIAN)
#include "../QBtSerialPortClient_symbian.h"
#elif defined(Q_OS_WIN32)
#include "../QBtSerialPortClient_win32.h"
#elif !defined(Q_OS_WIN32) && !defined(Q_OS_SYMBIAN)
#include "../QBtSerialPortClient_stub.h"
#endif

QBT_NAMESPACE_BEGIN

//////////////////////////////////////////////////
// QBtSerialPortClient::QBtSerialPortClient()	//
// Default constructor							//
//////////////////////////////////////////////////
QBtSerialPortClient::QBtSerialPortClient(QObject *parent) : QObject(parent)
{
#ifdef Q_OS_SYMBIAN
    QT_TRAP_THROWING(_implPtr = QBtSerialPortClientPrivate::NewL(this));
#else
    _implPtr = new QBtSerialPortClientPrivate(this);
#endif
}

QBtSerialPortClient::~QBtSerialPortClient()
{
    SafeDelete(_implPtr);
}

bool QBtSerialPortClient::isConnected()
{
    return _implPtr->IsConnected();
}

void QBtSerialPortClient::connect(const QBtDevice& remoteDevice, const QBtService& remoteService)
{
#ifdef Q_OS_SYMBIAN
	QT_TRAP_THROWING(_implPtr->ConnectL(remoteDevice, remoteService) );
#else
	_implPtr->Connect (remoteDevice, remoteService);
#endif

}

void QBtSerialPortClient::disconnect()
{
    _implPtr->Disconnect();
}

void QBtSerialPortClient::sendData(const QString& data)
{
    _implPtr->SendData(data);
}

void QBtSerialPortClient::sendData (const QByteArray & data)
{
	_implPtr->SendData(data);
}

QBT_NAMESPACE_END


code:
/*
 * QBtSerialPortClient_stub.cpp
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtSerialPortClient_stub.h"

QBtSerialPortClientPrivate::QBtSerialPortClientPrivate(QBtSerialPortClient* publicClass) :
	p_ptr(publicClass)
{
}

QBtSerialPortClientPrivate::~QBtSerialPortClientPrivate()
{

}

bool QBtSerialPortClientPrivate::IsConnected()
{
	return false;
}

void QBtSerialPortClientPrivate::Disconnect()
{

}

void QBtSerialPortClientPrivate::Connect(
		const QBtDevice& remoteDevice,
		const QBtService& remoteService)
{

}

void QBtSerialPortClientPrivate::SendData(const QString& data)
{

}


code:
/*
 * QBtSerialPortClient_symbian.cpp
 *
 *
 *      Author: Ftylitakis Nikolaos, Luis Valente
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtSerialPortClient_symbian.h"
#include <QBtAuxFunctions.h>
#include "utf.h"

// protocol constants
_LIT(KStrRFCOMM, "RFCOMM");

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------

QBtSerialPortClientPrivate* QBtSerialPortClientPrivate::NewL(QBtSerialPortClient* publicClass)
{
    QBtSerialPortClientPrivate* self = QBtSerialPortClientPrivate::NewLC(publicClass);
    CleanupStack::Pop(self);
    return self;
}

QBtSerialPortClientPrivate* QBtSerialPortClientPrivate::NewLC(QBtSerialPortClient* publicClass)
{
    QBtSerialPortClientPrivate* self = new (ELeave) QBtSerialPortClientPrivate(publicClass);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
}

void QBtSerialPortClientPrivate::ConstructL()
{
    if (iSocketServ.Connect() != KErrNone)
        QT_TRYCATCH_LEAVING (emit p_ptr->error(QBtSerialPortClient::ErrorUnavailable) );

    // timer
    iTimer = CPeriodic::NewL (CIdle::EPriorityIdle);

}

QBtSerialPortClientPrivate::QBtSerialPortClientPrivate(QBtSerialPortClient* publicClass)
    : CActive(CActive::EPriorityStandard),
      iState(ENone),
      p_ptr(publicClass),
      iMessage (0)
{
    CActiveScheduler::Add(this);
}

QBtSerialPortClientPrivate::~QBtSerialPortClientPrivate()
{
    Disconnect();

    // delete connect timer
    CancelConnectionTimer();
    delete iTimer;

    // disconnect and kill socket
    if(IsActive())
        Cancel();

    if (iMessage)
        delete iMessage;
}

void QBtSerialPortClientPrivate::DoCancel()
{

}

// ----------------------------------------------------------------------------
// QBtSerialPortClientPrivate::ConnectL(THostName aName, TBTDevAddr aAddr, TInt aPort)
//
// create a connection to given address on given port.
// ----------------------------------------------------------------------------
TBool QBtSerialPortClientPrivate::ConnectL (const QBtDevice& remoteDevice, const QBtService& remoteService)
{
    if (iState != ENone)
    { BT_DEBUG_MSG("warning: trying to connect and state != ENone"); return false; }

    device =  remoteDevice;
    service = remoteService;

    // load protocol, RFCOMM
    //TProtocolDesc pdesc;
    //User::LeaveIfError(iSocketServ.FindProtocol(_L("RFCOMM"), pdesc));

    // see doc: NOTE: Deprecated default connection scenario

    // open socket
    User::LeaveIfError(iSock.Open(iSocketServ, KStrRFCOMM));

    // set address and port
    TBTSockAddr addr;
    addr.SetBTAddr(device.getAddress().convertToSymbianBtDevAddr());
    addr.SetPort(service.getPort());

    // what about these fields?
    //TBTServiceSecurity sec;
    //sec.SetAuthentication(ETrue);
    //sec.SetEncryption(ETrue);
    //addr.SetSecurity(sec);

    _addr = addr;

    // connect socket
    TRequestStatus status;
    iSock.Connect(addr, status);

    iState = EConnecting;

    // start connection timer
    StartConnectionTimer();

    // wait (should we wait here? or use the ActiveObject RunL ?)
    User::WaitForRequest(status);

    // cancel timers
    CancelConnectionTimer();

    if (status != KErrNone)
    {
        BT_DEBUG_MSG (QString ("[connect] error detected: %1").arg (status.Int()) );

        iState = ENone;

        switch (status.Int())
        {
        case KErrTimedOut:
        case KErrCancel:
            QT_TRYCATCH_LEAVING (emit p_ptr->error(QBtSerialPortClient::ErrorConnectionTimeout) );
            break;

        case KErrAlreadyExists:
            QT_TRYCATCH_LEAVING (emit p_ptr->error(QBtSerialPortClient::ErrorAlreadyConnected) );
            break;

        case KErrCouldNotConnect:
        default:
            QT_TRYCATCH_LEAVING (emit p_ptr->error(QBtSerialPortClient::ErrorOpeningConnection) );

        }

        return false;
    }

    // prepare for receive
    ReceiveData();

    // notify
    QT_TRYCATCH_LEAVING (emit p_ptr->connectedToServer() );

    //SetActive();
    return true;
}

// ----------------------------------------------------------------------------
// callback for notifying connection timeout
//
// ----------------------------------------------------------------------------

TInt QBtSerialPortClientPrivate::ConnectTimerCallBack (TAny* aPtr)
{
    BT_DEBUG_MSG ("[timer] entering");

    QBtSerialPortClientPrivate* p = (QBtSerialPortClientPrivate*) aPtr;

    // ignore if connection was successful
    if (p->iState != EConnecting)
    {
        BT_DEBUG_MSG ("[timer] got connection, ignoring timeout event");
        return EFalse;
    }

    BT_DEBUG_MSG ("[timer] canceling ActiveObject");

    if (p->IsActive())
        p->Cancel();

    // change state
    p->iState = ENone;

    BT_DEBUG_MSG ("[timer] emit error signal");

    // emit error
    QT_TRYCATCH_LEAVING (emit p->p_ptr->error (QBtSerialPortClient::ErrorConnectionTimeout));

    BT_DEBUG_MSG ("[timer] end");

    return EFalse;
}

void QBtSerialPortClientPrivate::StartConnectionTimer()
{
    // 30s interval (this should be a parameter)
    TTimeIntervalMicroSeconds32 interval (30 * 1000*1000);

    if (iTimer)
        iTimer->Start (interval, interval, TCallBack (ConnectTimerCallBack, this) );
}

void QBtSerialPortClientPrivate::CancelConnectionTimer()
{
    if (iTimer)
        iTimer->Cancel();
}

// ----------------------------------------------------------------------------
// QBtSerialPortClientPrivate::Disconnect()
//
// disconnect from remote device, shutdown connected socket
// ----------------------------------------------------------------------------
void QBtSerialPortClientPrivate::Disconnect()
{
    if (iState == ENone || iState == EDisconnecting)
        return;

    //
    iState = EDisconnecting;

    // cancel timers
    CancelConnectionTimer();

    // shutdown socket
    TRequestStatus status;

    // cancel all
    iSock.CancelAll();
    iSock.Shutdown(RSocket::ENormal, status);
    User::WaitForRequest(status);
    iSock.Close();

    iState = ENone;

    // check
    if (status == KErrNone)
    {
        QT_TRYCATCH_LEAVING (emit p_ptr->disconnectedFromServer() );
    }
    else
    {
        QT_TRYCATCH_LEAVING (emit p_ptr->error(QBtSerialPortClient::ErrorOnDisconnecting) );
    }

    //iState = EDisconnecting;
    // SetActive();
    // notification will be in RunL with KErrCancel (in case of using SetActive)

}

TBool QBtSerialPortClientPrivate::IsConnected()
{
    return (iState == ESending || iState == EWaiting);
}

// ----------------------------------------------------------------------------
// QBtSerialPortClientPrivate::ReceiveDataL()
//
// wait for and receive data from remote device, read connected socket
// ----------------------------------------------------------------------------
void QBtSerialPortClientPrivate::ReceiveData()
{
    // cancel pending operations
    iSock.CancelRead();
    if(IsActive())
        Cancel();

    // receive data from socket
    iState=EWaiting;
    iSock.RecvOneOrMore(iBuffer, 0, iStatus, iLen);
    SetActive();
}

// ----------------------------------------------------------------------------
// QBtSerialPortClientPrivate::SendData(const QString& data)
//
// send given data to remote device, write to connected socket
// ----------------------------------------------------------------------------

void QBtSerialPortClientPrivate::SendData (const QString& data)
{
    QByteArray array = data.toUtf8();
    SendData (array);
}

// ----------------------------------------------------------------------------
// QBtSerialPortClientPrivate::SendData(const QByteArray& data)
//
// send given data to remote device, write to connected socket
// ----------------------------------------------------------------------------
void QBtSerialPortClientPrivate:: SendData (const QByteArray& data)
{
    TPtrC8 desc8 (reinterpret_cast<const TText8*> (data.constData()), data.size());

    // delete previous data
    if (iMessage)
        delete iMessage;

    iMessage = HBufC8::NewL(desc8.Length());
    iMessage->Des().Copy(desc8);

    // cancel any read requests on socket
    iSock.CancelRead();

    if (IsActive())
        Cancel();

    // send message
    iState = ESending;

    iSock.Write (*iMessage, iStatus);
    SetActive();
}

// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
void QBtSerialPortClientPrivate::RunL()
{
    //BT_DEBUG_MSG (QString ("[RunL status: %1 state: %2]").arg (iStatus.Int()).arg (iState) );

    // cancel possible timers
    CancelConnectionTimer();

    // see what's happened
    if (iStatus != KErrNone)
    {
        switch (iStatus.Int() )
        {
        // we were disconnected (by us)
        case KErrCancel:
        {
            iState = ENone;
            // ignore this signal for now as Disconnect() is using WaitForRequest
            // QT_TRYCATCH_LEAVING (emit p_ptr->disconnectedFromServer() );

            return;
        }

            // we were disconnected by peer
        case KErrDisconnected:
        {
            iState = ENone;
            QT_TRYCATCH_LEAVING (emit p_ptr->connectionResetByPeer() );
            return;
        }

            // not ready to initiate new operation (something is still underway)
        case KErrNotReady:
        {
            // no change in current state (?)
            QT_TRYCATCH_LEAVING (emit p_ptr->error (QBtSerialPortClient::ErrorAlreadyInUse) );
            return;
        }

        }

        BT_DEBUG_MSG (QString ("[RunL error: %1]").arg (iStatus.Int()));

        // get the error
        switch (iState)
        {
        case EConnecting:
        {
            QT_TRYCATCH_LEAVING (emit p_ptr->error (QBtSerialPortClient::ErrorOpeningConnection) );
            break;
        }

        case EWaiting:
        case ESending:
        {
            QT_TRYCATCH_LEAVING (emit p_ptr->error (QBtSerialPortClient::ErrorConnectionError));
            break;
        }

        default:
            QT_TRYCATCH_LEAVING (emit p_ptr->error (QBtSerialPortClient::ErrorUndefinedError));
            break;

        }

        iState = ENone;
        return;
    }

    // no error
    switch (iState)
    {
    // notification should be the last thing because the user might change the state of the
    // object, for example, by calling SendData() in a slot for the 'connectedToServer' signal

    case EConnecting:
    {
        // this one would run only if SetActive() is called in connect()
        iState = EIdle;

        // wait incoming data on socket
        ReceiveData();

        // notify
        QT_TRYCATCH_LEAVING (emit p_ptr->connectedToServer() );
        break;
    }

    case EWaiting:
    {
        // we got incoming data!
        QString receivedString = QString::fromUtf8((const char*)iBuffer.Ptr(), iBuffer.Size());

        // start expecting new incoming data
        ReceiveData();

        // notify
        QT_TRYCATCH_LEAVING (emit p_ptr->dataReceived (receivedString) );
        QT_TRYCATCH_LEAVING (emit p_ptr->dataReceived (QByteArray((const char*)iBuffer.Ptr())) );
        break;
    }
    case ESending:
    {
        // start expecting new incoming data
        ReceiveData();

        // notify
        QT_TRYCATCH_LEAVING  (emit p_ptr->dataSent() );
        break;
    }

    default:
        break;
    }
}


code:
/*
 * QBtSerialPortClient_win32.cpp
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../QBtSerialPortClient_win32.h"

#include <stdio.h>

QBT_NAMESPACE_BEGIN

QBtSerialPortClientPrivate::QBtSerialPortClientPrivate(QBtSerialPortClient* publicClass) :
	p_ptr(publicClass), com(NULL), connectionHandle(BTSDK_INVALID_HANDLE), server(NULL),
	connectingService(NULL), OSComPort(0), serialHandle(INVALID_HANDLE_VALUE), incomingDataBuffer("")
{
	QBtAuxFunctions::InitBthSdk();
	PLugInCommPort();
}

QBtSerialPortClientPrivate::~QBtSerialPortClientPrivate()
{
	CloseSerialPortHandle();
	Disconnect();
	DeinitializeCommPort();

	SafeDelete(server);
	SafeDelete(connectingService);

	QBtAuxFunctions::DeinitBthSdk();
}

void QBtSerialPortClientPrivate::Connect(
		const QBtDevice& remoteDevice,
		const QBtService& remoteService)
{
	if(!remoteDevice.getAddress().isValid())
	{
		emit p_ptr->error(QBtSerialPortClient::ErrorNoDeviceSelected);
		return;
	}

	if(remoteService.getClass() == QBtUuid (QBtConstants::UndefinedClass) &&
		remoteService.getHandle() == 0)
	{
		emit p_ptr->error(QBtSerialPortClient::ErrorNoServiceSelected);
		return;
	}

	server = new QBtDevice(remoteDevice);
	connectingService = new QBtService(remoteService);

	if(com)
		CloseSerialPortHandle();

	if(IsConnected())
		Disconnect();

	if(connectingService->getHandle() != 0)
	{
		if(!ConnectBtSerialPortProfile_Handle())
		{
			emit p_ptr->error(QBtSerialPortClient::ErrorOpeningConnection);
			return;
		}
	}
	else
		if(!ConnectBtSerialPortProfile_ServClass())
		{
			emit p_ptr->error(QBtSerialPortClient::ErrorOpeningConnection);
			return;
		}

	if(!InitializeSerialPortHandle())
	{
		emit p_ptr->error(QBtSerialPortClient::ErrorOpeningConnection);
		return;
	}

}

void QBtSerialPortClientPrivate::Disconnect()
{
	BTINT32 ulRet = BTSDK_FALSE;

	if(connectionHandle != BTSDK_INVALID_HANDLE){
		ulRet = Btsdk_Disconnect(connectionHandle);
		connectionHandle = BTSDK_INVALID_HANDLE;
	}
}

void QBtSerialPortClientPrivate::SendData(const QByteArray& data)
{
	if(!IsConnected() || com == NULL)
	{
		emit p_ptr->error(QBtSerialPortClient::ErrorUnavailable);
		return;
	}

	DWORD size = data.size();

	com->sendData((char*)data.data(),size);
}

void QBtSerialPortClientPrivate::SendData(const QString& data)
{
	if(!IsConnected() || com == NULL)
	{
		emit p_ptr->error(QBtSerialPortClient::ErrorUnavailable);
		return;
	}

	DWORD size = data.size();

	com->sendData((char*)data.toUtf8().constData(),size);

}

bool QBtSerialPortClientPrivate::IsConnected()
{
	return (connectionHandle != BTSDK_INVALID_HANDLE);
}

void QBtSerialPortClientPrivate::CloseSerialPortHandle()
{
	if(com)
	{
		com->disconnect();
		delete com;
		com = NULL;
	}
}

/************************************************************************/
/*               Connection Specific functions		                    */
/************************************************************************/

bool QBtSerialPortClientPrivate::ConnectBtSerialPortProfile_Handle()
{
	BTINT32 ulRet = BTSDK_FALSE;
	BtSdkSPPConnParamStru sppStru = {0};
	sppStru.size = sizeof(BtSdkSPPConnParamStru);
	sppStru.com_index = (BTUINT8)OSComPort ;

	int connCnt = 0;
	do
	{
		ulRet = Btsdk_Connect(connectingService->getHandle(), (BTUINT32)&sppStru, &connectionHandle );
		connCnt++;
	}while(ulRet != BTSDK_OK && connCnt < 5);

	connCnt = 0;
	if(ulRet != BTSDK_OK)
		emit p_ptr->error(QBtSerialPortClient::ErrorOpeningConnection);

	return (ulRet == BTSDK_OK);
}

bool QBtSerialPortClientPrivate::ConnectBtSerialPortProfile_ServClass()
{
	BTINT32 ulRet = BTSDK_FALSE;
	BtSdkSPPConnParamStru sppStru = {0};
	sppStru.size = sizeof(BtSdkSPPConnParamStru);
	sppStru.com_index = (BTUINT8)OSComPort ;
	//BTUINT16 service = BTSDK_CLS_SERIAL_PORT;

	BTDEVHDL devHandle = QBtAuxFunctions::GetDeviceHandle(server->getAddress());

	int connCnt = 0;
	do
	{
		ulRet = Btsdk_ConnectEx(devHandle, connectingService->getClass().get(), (BTUINT32)&sppStru, &connectionHandle );
		connCnt++;
	}while(ulRet != BTSDK_OK && connCnt < 5);

	connCnt = 0;
	if(ulRet != BTSDK_OK)
		emit p_ptr->error(QBtSerialPortClient::ErrorOpeningConnection);

	return (ulRet == BTSDK_OK);
}

/************************************************************************/
/*					Virtual comm port manipulation                      */
/************************************************************************/

bool QBtSerialPortClientPrivate::PLugInCommPort()
{
	BTINT32 ulRet = BTSDK_FALSE;
	BTUINT32 s_ComSerialNum = 0;

	//----------------------------connect------------------------//
	s_ComSerialNum = Btsdk_GetASerialNum();
	Btsdk_PlugInVComm(s_ComSerialNum , &OSComPort ,1 ,COMM_SET_RECORD|COMM_SET_USAGETYPE, 2200);
	ulRet = Btsdk_InitCommObj((BTUINT8)OSComPort, BTSDK_CLS_SERIAL_PORT);
	ulRet = BTSDK_OK;

	if(ulRet != BTSDK_OK)
	{
		emit p_ptr->error(QBtSerialPortClient::ErrorUnableToInitializePort);
		return false;
	}

	return true;
}

void QBtSerialPortClientPrivate::DeinitializeCommPort()
{
	BTINT32 ulRet = BTSDK_FALSE;
	BTUINT32 serialNum = 0;

	if(OSComPort == 0)
		return;

	serialNum = Btsdk_CommNumToSerialNum(OSComPort);
	Btsdk_PlugOutVComm(serialNum, COMM_SET_RECORD);
	ulRet = Btsdk_DeinitCommObj(OSComPort);
}

bool QBtSerialPortClientPrivate::InitializeSerialPortHandle()
{
	int	erreur;

/*#ifdef _DEBUG
	char szPort[10];
	wsprintf( szPort, "\\\\.\\COM%d", OSComPort );
#endif
#ifndef _DEBUG*/
	char szPort[10];
	sprintf( szPort, "\\\\.\\COM%d", OSComPort );
//#endif

	if(com != NULL)
		return false;

	com = new Tserial_event();

	if(com)
	{
		com->setManager(&QBtSerialPortClientPrivate::SerialEventManager);

		erreur = com->connect(szPort, 19200, SERIAL_PARITY_NONE, 8, false);

		if(!erreur)
		{
			com->setRxSize(1);
			com->owner = (void*) this;
		}

		return (!erreur);
	}
	else
		return false;

}

/************************************************************************/

/************************************************************************/
/*                       Serial Port event handling                     */
/************************************************************************/

void QBtSerialPortClientPrivate::SerialEventManager(uint32 object, uint32 event)
{
	Tserial_event *com;
	QBtSerialPortClientPrivate *handlingObject;

	com = (Tserial_event *) object;
	if (com!=0)
	{
		handlingObject = (QBtSerialPortClientPrivate *) com->owner;
		if (handlingObject!=0)
			handlingObject->SerialCallback(com, event);
	}
}

void QBtSerialPortClientPrivate::SerialCallback(Tserial_event *com_source, uint32 event)
{
	char *buffer;
	int   size;
	Tserial_event *com;

	com = (Tserial_event *) com_source;
	if (com!=0)
	{
		switch(event)
		{
		case  SERIAL_CONNECTED  :
			emit p_ptr->connectedToServer();
			break;
		case  SERIAL_DISCONNECTED  :
			emit p_ptr->disconnectedFromServer();
			break;
		case  SERIAL_DATA_SENT  :
			emit p_ptr->dataSent();
			break;
		case  SERIAL_DATA_ARRIVAL  :
			size   = com->getDataInSize();
			buffer = com->getDataInBuffer();

			if ((size>0) && (buffer!=0))
			{
				//if(buffer[0] == '\0')
				//{
				//	incomingDataBuffer.clear();
				//}
				//else
				//{
					QString newArray = QString::fromUtf8(buffer, size);
					emit p_ptr->dataReceived(newArray);
					emit p_ptr->dataReceived(QByteArray(buffer));
				//	incomingDataBuffer.append(newArray);
				//}
			}
			else
				emit p_ptr->error(QBtSerialPortClient::ErrorUndefinedError);

			com->dataHasBeenRead();
			break;
		}
	}
}

/************************************************************************/

QBT_NAMESPACE_END


code:
/*
 * QBtSerialPortClient.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTSERIALPORTCLIENT_H_
#define QBTSERIALPORTCLIENT_H_

#include <QBtGlobal.h>
#include <QBtTypes.h>
#include <QtCore/QObject>
#include <QtCore/QByteArray>

QBT_NAMESPACE_BEGIN

//forward declaration
class QBtSerialPortClientPrivate;

/**
 * Class that provides the mechanism to connect to a bluetooth serial port
 * server and communicate.
 *
 * Calling connect(const QBtDevice&, const QBtService&) user specifies
 * on which device to connect(on which serial port server) and on which
 * bluetooth service. The QBtDevice instance of the server can be
 * aquired using QBtDeviceDiscoverer or user can create his own instance
 * and set at least the QBtAddress field. Also the QBtService can be
 * aquired using QBtServiceDiscoverer targeting the beforementioned device.
 *
 * On successfull connection, connectedToServer() singal is emitted and
 * user is able to sendData(const QString&) to the server. If successfull
 * then dataSend() signal is emitted.
 *
 * If data is recieved from the server, dataReceived(const QString) signal is
 * emitted containing the bytes recieved. At this point user must be carefull
 * to read the data recieved using the same encoding as the sender (in this
 * case serial port server). QString contains all the necessary functions for
 * character encoding that is why is QString is used instead of QByteArray.
 *
 * When connection is no longer needed, disconnect() can be called.
 * disconnectedFromServer() is then emitted.
 *
 * In case of error error(QBtSerialPortClient::ErrorCode) signal is emitted.
 */
class DLL_EXPORT QBtSerialPortClient : public QObject
{
    Q_OBJECT

public:
    enum ErrorCode
    {
        ErrorAlreadyInUse,
        ErrorNotSupported,
        ErrorUnavailable,
        ErrorOpeningConnection,
        ErrorAlreadyConnected,
        ErrorUndefinedError,
        ErrorUnableToInitializePort,
        ErrorNoDeviceSelected,
        ErrorNoServiceSelected,
        ErrorConnectionError,
        ErrorConnectionTimeout,
        ErrorOnDisconnecting
    };

public:
    /**
     * A Serial port client.
     * According to the bluetooth specification, up to 7 instances of this class
     * can be connected simultaneously to other servers.
     */
    QBtSerialPortClient(QObject* parent);

    /**
     * Destructor.
     *
     * If isConnected() then disconnect() is called.
     */
    ~QBtSerialPortClient();

    /**
     * isConnected()
     *
     * Returns whether or not the client is connected to a remote server.
     */
    bool isConnected();

public slots:
    /**
     * connect()
     * RemoteDevice must contain at least the device address.
     * and remoteService at least a class ID (in case of SerialPort port field is also needed).
     * The remoteService info can be acquired by QBtServiceDiscoverer.
     */
    void connect(const QBtDevice& remoteDevice, const QBtService& remoteService);

    /**
     * disconnect()
     * Disconnects from the remote server if previously succusfully connected.
     */
    void disconnect();

    /**
     * sendData()
     * Send a string to the server.
     * If text is transmitted, it is up to the user to decide which text encoding to use.
     * Upon succesfull transmittion, dataSent() signal is emitted.
     */
    void sendData(const QString& data);

    /**
     * Send a array of bytes to the server, as is.
     * Upon succesfull transmittion, dataSent() signal is emitted.
     */
    void sendData (const QByteArray & data);

signals:
    /**
     * Emitted when successfully disconnected from the remote server (initiated from client).
     */
    void disconnectedFromServer();

    /**
     * Emitted when the server initiated a disconnection.
     */
    void connectionResetByPeer ();

    /**
     * Emitted when successfully connected to the remote server.
     */
    void connectedToServer();

    /**
     * Emitted when after sendData(QString) is called, if the data is send
     * successfully.
     */
    void dataSent();

    /**
     * Emitted as feedback when data are received successfully.
     */
    void dataReceived(const QString & data);

    /**
     * Emitted the instance the dataReceived(const QString&) signal is emitted. User
     * decides which format wants to read.
     */
    void dataReceived(const QByteArray & data);

    /**
     * Emitted in case of error.
     */
    void error(QBtSerialPortClient::ErrorCode error);

private:
    friend class QBtSerialPortClientPrivate;
    QBtSerialPortClientPrivate* _implPtr;
};

QBT_NAMESPACE_END

//Q_DECLARE_METATYPE(QBT_PREPEND_NAMESPACE(QBtSerialPortClient))

#endif /* QBTSERIALPORTCLIENT_H_ */


code:
/*
 * QBtSerialPortClient_stub.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTSERIALPORTCLIENT_STUB_H_
#define QBTSERIALPORTCLIENT_STUB_H_

#include "./QBtSerialPortClient.h"

class QBtSerialPortClientPrivate
{
public:
	QBtSerialPortClientPrivate(QBtSerialPortClient* publicClass);
	~QBtSerialPortClientPrivate();

	bool IsConnected();
	void Disconnect();
	void Connect(const QBtDevice& remoteDevice, const QBtService& remoteService);
	void SendData(const QString& data);

private:
	QBtSerialPortClient* p_ptr;
};

#endif /* QBTSERIALPORTCLIENT_STUB_H_ */


code:
/*
 * QBtSerialPortClient_symbian.h
 *
 *
 *      Author: Ftylitakis Nikolaos, Luis Valente
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTSERIALPORTCLIENT_SYMBIAN_H_
#define QBTSERIALPORTCLIENT_SYMBIAN_H_

#include "QBtSerialPortClient.h"
#include <QTimer.h>

#include <e32base.h>
#include <es_sock.h>
#include <btdevice.h>
#include <bt_sock.h>

class QBtSerialPortClientPrivate : public CActive
{

public:

	/*!
	 * NewL()
	 *
	 *  Create new QBtSerialPortClientPrivate object
	 * return a pointer to the created instance of QBtSerialPortClientPrivate
	 */
	static QBtSerialPortClientPrivate* NewL(QBtSerialPortClient* publicClass);

	/*!
	 * NewLC()
	 *
	 */
	static QBtSerialPortClientPrivate* NewLC(QBtSerialPortClient* publicClass);

	/*!
	 * ~QBtSerialPortClientPrivate()
	 *
	 *  Destroy the object and release all memory objects
	 */
	~QBtSerialPortClientPrivate();

	/*!
	 * ConnectL()
	 *
	 *  Creates a connection to given remote address on given port.
	 *
	 * param aName the name of the slave to connect to.
	 * param aAddr the address of the slave to connect to.
	 * param aPort the port on slave to connect to.
	 *
	 * return the status of connection attempt
	 */
	TBool ConnectL(const QBtDevice& remoteDevice, const QBtService& remoteService);

	/*!
	 * Disconnect()
	 *
	 *  Disconnects connector from slave.
	 */
	void Disconnect();

	/*!
	 * SendDataL()
	 *
	 *  Sends given data to slave.
	 *
	 * param aData the message to send to slave.
	 */
	void SendData(const QString& data);
	void SendData(const QByteArray& data);

	/*!
	 * IsConnected()
	 *
	 * return the connection state
	 */
	TBool IsConnected();

protected:

	/*!
	 * RunL()
	 *
	 *  Handle the active objects request completion.
	 */
	void RunL();

	/*!
	 * DoCancel()
	 *
	 *  Cancels the outstanding request on active object.
	 */
	void DoCancel();

private:

	/*!
	 * QBtSerialPortClientPrivate()
	 *
	 *  Perform the first phase of two phase construction
	 *
	 * @param the qt public class
	 */
	QBtSerialPortClientPrivate(QBtSerialPortClient* publicClass);

	/*!
	 * ConstructL()
	 *
	 */
	void ConstructL();

	/*!
	 * ReceiveData()
	 *
	 *  Wait for and receive data from slave.
	 */
	void ReceiveData();

private:

	static TInt ConnectTimerCallBack (TAny* aPtr);

	void StartConnectionTimer();
	void CancelConnectionTimer();

private: // data

	// remote device
	QBtDevice device;
	// remote service
	QBtService service;
	// connecting socket
	RSocket iSock;
	// buffer holding received data
	TBuf8<128> iBuffer;
	// length of received data
	TSockXfrLength iLen;
	// socket server handle
	RSocketServ iSocketServ;

	// the state of the connector
	enum TState
	{
		ENone = 1,
		EIdle,
		EConnecting,
		EDisconnecting,
		EWaiting,
		ESending
	};

	TState iState;

	QBtSerialPortClient* p_ptr;

	CPeriodic* iTimer;

	TBTSockAddr _addr;

	HBufC8* iMessage;
};

#endif /* QBTSERIALPORTCLIENT_SYMBIAN_H_ */


code:
/*
 * QBtSerialPortClient_win32.h
 *
 *
 *      Author: Ftylitakis Nikolaos
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef QBTSERIALPORTCLIENT_WIN32_H_
#define QBTSERIALPORTCLIENT_WIN32_H_

//#if defined(Q_CC_MSVC)
	#include "QBtSerialPortClient.h"
	#include "Tserial_event.h"
//#else
//	#include "./QBtSerialPortClient.h"
//	#include "../../WinSerialPort/Tserial_event.h"
//#endif

#include <QBtAuxFunctions.h>

QBT_NAMESPACE_BEGIN

class QBtSerialPortClientPrivate
{
public:
	QBtSerialPortClientPrivate(QBtSerialPortClient* publicClass);
	~QBtSerialPortClientPrivate();

	bool IsConnected();
	void Disconnect();
	/**
	* Connect()
	* Connect to the server
	* INFO: if remoteService has no handle information then the classId
	* field is used to connect. (Tested class id working QBtConstants::SerialPort)
	*
	* @param remoteDevice the remote server to connect to
	* @param remoteServive the remote service of the server
	*/
	void Connect(const QBtDevice& remoteDevice, const QBtService& remoteService);
	void SendData(const QString& data);
	void SendData(const QByteArray& data);

private:
	/**
	 * PLugInCommPort()
	 * Plug in a virtual comm port given by the OS.
	 * This comm port will be used later on to communicate.
	 */
	bool PLugInCommPort();
	void DeinitializeCommPort();

	/*
	 * ConnectBtSerialPortProfile_Handle()
	 * This function is called when remoteService has a valid handle.
	 * and the connecting port.
	 */
	bool ConnectBtSerialPortProfile_Handle();

	/*
	 * ConnectBtSerialPortProfile_ServClass()
	 * Used when the only info provided about the service is its class
	 * and the connecting port.
	 */
	bool ConnectBtSerialPortProfile_ServClass();

	bool InitializeSerialPortHandle();
	void CloseSerialPortHandle();

	static void SerialEventManager(uint32 object, uint32 event);
	void SerialCallback(Tserial_event *com_source, uint32 event);

private:
	// the server device info
	QString incomingDataBuffer;
	BTUINT32 OSComPort;
	HANDLE serialHandle;

	QBtDevice* server;
	QBtService* connectingService;
	BTCONNHDL connectionHandle;
	Tserial_event *com;

	// Qt parent public class
	QBtSerialPortClient* p_ptr;
};

QBT_NAMESPACE_END

#endif /* QBTSERIALPORTCLIENT_WIN32_H_ */