--- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
@@ -1,16 +1,17 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothDaemonInterface.h"
#include "BluetoothDaemonA2dpInterface.h"
+#include "BluetoothDaemonAvrcpInterface.h"
#include "BluetoothDaemonHandsfreeInterface.h"
#include "BluetoothDaemonHelpers.h"
#include "BluetoothDaemonSetupInterface.h"
#include "BluetoothDaemonSocketInterface.h"
#include "BluetoothInterfaceHelpers.h"
#include "mozilla/unused.h"
using namespace mozilla::ipc;
@@ -1351,23 +1352,72 @@ private:
}
};
//
// Protocol handling
//
+// |BluetoothDaemonProtocol| is the central class for communicating
+// with the Bluetooth daemon. It maintains both socket connections
+// to the external daemon and implements the complete HAL protocol
+// by inheriting from base-class modules.
+//
+// Each |BluetoothDaemon*Module| class implements an individual
+// module of the HAL protocol. Each class contains the abstract
+// methods
+//
+// - |Send|,
+// - |RegisterModule|, and
+// - |UnregisterModule|.
+//
+// Module classes use |Send| to send out command PDUs. The socket
+// in |BluetoothDaemonProtocol| is required for sending. The abstract
+// method hides all these internal details from the modules.
+//
+// |RegisterModule| is required during module initialization, when
+// modules must register themselves at the daemon. The register command
+// is not part of the module itself, but contained in the Setup module
+// (id of 0x00). The abstract method |RegisterModule| allows modules to
+// call into the Setup module for generating the register command.
+//
+// |UnregisterModule| works like |RegisterModule|, but for cleanups.
+//
+// |BluetoothDaemonProtocol| also handles PDU receiving. It implements
+// the method |Handle| from |BluetoothDaemonPDUConsumer|. The socket
+// connections of type |BluetoothDaemonConnection| invoke this method
+// to forward received PDUs for processing by higher layers. The
+// implementation of |Handle| checks the service id of the PDU and
+// forwards it to the correct module class using the module's method
+// |HandleSvc|. Further PDU processing is module-dependent.
+//
+// To summarize the interface between |BluetoothDaemonProtocol| and
+// modules; the former implements the abstract methods
+//
+// - |Send|,
+// - |RegisterModule|, and
+// - |UnregisterModule|,
+//
+// which allow modules to send out data. Each module implements the
+// method
+//
+// - |HandleSvc|,
+//
+// which is called by |BluetoothDaemonProtcol| to hand over received
+// PDUs into a module.
+//
class BluetoothDaemonProtocol MOZ_FINAL
: public BluetoothDaemonPDUConsumer
, public BluetoothDaemonSetupModule
, public BluetoothDaemonCoreModule
, public BluetoothDaemonSocketModule
, public BluetoothDaemonHandsfreeModule
, public BluetoothDaemonA2dpModule
+ , public BluetoothDaemonAvrcpModule
{
public:
BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection);
nsresult RegisterModule(uint8_t aId, uint8_t aMode,
BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE;
nsresult UnregisterModule(uint8_t aId,
@@ -1393,16 +1443,18 @@ private:
void HandleCoreSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
void HandleSocketSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
void HandleHandsfreeSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
void HandleA2dpSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
+ void HandleAvrcpSvc(const BluetoothDaemonPDUHeader& aHeader,
+ BluetoothDaemonPDU& aPDU, void* aUserData);
BluetoothDaemonConnection* mConnection;
nsTArray<void*> mUserDataQ;
};
BluetoothDaemonProtocol::BluetoothDaemonProtocol(
BluetoothDaemonConnection* aConnection)
: mConnection(aConnection)
@@ -1470,29 +1522,40 @@ void
BluetoothDaemonProtocol::HandleA2dpSvc(
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
void* aUserData)
{
BluetoothDaemonA2dpModule::HandleSvc(aHeader, aPDU, aUserData);
}
void
+BluetoothDaemonProtocol::HandleAvrcpSvc(
+ const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
+ void* aUserData)
+{
+ BluetoothDaemonAvrcpModule::HandleSvc(aHeader, aPDU, aUserData);
+}
+
+void
BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU)
{
static void (BluetoothDaemonProtocol::* const HandleSvc[])(
const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = {
INIT_ARRAY_AT(0x00, &BluetoothDaemonProtocol::HandleSetupSvc),
INIT_ARRAY_AT(0x01, &BluetoothDaemonProtocol::HandleCoreSvc),
INIT_ARRAY_AT(0x02, &BluetoothDaemonProtocol::HandleSocketSvc),
INIT_ARRAY_AT(0x03, nullptr), // HID host
INIT_ARRAY_AT(0x04, nullptr), // PAN
INIT_ARRAY_AT(BluetoothDaemonHandsfreeModule::SERVICE_ID,
&BluetoothDaemonProtocol::HandleHandsfreeSvc),
INIT_ARRAY_AT(BluetoothDaemonA2dpModule::SERVICE_ID,
- &BluetoothDaemonProtocol::HandleA2dpSvc)
+ &BluetoothDaemonProtocol::HandleA2dpSvc),
+ INIT_ARRAY_AT(0x07, nullptr), // Health
+ INIT_ARRAY_AT(BluetoothDaemonAvrcpModule::SERVICE_ID,
+ &BluetoothDaemonProtocol::HandleAvrcpSvc)
};
BluetoothDaemonPDUHeader header;
if (NS_FAILED(UnpackPDU(aPDU, header)) ||
NS_WARN_IF(!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc))) ||
NS_WARN_IF(!(HandleSvc[header.mService]))) {
return;
@@ -2074,12 +2137,18 @@ BluetoothDaemonInterface::GetBluetoothA2
mA2dpInterface = new BluetoothDaemonA2dpInterface(mProtocol);
return mA2dpInterface;
}
BluetoothAvrcpInterface*
BluetoothDaemonInterface::GetBluetoothAvrcpInterface()
{
- return nullptr;
+ if (mAvrcpInterface) {
+ return mAvrcpInterface;
+ }
+
+ mAvrcpInterface = new BluetoothDaemonAvrcpInterface(mProtocol);
+
+ return mAvrcpInterface;
}
END_BLUETOOTH_NAMESPACE