зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1110049: Added Bluetooth A2DP module for daemon backend (under bluetooth2/), r=btian
This commit is contained in:
Родитель
105f2a4a7a
Коммит
a5d441e42c
|
@ -0,0 +1,285 @@
|
|||
/* -*- 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 "BluetoothDaemonA2dpInterface.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
//
|
||||
// A2DP module
|
||||
//
|
||||
|
||||
BluetoothA2dpNotificationHandler*
|
||||
BluetoothDaemonA2dpModule::sNotificationHandler;
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::SetNotificationHandler(
|
||||
BluetoothA2dpNotificationHandler* aNotificationHandler)
|
||||
{
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonA2dpModule::Send(BluetoothDaemonPDU* aPDU,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
aRes->AddRef(); // Keep reference for response
|
||||
return Send(aPDU, static_cast<void*>(aRes));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU, void* aUserData)
|
||||
{
|
||||
static void (BluetoothDaemonA2dpModule::* const HandleOp[])(
|
||||
const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = {
|
||||
INIT_ARRAY_AT(0, &BluetoothDaemonA2dpModule::HandleRsp),
|
||||
INIT_ARRAY_AT(1, &BluetoothDaemonA2dpModule::HandleNtf),
|
||||
};
|
||||
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
// negate twice to map bit to 0/1
|
||||
unsigned int isNtf = !!(aHeader.mOpcode & 0x80);
|
||||
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData);
|
||||
}
|
||||
|
||||
// Commands
|
||||
//
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonA2dpModule::ConnectCmd(
|
||||
const nsAString& aRemoteAddr, BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoPtr<BluetoothDaemonPDU> pdu(new BluetoothDaemonPDU(SERVICE_ID,
|
||||
OPCODE_CONNECT,
|
||||
6)); // Address
|
||||
nsresult rv = PackPDU(
|
||||
PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Send(pdu, aRes);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << pdu.forget();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonA2dpModule::DisconnectCmd(
|
||||
const nsAString& aRemoteAddr, BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoPtr<BluetoothDaemonPDU> pdu(new BluetoothDaemonPDU(SERVICE_ID,
|
||||
OPCODE_DISCONNECT,
|
||||
6)); // Address
|
||||
nsresult rv = PackPDU(
|
||||
PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Send(pdu, aRes);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << pdu.forget();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Responses
|
||||
//
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::ErrorRsp(
|
||||
const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU, BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
ErrorRunnable::Dispatch(
|
||||
aRes, &BluetoothA2dpResultHandler::OnError, UnpackPDUInitOp(aPDU));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::ConnectRsp(
|
||||
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
ResultRunnable::Dispatch(
|
||||
aRes, &BluetoothA2dpResultHandler::Connect, UnpackPDUInitOp(aPDU));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::DisconnectRsp(
|
||||
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
ResultRunnable::Dispatch(
|
||||
aRes, &BluetoothA2dpResultHandler::Disconnect, UnpackPDUInitOp(aPDU));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::HandleRsp(
|
||||
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
|
||||
void* aUserData)
|
||||
{
|
||||
static void (BluetoothDaemonA2dpModule::* const HandleRsp[])(
|
||||
const BluetoothDaemonPDUHeader&,
|
||||
BluetoothDaemonPDU&,
|
||||
BluetoothA2dpResultHandler*) = {
|
||||
INIT_ARRAY_AT(OPCODE_ERROR,
|
||||
&BluetoothDaemonA2dpModule::ErrorRsp),
|
||||
INIT_ARRAY_AT(OPCODE_CONNECT,
|
||||
&BluetoothDaemonA2dpModule::ConnectRsp),
|
||||
INIT_ARRAY_AT(OPCODE_DISCONNECT,
|
||||
&BluetoothDaemonA2dpModule::DisconnectRsp),
|
||||
};
|
||||
|
||||
MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
|
||||
|
||||
if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) ||
|
||||
NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothA2dpResultHandler> res =
|
||||
already_AddRefed<BluetoothA2dpResultHandler>(
|
||||
static_cast<BluetoothA2dpResultHandler*>(aUserData));
|
||||
|
||||
if (!res) {
|
||||
return; // Return early if no result handler has been set for response
|
||||
}
|
||||
|
||||
(this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
|
||||
}
|
||||
|
||||
// Notifications
|
||||
//
|
||||
|
||||
// Returns the current notification handler to a notification runnable
|
||||
class BluetoothDaemonA2dpModule::NotificationHandlerWrapper MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
typedef BluetoothA2dpNotificationHandler ObjectType;
|
||||
|
||||
static ObjectType* GetInstance()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return sNotificationHandler;
|
||||
}
|
||||
};
|
||||
|
||||
// Init operator class for ConnectionStateNotification
|
||||
class BluetoothDaemonA2dpModule::ConnectionStateInitOp MOZ_FINAL
|
||||
: private PDUInitOp
|
||||
{
|
||||
public:
|
||||
ConnectionStateInitOp(BluetoothDaemonPDU& aPDU)
|
||||
: PDUInitOp(aPDU)
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
operator () (BluetoothA2dpConnectionState& aArg1, nsString& aArg2) const
|
||||
{
|
||||
BluetoothDaemonPDU& pdu = GetPDU();
|
||||
|
||||
/* Read state */
|
||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Read address */
|
||||
rv = UnpackPDU(
|
||||
pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
WarnAboutTrailingData();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::ConnectionStateNtf(
|
||||
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
|
||||
{
|
||||
ConnectionStateNotification::Dispatch(
|
||||
&BluetoothA2dpNotificationHandler::ConnectionStateNotification,
|
||||
ConnectionStateInitOp(aPDU));
|
||||
}
|
||||
|
||||
// Init operator class for AudioStateNotification
|
||||
class BluetoothDaemonA2dpModule::AudioStateInitOp MOZ_FINAL
|
||||
: private PDUInitOp
|
||||
{
|
||||
public:
|
||||
AudioStateInitOp(BluetoothDaemonPDU& aPDU)
|
||||
: PDUInitOp(aPDU)
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
operator () (BluetoothA2dpAudioState& aArg1,
|
||||
nsString& aArg2) const
|
||||
{
|
||||
BluetoothDaemonPDU& pdu = GetPDU();
|
||||
|
||||
/* Read state */
|
||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Read address */
|
||||
rv = UnpackPDU(
|
||||
pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
WarnAboutTrailingData();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::AudioStateNtf(
|
||||
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
|
||||
{
|
||||
AudioStateNotification::Dispatch(
|
||||
&BluetoothA2dpNotificationHandler::AudioStateNotification,
|
||||
AudioStateInitOp(aPDU));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::HandleNtf(
|
||||
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
|
||||
void* aUserData)
|
||||
{
|
||||
static void (BluetoothDaemonA2dpModule::* const HandleNtf[])(
|
||||
const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = {
|
||||
INIT_ARRAY_AT(0, &BluetoothDaemonA2dpModule::ConnectionStateNtf),
|
||||
INIT_ARRAY_AT(1, &BluetoothDaemonA2dpModule::AudioStateNtf),
|
||||
};
|
||||
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
uint8_t index = aHeader.mOpcode - 0x81;
|
||||
|
||||
if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) ||
|
||||
NS_WARN_IF(!HandleNtf[index])) {
|
||||
return;
|
||||
}
|
||||
|
||||
(this->*(HandleNtf[index]))(aHeader, aPDU);
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
|
@ -0,0 +1,123 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluetoothdaemona2dpinterface_h
|
||||
#define mozilla_dom_bluetooth_bluetoothdaemona2dpinterface_h
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
class BluetoothDaemonA2dpModule
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
SERVICE_ID = 0x06
|
||||
};
|
||||
|
||||
enum {
|
||||
OPCODE_ERROR = 0x00,
|
||||
OPCODE_CONNECT = 0x01,
|
||||
OPCODE_DISCONNECT = 0x02
|
||||
};
|
||||
|
||||
virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0;
|
||||
|
||||
virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
|
||||
BluetoothSetupResultHandler* aRes) = 0;
|
||||
|
||||
virtual nsresult UnregisterModule(uint8_t aId,
|
||||
BluetoothSetupResultHandler* aRes) = 0;
|
||||
|
||||
void SetNotificationHandler(
|
||||
BluetoothA2dpNotificationHandler* aNotificationHandler);
|
||||
|
||||
//
|
||||
// Commands
|
||||
//
|
||||
|
||||
nsresult ConnectCmd(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
nsresult DisconnectCmd(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
nsresult Send(BluetoothDaemonPDU* aPDU,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
void HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU, void* aUserData);
|
||||
|
||||
//
|
||||
// Responses
|
||||
//
|
||||
|
||||
typedef BluetoothResultRunnable0<BluetoothA2dpResultHandler, void>
|
||||
ResultRunnable;
|
||||
|
||||
typedef BluetoothResultRunnable1<BluetoothA2dpResultHandler, void,
|
||||
BluetoothStatus, BluetoothStatus>
|
||||
ErrorRunnable;
|
||||
|
||||
void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
void DisconnectRsp(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
void HandleRsp(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU,
|
||||
void* aUserData);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
|
||||
class NotificationHandlerWrapper;
|
||||
|
||||
typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
|
||||
BluetoothA2dpConnectionState,
|
||||
nsString,
|
||||
BluetoothA2dpConnectionState,
|
||||
const nsAString&>
|
||||
ConnectionStateNotification;
|
||||
|
||||
typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
|
||||
BluetoothA2dpAudioState,
|
||||
nsString,
|
||||
BluetoothA2dpAudioState,
|
||||
const nsAString&>
|
||||
AudioStateNotification;
|
||||
|
||||
class AudioStateInitOp;
|
||||
class ConnectionStateInitOp;
|
||||
|
||||
void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU);
|
||||
|
||||
void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU);
|
||||
|
||||
void HandleNtf(const BluetoothDaemonPDUHeader& aHeader,
|
||||
BluetoothDaemonPDU& aPDU,
|
||||
void* aUserData);
|
||||
|
||||
static BluetoothA2dpNotificationHandler* sNotificationHandler;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -51,6 +51,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
'bluedroid/BluetoothA2dpHALInterface.cpp',
|
||||
'bluedroid/BluetoothA2dpManager.cpp',
|
||||
'bluedroid/BluetoothAvrcpHALInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonA2dpInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonHandsfreeInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonHelpers.cpp',
|
||||
'bluedroid/BluetoothDaemonInterface.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче