--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -402,16 +402,35 @@ BluetoothHfpManager::Connect(const nsASt
false,
this,
runnable);
runnable.forget();
return NS_FAILED(rv) ? false : true;
}
+bool
+BluetoothHfpManager::Listen()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ BluetoothService* bs = BluetoothService::Get();
+ if (!bs) {
+ NS_WARNING("BluetoothService not available!");
+ return false;
+ }
+
+ nsresult rv = bs->ListenSocketViaService(BluetoothReservedChannels::HANDSFREE_AG,
+ BluetoothSocketType::RFCOMM,
+ true,
+ false,
+ this);
+ return NS_FAILED(rv) ? false : true;
+}
+
void
BluetoothHfpManager::Disconnect()
{
CloseSocket();
}
bool
BluetoothHfpManager::SendLine(const char* aMessage)
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -29,17 +29,17 @@ public:
void ReceiveSocketData(mozilla::ipc::UnixSocketRawData* aMessage);
bool Connect(const nsAString& aDeviceObjectPath,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
bool SendLine(const char* aMessage);
void CallStateChanged(int aCallIndex, int aCallState,
const char* aNumber, bool aIsActive);
-
+ bool Listen();
private:
BluetoothHfpManager();
bool BroadcastSystemMessage(const char* aCommand,
const int aCommandLength);
nsresult HandleVolumeChanged(const nsAString& aData);
int mCurrentVgs;
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -274,16 +274,23 @@ public:
virtual bool
ConnectObjectPush(const nsAString& aDeviceAddress,
const nsAString& aAdapterPath,
BluetoothReplyRunnable* aRunnable) = 0;
virtual void
DisconnectObjectPush(BluetoothReplyRunnable* aRunnable) = 0;
+ virtual nsresult
+ ListenSocketViaService(int aChannel,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt,
+ mozilla::ipc::UnixSocketConsumer* aConsumer) = 0;
+
bool
IsEnabled() const
{
return mEnabled;
}
protected:
BluetoothService()
--- a/dom/bluetooth/BluetoothServiceUuid.h
+++ b/dom/bluetooth/BluetoothServiceUuid.h
@@ -25,14 +25,29 @@ namespace BluetoothServiceUuid {
namespace BluetoothServiceUuidStr {
static const char* Headset = "00001108-0000-1000-8000-00805F9B34FB";
static const char* HeadsetAG = "00001112-0000-1000-8000-00805F9B34FB";
static const char* Handsfree = "0000111E-0000-1000-8000-00805F9B34FB";
static const char* HandsfreeAG = "0000111F-0000-1000-8000-00805F9B34FB";
static const char* ObjectPush = "00001105-0000-1000-8000-00805F9B34FB";
}
+// TODO/qdot: Move these back into gonk and make the service handler deal with
+// it there.
+//
+// Gotten from reading the "u8" values in B2G/external/bluez/src/adapter.c
+// These were hardcoded into android
+enum BluetoothReservedChannels {
+ DIALUP_NETWORK = 1,
+ HANDSFREE_AG = 10,
+ HEADSET_AG = 11,
+ OPUSH = 12,
+ SIM_ACCESS = 15,
+ PBAP_PSE = 19,
+ FTP = 20,
+};
+
}
}
}
#endif
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -221,16 +221,29 @@ BluetoothServiceChildProcess::GetSocketV
bool aEncrypt,
mozilla::ipc::UnixSocketConsumer* aConsumer,
BluetoothReplyRunnable* aRunnable)
{
MOZ_NOT_REACHED("This should never be called!");
return NS_ERROR_FAILURE;
}
+
+nsresult
+BluetoothServiceChildProcess::ListenSocketViaService(
+ int aChannel,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt,
+ mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+ MOZ_NOT_REACHED("This should never be called!");
+ return NS_ERROR_FAILURE;
+}
+
bool
BluetoothServiceChildProcess::SetPinCodeInternal(
const nsAString& aDeviceAddress,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
SetPinCodeRequest(nsString(aDeviceAddress), nsString(aPinCode)));
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -96,16 +96,23 @@ public:
GetSocketViaService(const nsAString& aObjectPath,
const nsAString& aService,
BluetoothSocketType aType,
bool aAuth,
bool aEncrypt,
mozilla::ipc::UnixSocketConsumer* aConsumer,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
+ virtual nsresult
+ ListenSocketViaService(int aChannel,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt,
+ mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
+
virtual bool
SetPinCodeInternal(const nsAString& aDeviceAddress,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
SetPasskeyInternal(const nsAString& aDeviceAddress,
uint32_t aPasskey,
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -256,16 +256,17 @@ public:
// Due to the fact that we need to queue the dbus call to the command thread
// inside the bluetoothservice, we have to route the call down to the main
// thread and then back out to the command thread. There has to be a better
// way to do this.
if (NS_FAILED(bs->PrepareAdapterInternal(mPath))) {
NS_WARNING("prepare adapter failed");
return NS_ERROR_FAILURE;
}
+
return NS_OK;
}
private:
nsString mPath;
};
class DevicePropertiesSignalHandler : public nsRunnable
@@ -723,16 +724,39 @@ ExtractHandles(DBusMessage *aReply, nsTA
}
} else {
LOG_AND_FREE_DBUS_ERROR(&err);
}
}
// static
bool
+BluetoothDBusService::AddServiceRecords(const nsAString& aAdapterPath,
+ const char* serviceName,
+ unsigned long long uuidMsb,
+ unsigned long long uuidLsb,
+ int channel)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ DBusMessage *reply;
+ reply = dbus_func_args(gThreadConnection->GetConnection(),
+ NS_ConvertUTF16toUTF8(aAdapterPath).get(),
+ DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
+ DBUS_TYPE_STRING, &serviceName,
+ DBUS_TYPE_UINT64, &uuidMsb,
+ DBUS_TYPE_UINT64, &uuidLsb,
+ DBUS_TYPE_UINT16, &channel,
+ DBUS_TYPE_INVALID);
+
+ return reply ? dbus_returns_uint32(reply) : -1;
+}
+
+// static
+bool
BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServices,
nsTArray<uint32_t>& aServiceHandlesContainer)
{
MOZ_ASSERT(!NS_IsMainThread());
int length = aServices.Length();
if (length == 0) return false;
@@ -2272,17 +2296,19 @@ public:
nsresult
Run()
{
MOZ_ASSERT(!NS_IsMainThread());
nsString address = GetAddressFromObjectPath(mObjectPath);
nsString replyError;
- BluetoothUnixSocketConnector c(BluetoothSocketType::SCO, -1, mAuth, mEncrypt);
+ BluetoothUnixSocketConnector* c =
+ new BluetoothUnixSocketConnector(BluetoothSocketType::SCO, -1,
+ mAuth, mEncrypt);
BluetoothScoManager* sco = BluetoothScoManager::Get();
if (!mConsumer->ConnectSocket(c, NS_ConvertUTF16toUTF8(address).get())) {
replyError.AssignLiteral("SocketConnectionError");
sco->SetConnected(false);
return NS_ERROR_FAILURE;
}
sco->SetConnected(true);
@@ -2297,47 +2323,47 @@ public:
private:
nsRefPtr<UnixSocketConsumer> mConsumer;
nsString mObjectPath;
bool mAuth;
bool mEncrypt;
};
-class CreateBluetoothSocketRunnable : public nsRunnable
+class ConnectBluetoothSocketRunnable : public nsRunnable
{
public:
- CreateBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable,
- UnixSocketConsumer* aConsumer,
- const nsAString& aObjectPath,
- const nsAString& aServiceUUID,
- BluetoothSocketType aType,
- bool aAuth,
- bool aEncrypt)
+ ConnectBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable,
+ UnixSocketConsumer* aConsumer,
+ const nsAString& aObjectPath,
+ const nsAString& aServiceUUID,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt)
: mRunnable(dont_AddRef(aRunnable)),
mConsumer(aConsumer),
mObjectPath(aObjectPath),
mServiceUUID(aServiceUUID),
mType(aType),
mAuth(aAuth),
mEncrypt(aEncrypt)
{
}
nsresult
Run()
{
- NS_WARNING("Running create socket!\n");
MOZ_ASSERT(!NS_IsMainThread());
nsString address = GetAddressFromObjectPath(mObjectPath);
int channel = GetDeviceServiceChannel(mObjectPath, mServiceUUID, 0x0004);
BluetoothValue v;
nsString replyError;
- BluetoothUnixSocketConnector c(mType, channel, mAuth, mEncrypt);
+ BluetoothUnixSocketConnector* c =
+ new BluetoothUnixSocketConnector(mType, channel, mAuth, mEncrypt);
if (!mConsumer->ConnectSocket(c, NS_ConvertUTF16toUTF8(address).get())) {
replyError.AssignLiteral("SocketConnectionError");
DispatchBluetoothReply(mRunnable, v, replyError);
return NS_ERROR_FAILURE;
}
// Bluetooth value needs to be set to something to succeed.
v = true;
DispatchBluetoothReply(mRunnable, v, replyError);
@@ -2390,22 +2416,82 @@ BluetoothDBusService::GetSocketViaServic
{
NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
if (!mConnection || !gThreadConnection) {
NS_ERROR("Bluetooth service not started yet!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
- nsRefPtr<nsRunnable> func(new CreateBluetoothSocketRunnable(runnable,
+ nsRefPtr<nsRunnable> func(new ConnectBluetoothSocketRunnable(runnable,
aConsumer,
aObjectPath,
aService, aType,
aAuth, aEncrypt));
if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
NS_WARNING("Cannot dispatch firmware loading task!");
return NS_ERROR_FAILURE;
}
runnable.forget();
return NS_OK;
}
+class ListenBluetoothSocketRunnable : public nsRunnable
+{
+public:
+ ListenBluetoothSocketRunnable(UnixSocketConsumer* aConsumer,
+ int aChannel,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt)
+ : mConsumer(aConsumer)
+ , mChannel(aChannel)
+ , mType(aType)
+ , mAuth(aAuth)
+ , mEncrypt(aEncrypt)
+ {
+ }
+
+ nsresult
+ Run()
+ {
+ MOZ_ASSERT(!NS_IsMainThread());
+ BluetoothUnixSocketConnector* c =
+ new BluetoothUnixSocketConnector(mType, mChannel, mAuth, mEncrypt);
+ if (!mConsumer->ListenSocket(c)) {
+ NS_WARNING("Can't listen on socket!");
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+ }
+
+private:
+ nsRefPtr<UnixSocketConsumer> mConsumer;
+ int mChannel;
+ BluetoothSocketType mType;
+ bool mAuth;
+ bool mEncrypt;
+};
+
+nsresult
+BluetoothDBusService::ListenSocketViaService(int aChannel,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt,
+ mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+ NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+ if (!mConnection || !gThreadConnection) {
+ NS_ERROR("Bluetooth service not started yet!");
+ return NS_ERROR_FAILURE;
+ }
+ nsRefPtr<nsRunnable> func(new ListenBluetoothSocketRunnable(aConsumer,
+ aChannel, aType,
+ aAuth,
+ aEncrypt));
+ if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
+ NS_WARNING("Cannot dispatch firmware loading task!");
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -54,16 +54,30 @@ public:
BluetoothReplyRunnable* aRunnable);
virtual bool
GetDevicePath(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
nsAString& aDevicePath);
static bool
+ AddServiceRecords(const nsAString& aAdapterPath,
+ const char* serviceName,
+ unsigned long long uuidMsb,
+ unsigned long long uuidLsb,
+ int channel);
+
+ static bool
+ RemoveServiceRecords(const nsAString& aAdapterPath,
+ const char* serviceName,
+ unsigned long long uuidMsb,
+ unsigned long long uuidLsb,
+ int channel);
+
+ static bool
AddReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServices,
nsTArray<uint32_t>& aServiceHandlesContainer);
static bool
RemoveReservedServicesInternal(const nsAString& aAdapterPath,
const nsTArray<uint32_t>& aServiceHandles);
@@ -78,16 +92,23 @@ public:
const nsAString& aService,
BluetoothSocketType aType,
bool aAuth,
bool aEncrypt,
mozilla::ipc::UnixSocketConsumer* aConsumer,
BluetoothReplyRunnable* aRunnable);
virtual nsresult
+ ListenSocketViaService(int aChannel,
+ BluetoothSocketType aType,
+ bool aAuth,
+ bool aEncrypt,
+ mozilla::ipc::UnixSocketConsumer* aConsumer);
+
+ virtual nsresult
CreatePairedDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress,
int aTimeout,
BluetoothReplyRunnable* aRunnable);
virtual nsresult
RemoveDeviceInternal(const nsAString& aAdapterPath,
const nsAString& aDeviceObjectPath,
--- a/ipc/dbus/DBusUtils.cpp
+++ b/ipc/dbus/DBusUtils.cpp
@@ -259,23 +259,39 @@ DBusMessage * dbus_func_args_error(DBusC
first_arg_type, lst);
va_end(lst);
return ret;
}
int dbus_returns_int32(DBusMessage *reply)
{
DBusError err;
- int ret = -1;
+ int32_t ret = -1;
dbus_error_init(&err);
if (!dbus_message_get_args(reply, &err,
DBUS_TYPE_INT32, &ret,
DBUS_TYPE_INVALID)) {
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
}
dbus_message_unref(reply);
return ret;
}
+int dbus_returns_uint32(DBusMessage *reply)
+{
+ DBusError err;
+ uint32_t ret = -1;
+
+ dbus_error_init(&err);
+ if (!dbus_message_get_args(reply, &err,
+ DBUS_TYPE_UINT32, &ret,
+ DBUS_TYPE_INVALID)) {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
+ }
+
+ dbus_message_unref(reply);
+ return ret;
+}
+
}
}
--- a/ipc/dbus/DBusUtils.h
+++ b/ipc/dbus/DBusUtils.h
@@ -103,13 +103,15 @@ DBusMessage* dbus_func_args_timeout_val
const char* path,
const char* ifc,
const char* func,
int first_arg_type,
va_list args);
int dbus_returns_int32(DBusMessage *reply);
+int dbus_returns_uint32(DBusMessage *reply);
+
}
}
#endif