Bluetooth connection working (Linux).

Change-Id: Iac77c3ce0ab0ea7bda3105c58859888e55e64d2d
This commit is contained in:
Andrzej J.R. Hunt
2012-08-22 12:44:42 +02:00
parent 9d73597289
commit 1db66c2a1a
13 changed files with 230 additions and 121 deletions

View File

@@ -8,6 +8,8 @@
*/
package org.libreoffice.impressremote.communication;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.UUID;
@@ -15,6 +17,8 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
/**
* Standard Network client. Connects to a server using Sockets.
@@ -31,67 +35,77 @@ public class BluetoothClient extends Client {
super(aContext);
try {
BluetoothAdapter aAdapter = BluetoothAdapter.getDefaultAdapter();
System.out.println("Attemtping to connect to:" + bluetoothAddress);
BluetoothDevice aDevice = aAdapter
.getRemoteDevice(bluetoothAddress);
aAdapter.cancelDiscovery();
BluetoothSocket aSocket = aDevice
.createRfcommSocketToServiceRecord(UUID
.fromString("00001101-0000-1000-8000-00805f9b34fb"));
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
aSocket.connect();
// mSocket = aSocket;
System.out.println("Connected");
mInputStream = aSocket.getInputStream();
mReader = new BufferedReader(new InputStreamReader(mInputStream,
CHARSET));
mOutputStream = aSocket.getOutputStream();
// mOutputStream.write(20);
// mOutputStream.write(20);
// mOutputStream.write(20);
// mOutputStream.flush();
// System.out.println("reading");
// while (true) {
// System.out.println(mInputStream.read());
// }
String aTemp = mReader.readLine();
System.out.println("SF:waited");
if (!aTemp.equals("LO_SERVER_SERVER_PAIRED")) {
return;
}
while (mReader.readLine().length() != 0) {
// Get rid of extra lines
}
Intent aIntent = new Intent(
CommunicationService.MSG_PAIRING_SUCCESSFUL);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
startListening();
// Pairing.
// Random aRandom = new Random();
// String aPin = "" + (aRandom.nextInt(9000) + 1000);
// while (aPin.length() < 4) {
// aPin = "0" + aPin; // Add leading zeros if necessary
// }
// Intent aIntent = new Intent(
// CommunicationService.MSG_PAIRING_STARTED);
// aIntent.putExtra("PIN", aPin);
// mPin = aPin;
// LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
// // Send out
// String aName = CommunicationService.getDeviceName(); // TODO: get the proper name
// sendCommand("LO_SERVER_CLIENT_PAIR\n" + aName + "\n" + aPin
// + "\n\n");
//
// // Wait until we get the appropriate string back...
// System.out.println("SF:waiting");
// String aTemp = mReader.readLine();
// System.out.println("SF:waited");
// if (!aTemp.equals("LO_SERVER_SERVER_PAIRED")) {
// return;
// } else {
//
// }
// while (mReader.readLine().length() != 0) {
// // Get rid of extra lines
// System.out.println("SF: empty line");
// }
// System.out.println("SD: empty");
// startListening();
} catch (Exception e) {
e.printStackTrace();
}
// BluetoothSocket aSocket = new BluetoothClient(bluetoothAddress, aContext)
// .createRfcommSocketToServiceRecord(UUID
// .fromString("00001101-0000-1000-8000-00805F9B34F
// }
// try {
// mSocket = new Socket(ipAddress, PORT);
// mInputStream = mSocket.getInputStream();
// mReader = new BufferedReader(new InputStreamReader(mInputStream,
// CHARSET));
// mOutputStream = mSocket.getOutputStream();
// // Pairing.
// Random aRandom = new Random();
// String aPin = "" + (aRandom.nextInt(9000) + 1000);
// while (aPin.length() < 4) {
// aPin = "0" + aPin; // Add leading zeros if necessary
// }
// Intent aIntent = new Intent(
// CommunicationService.MSG_PAIRING_STARTED);
// aIntent.putExtra("PIN", aPin);
// mPin = aPin;
// LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
// // Send out
// String aName = CommunicationService.getDeviceName(); // TODO: get the proper name
// sendCommand("LO_SERVER_CLIENT_PAIR\n" + aName + "\n" + aPin
// + "\n\n");
//
// // Wait until we get the appropriate string back...
// System.out.println("SF:waiting");
// String aTemp = mReader.readLine();
// System.out.println("SF:waited");
// if (!aTemp.equals("LO_SERVER_SERVER_PAIRED")) {
// return;
// } else {
// aIntent = new Intent(
// CommunicationService.MSG_PAIRING_SUCCESSFUL);
// LocalBroadcastManager.getInstance(mContext).sendBroadcast(
// aIntent);
// }
// while (mReader.readLine().length() != 0) {
// // Get rid of extra lines
// System.out.println("SF: empty line");
// }
// System.out.println("SD: empty");
// startListening();
// } catch (UnknownHostException e) {
// // TODO Tell the user we have a problem
// e.printStackTrace();
// } catch (IOException e) {
// // TODO As above
// e.printStackTrace();
// }
}

View File

@@ -11,6 +11,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
public class BluetoothFinder {
@@ -32,9 +33,8 @@ public class BluetoothFinder {
return; // No bluetooth adapter found (emulator, special devices)
}
System.out.println("BT:Discovery starting");
IntentFilter aFilter = new IntentFilter(
BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
aFilter.addAction(BluetoothDevice.ACTION_FOUND);
IntentFilter aFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
aFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
mContext.registerReceiver(mReceiver, aFilter);
mAdapter.enable();
@@ -64,7 +64,7 @@ public class BluetoothFinder {
@Override
public void onReceive(Context context, Intent aIntent) {
// TODO Auto-generated method stub
System.out.println("Received intent");
System.out.print("Received intent<<<");
System.out.println(aIntent.getAction());
if (aIntent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
BluetoothDevice aDevice = (BluetoothDevice) aIntent.getExtras()
@@ -77,7 +77,8 @@ public class BluetoothFinder {
System.out.println("Now we have: " + mServerList.size());
Intent aNIntent = new Intent(
CommunicationService.MSG_SERVERLIST_CHANGED);
mContext.sendBroadcast(aNIntent);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(
aNIntent);
// System.out.println("Found " + aDevice.getName());
// try {
// // "f36d0a20-e876-11e1-aff1-0800200c9a66"

View File

@@ -35,6 +35,8 @@ public class Receiver {
}
public void parseCommand(ArrayList<String> aCommand) {
if (aCommand.size() == 0)
return; // E.g. if empty line received for whatever reason.
String aInstruction = aCommand.get(0);
if (aInstruction.equals("slideshow_started")) {
int aSlideShowlength = Integer.parseInt(aCommand.get(1));

View File

@@ -13,6 +13,7 @@ import org.libreoffice.impressremote.communication.Server.Protocol;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
public class ServerFinder {
@@ -169,7 +170,7 @@ public class ServerFinder {
*/
private void notifyActivity() {
Intent aIntent = new Intent(CommunicationService.MSG_SERVERLIST_CHANGED);
mContext.sendBroadcast(aIntent);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
}
public Collection<Server> getServerList() {

View File

@@ -22,29 +22,60 @@
#include "bluetooth/rfcomm.h"
#endif
#include "Communicator.hxx"
using namespace sd;
BluetoothServer::BluetoothServer():
Thread( "BluetoothServer" )
BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators ):
Thread( "BluetoothServer" ),
mpCommunicators( pCommunicators )
{
}
BluetoothServer::~BluetoothServer()
{
}
struct oslSocketImpl {
int m_Socket;
int m_nLastError;
void* m_CloseCallback;
void* m_CallbackArg;
oslInterlockedCount m_nRefCount;
#if defined(LINUX)
sal_Bool m_bIsAccepting;
sal_Bool m_bIsInShutdown;
#endif
};
void BluetoothServer::execute()
{
#ifdef LINUX
// g_type_init();
// GError* aError = NULL;
// GDBusConnection* aConnection = g_bus_get_sync( G_BUS_TYPE_SYSTEM, NULL, &aError );
// if ( aError )
// {
// fprintf( stderr, aError->message );
// g_error_free( aError );
// }
g_type_init();
GError* aError = NULL;
GDBusConnection* aConnection = g_bus_get_sync( G_BUS_TYPE_SYSTEM, NULL, &aError );
if ( aError )
{
fprintf( stderr, aError->message );
g_error_free( aError );
}
GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
"org.bluez", "/", "org.bluez.Manager",
"DefaultAdapter", NULL,
G_VARIANT_TYPE_TUPLE,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
if ( aError )
{
fprintf( stderr, aError->message );
g_error_free( aError );
}
fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );
// GDBusObjectManager* aManager = g_dbus_object_manager_client_new_sync( aConnection,
// G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.bluez.Manager", "/org/bluez",
// NULL, NULL, NULL, NULL, &aError );
@@ -53,14 +84,21 @@ void BluetoothServer::execute()
// fprintf( stderr, aError->message );
// g_error_free( aError );
// }
//
// GVariant *aRet = g_dbus_connection_call_sync( aConnection,
// "org.bluez", "/", "org.bluez.Database",
// "AddServiceRecordFromXml",
// g_variant_new ("s",
// ""),,
// G_VARIANT_TYPE_UINT32,
// G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
GVariant *aRecordHandle = g_dbus_connection_call_sync( aConnection,
"org.bluez", g_variant_get_string( aAdapterName, NULL ), "org.bluez.Service",
"AddRecord",
g_variant_new("(s)",
"<?xml version='1.0' encoding= 'UTF-8' ?><record><attribute id='0x0001'><sequence><uuid value='0x1101' /></sequence></attribute><attribute id='0x0004'><sequence><sequence><uuid value='0x0100' /></sequence><sequence><uuid value='0x0003' /><uint8 value='0x05' /></sequence></sequence></attribute><attribute id='0x0005'><sequence><uuid value='0x1002' /></sequence></attribute><attribute id='0x0006'><sequence><uint16 value='0x656e' /><uint16 value='0x006a' /><uint16 value='0x0100' /></sequence></attribute><attribute id='0x0009'><sequence><sequence><uuid value='0x1101' /><uint16 value='0x0100' /></sequence></sequence></attribute><attribute id='0x0100'><text value='Serial Port' /></attribute><attribute id='0x0101'><text value='COM Port' /></attribute></record>"),
G_VARIANT_TYPE_TUPLE,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
if ( aError )
{
fprintf( stderr, aError->message );
g_error_free( aError );
}
(void) aRecordHandle;
// Remove handle again at some point
// g_variant_unref( aRet );
// fprintf( stderr, "Manager gotten\n" );
//
@@ -125,8 +163,8 @@ void BluetoothServer::execute()
sockaddr_rc aAddr;
aAddr.rc_family = AF_BLUETOOTH;
// aAddr.rc_bdaddr = *BDADDR_ANY;
aAddr.rc_channel = 1;
aAddr.rc_bdaddr = {{0, 0, 0, 0, 0, 0}}; // BDADDR_ANY is broken
aAddr.rc_channel = 5;
if ( bind( aSocket, (sockaddr*) &aAddr, sizeof(aAddr)) < 0 ) {
close( aSocket );
@@ -141,12 +179,18 @@ void BluetoothServer::execute()
sockaddr_rc aRemoteAddr;
socklen_t aRemoteAddrLen = sizeof(aRemoteAddr);
if ( accept(aSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen) < 0 )
int bSocket;
if ( (bSocket = accept(aSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 )
{
close( aSocket );
return;
} else {
fprintf( stderr, "Accepted Bluetooth\n" );
Communicator* pCommunicator = new Communicator( new BufferedStreamSocket( bSocket) );
mpCommunicators->push_back( pCommunicator );
pCommunicator->launch();
}
#endif
@@ -163,14 +207,14 @@ void BluetoothServer::execute()
BluetoothServer *sd::BluetoothServer::spServer = NULL;
void BluetoothServer::setup()
void BluetoothServer::setup( std::vector<Communicator*>* pCommunicators )
{
if (spServer)
return;
spServer = new BluetoothServer();
spServer = new BluetoothServer( pCommunicators );
spServer->launch();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -10,16 +10,19 @@
#define _SD_IMPRESSREMOTE_BLUETOOTHSERVER_HXX
#include <salhelper/thread.hxx>
#include <vector>
namespace sd
{
class Communicator;
class BluetoothServer:
public salhelper::Thread
{
public:
static void setup();
static void setup( std::vector<Communicator*>* pCommunicators );
private:
BluetoothServer();
BluetoothServer( std::vector<Communicator*>* pCommunicators );
~BluetoothServer();
static BluetoothServer *spServer;
@@ -27,6 +30,7 @@ namespace sd
public:
private:
void execute();
std::vector<Communicator*>* mpCommunicators;
};
}

View File

@@ -11,6 +11,12 @@
#include <algorithm>
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <unistd.h>
#endif
using namespace sd;
using namespace std;
using namespace osl;
@@ -19,10 +25,36 @@ BufferedStreamSocket::BufferedStreamSocket( const osl::StreamSocket &aSocket ):
StreamSocket( aSocket ),
aRet( 0 ),
aRead( 0 ),
aBuffer()
aBuffer(),
mSocket( 0 ),
usingCSocket( false)
{
}
BufferedStreamSocket::BufferedStreamSocket( int aSocket ):
StreamSocket(),
aRet( 0 ),
aRead( 0 ),
aBuffer(),
mSocket( aSocket ),
usingCSocket( true )
{
}
void BufferedStreamSocket::getPeerAddr(osl::SocketAddr& rAddr)
{
assert ( !usingCSocket );
StreamSocket::getPeerAddr( rAddr );
}
sal_Int32 BufferedStreamSocket::write( const void* pBuffer, sal_uInt32 n )
{
if ( !usingCSocket )
return StreamSocket::write( pBuffer, n );
else
return ::write( mSocket, pBuffer, (size_t) n );
}
sal_Int32 BufferedStreamSocket::readLine( OString& aLine )
{
while ( true )
@@ -39,12 +71,15 @@ sal_Int32 BufferedStreamSocket::readLine( OString& aLine )
aBuffer.erase( aBuffer.begin(), aIt + 1 ); // Also delete the empty line
aRead -= (aLocation + 1);
return aLine.getLength();
return aLine.getLength() + 1;
}
// Then try and receive if nothing present
aBuffer.resize( aRead + 100 );
aRet = recv( &aBuffer[aRead], 100 );
if ( !usingCSocket)
aRet = StreamSocket::recv( &aBuffer[aRead], 100 );
else
aRet = ::read( mSocket, &aBuffer[aRead], 100 );
if ( aRet == 0 )
{

View File

@@ -20,14 +20,27 @@ namespace sd
{
/**
* A wrapper for an osl StreamSocket to allow reading lines.
* [A wrapper for an osl StreamSocket to allow reading lines.]
*
* Currently wraps either an osl StreamSocket or a standard c socket,
* allowing reading and writing for our purposes. Should eventually be
* returned to being a StreamSocket wrapper if/when Bluetooth is
* integrated into osl Sockets.
*/
class BufferedStreamSocket :
public ::osl::StreamSocket,
private ::osl::StreamSocket,
private ::boost::noncopyable
{
public:
/**
* Create a BufferedStreamSocket on top of an
* osl::StreamSocket.
*/
BufferedStreamSocket( const osl::StreamSocket &aSocket );
/**
* Create a BufferedStreamSocket on top of a standard c socket.
*/
BufferedStreamSocket( int aSocket );
BufferedStreamSocket( const BufferedStreamSocket &aSocket );
/**
* Blocks until a line is read.
@@ -35,9 +48,15 @@ namespace sd
* if there was a problem in communications.
*/
sal_Int32 readLine(OString& aLine);
sal_Int32 write( const void* pBuffer, sal_uInt32 n );
void getPeerAddr(osl::SocketAddr&);
private:
sal_Int32 aRet, aRead;
std::vector<char> aBuffer;
int mSocket;
bool usingCSocket;
};
}

View File

@@ -37,7 +37,7 @@ Communicator::~Communicator()
// Run as a thread
void Communicator::execute()
{
pTransmitter = new Transmitter( *mpSocket );
pTransmitter = new Transmitter( mpSocket );
pTransmitter->launch();
pTransmitter->addMessage( "LO_SERVER_SERVER_PAIRED\n\n",
@@ -61,33 +61,24 @@ void Communicator::execute()
{
}
sal_uInt64 aRet, aRead;
vector<char> aBuffer;
sal_uInt64 aRet;
vector<OString> aCommand;
aRead = 0;
while ( true )
{
aBuffer.resize( aRead + 100 );
aRet = mpSocket->recv( &aBuffer[aRead], 100 );
OString aLine;
aRet = mpSocket->readLine( aLine );
if ( aRet == 0 )
{
break; // I.e. transmission finished.
}
aRead += aRet;
vector<char>::iterator aIt;
while ( (aIt = find( aBuffer.begin(), aBuffer.end(), '\n' ))
!= aBuffer.end() )
if ( aLine.getLength() )
{
sal_uInt64 aLocation = aIt - aBuffer.begin();
aCommand.push_back( OString( &(*aBuffer.begin()), aLocation ) );
if ( aIt == aBuffer.begin() )
{
aReceiver.parseCommand( aCommand );
aCommand.clear();
}
aBuffer.erase( aBuffer.begin(), aIt + 1 ); // Also delete the empty line
aRead -= (aLocation + 1);
aCommand.push_back( aLine );
}
else
{
aReceiver.parseCommand( aCommand );
aCommand.clear();
}
}
// TODO: deal with transmision errors gracefully.

View File

@@ -55,8 +55,6 @@ void Receiver::parseCommand( std::vector<OString> aCommand )
}
catch (uno::RuntimeException &)
{
fprintf( stderr, "Error in retrieving Controller\n" );
//return;
}
if ( aCommand[0].equals( "transition_next" ) )

View File

@@ -83,7 +83,6 @@ void RemoteServer::execute()
if ( ! pSocket->readLine( aLine ) ) delete pSocket;
OString aPin( aLine );
fprintf( stderr, "Pin:%s\n", aPin.getStr() );
SocketAddr aClientAddr;
pSocket->getPeerAddr( aClientAddr );
@@ -117,6 +116,8 @@ void RemoteServer::setup()
spServer = new RemoteServer();
spServer->launch();
sd::BluetoothServer::setup( &(spServer->mCommunicators) );
}
@@ -211,7 +212,6 @@ void SdDLL::RegisterRemotes()
sd::RemoteServer::setup();
sd::DiscoveryService::setup();
sd::BluetoothServer::setup();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -13,9 +13,9 @@ using namespace std;
using namespace osl; // Sockets etc.
using namespace sd;
Transmitter::Transmitter( StreamSocket &aSocket )
Transmitter::Transmitter( BufferedStreamSocket* aSocket )
: Thread( "TransmitterThread" ),
mStreamSocket( aSocket ),
pStreamSocket( aSocket ),
mQueuesNotEmpty(),
mFinishRequested(),
mQueueMutex(),
@@ -38,13 +38,13 @@ void Transmitter::execute()
{
OString aMessage( mHighPriority.front() );
mHighPriority.pop();
mStreamSocket.write( aMessage.getStr(), aMessage.getLength() );
pStreamSocket->write( aMessage.getStr(), aMessage.getLength() );
}
else if ( !mLowPriority.empty() )
{
OString aMessage( mLowPriority.front() );
mLowPriority.pop();
mStreamSocket.write( aMessage.getStr(), aMessage.getLength() );
pStreamSocket->write( aMessage.getStr(), aMessage.getLength() );
}
if ( mLowPriority.empty() && mHighPriority.empty() )

View File

@@ -11,7 +11,7 @@
#include <osl/conditn.hxx>
#include <osl/mutex.hxx>
#include <osl/socket.hxx>
#include "BufferedStreamSocket.hxx"
#include <salhelper/thread.hxx>
#include <rtl/string.hxx>
@@ -25,7 +25,7 @@ class Transmitter
{
public:
enum Priority { PRIORITY_LOW = 1, PRIORITY_HIGH };
Transmitter( osl::StreamSocket &aSocket );
Transmitter( ::sd::BufferedStreamSocket* aSocket );
~Transmitter();
void addMessage( const rtl::OString& aMessage, const Priority aPriority );
void notifyFinished();
@@ -33,7 +33,7 @@ public:
private:
void execute();
::osl::StreamSocket mStreamSocket;
::sd::BufferedStreamSocket* pStreamSocket;
::osl::Condition mQueuesNotEmpty;
::osl::Condition mFinishRequested;