Bug 1223729 - HID Connection Implementation, r=jocelyn, sr=mrbkap

--HG--
rename : dom/bluetooth/common/BluetoothHidManager.cpp => dom/bluetooth/bluez/BluetoothHidManager.cpp
rename : dom/bluetooth/common/BluetoothHidManager.h => dom/bluetooth/bluez/BluetoothHidManager.h
This commit is contained in:
Louis Chang 2015-12-04 11:58:55 +08:00
parent 4e06af5a13
commit 73c9a25e36
20 changed files with 2288 additions and 3 deletions

View File

@ -798,6 +798,7 @@ GK_ATOM(onhashchange, "onhashchange")
GK_ATOM(onheadphoneschange, "onheadphoneschange")
GK_ATOM(onheld, "onheld")
GK_ATOM(onhfpstatuschanged, "onhfpstatuschanged")
GK_ATOM(onhidstatuschanged, "onhidstatuschanged")
GK_ATOM(onholding, "onholding")
GK_ATOM(oniccchange, "oniccchange")
GK_ATOM(oniccdetected, "oniccdetected")

View File

@ -514,6 +514,78 @@ Convert(int32_t aIn, BluetoothGattStatus& aOut)
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHidProtocolMode& aOut)
{
static const BluetoothHidProtocolMode sMode[] = {
[0x00] = HID_PROTOCOL_MODE_REPORT,
[0x01] = HID_PROTOCOL_MODE_BOOT
};
if (aIn == 0xff) {
/* This case is handled separately to not populate
* |sMode| with empty entries. */
aOut = HID_PROTOCOL_MODE_UNSUPPORTED;
return NS_OK;
}
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, BluetoothHidProtocolMode)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sMode[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHidConnectionState& aOut)
{
static const BluetoothHidConnectionState sConnectionState[] = {
[0x00] = HID_CONNECTION_STATE_CONNECTED,
[0x01] = HID_CONNECTION_STATE_CONNECTING,
[0x02] = HID_CONNECTION_STATE_DISCONNECTED,
[0x03] = HID_CONNECTION_STATE_DISCONNECTING,
[0x04] = HID_CONNECTION_STATE_FAILED_MOUSE_FROM_HOST,
[0x05] = HID_CONNECTION_STATE_FAILED_KEYBOARD_FROM_HOST,
[0x06] = HID_CONNECTION_STATE_FAILED_TOO_MANY_DEVICES,
[0x07] = HID_CONNECTION_STATE_FAILED_NO_HID_DRIVER,
[0x08] = HID_CONNECTION_STATE_FAILED_GENERIC,
[0x09] = HID_CONNECTION_STATE_UNKNOWN
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sConnectionState),
uint8_t, BluetoothHidConnectionState)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sConnectionState[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHidStatus& aOut)
{
static const BluetoothHidStatus sStatus[] = {
[0x00] = HID_STATUS_OK,
[0x01] = HID_STATUS_HANDSHAKE_DEVICE_NOT_READY,
[0x02] = HID_STATUS_HANDSHAKE_INVALID_REPORT_ID,
[0x03] = HID_STATUS_HANDSHAKE_TRANSACTION_NOT_SPT,
[0x04] = HID_STATUS_HANDSHAKE_INVALID_PARAMETER,
[0x05] = HID_STATUS_HANDSHAKE_GENERIC_ERROR,
[0x06] = HID_STATUS_GENERAL_ERROR,
[0x07] = HID_STATUS_SDP_ERROR,
[0x08] = HID_STATUS_SET_PROTOCOL_ERROR,
[0x09] = HID_STATUS_DEVICE_DATABASE_FULL,
[0x0a] = HID_STATUS_DEVICE_TYPE_NOT_SUPPORTED,
[0x0b] = HID_STATUS_NO_RESOURCES,
[0x0c] = HID_STATUS_AUTHENTICATION_FAILED,
[0x0d] = HID_STATUS_HDL
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sStatus), uint8_t, BluetoothHidStatus)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sStatus[aIn];
return NS_OK;
}
nsresult
Convert(nsresult aIn, BluetoothStatus& aOut)
{
@ -981,6 +1053,47 @@ Convert(BluetoothGattWriteType aIn, int32_t& aOut)
return NS_OK;
}
nsresult
Convert(BluetoothHidProtocolMode aIn, uint8_t& aOut)
{
static const uint8_t sMode[] = {
[HID_PROTOCOL_MODE_REPORT] = 0x00,
[HID_PROTOCOL_MODE_BOOT] = 0x01
};
if (aIn == HID_PROTOCOL_MODE_UNSUPPORTED) {
/* This case is handled separately to not populate
* |sValue| with empty entries. */
aOut = 0xff;
return NS_OK;
}
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sMode), BluetoothHidProtocolMode, uint8_t)) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sMode[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHidReportType aIn, uint8_t& aOut)
{
static const uint8_t sType[] = {
[0x00] = static_cast<BluetoothHidReportType>(0),
[HID_REPORT_TYPE_INPUT] = 0x01,
[HID_REPORT_TYPE_OUTPUT] = 0x02,
[HID_REPORT_TYPE_FEATURE] = 0x03
};
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
aIn >= MOZ_ARRAY_LENGTH(sType),
BluetoothHidReportType, uint8_t)) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sType[aIn];
return NS_OK;
}
/* |ConvertArray| is a helper for converting arrays. Pass an
* instance of this structure as the first argument to |Convert|
* to convert an array. The output type has to support the array
@ -1406,6 +1519,61 @@ PackPDU(BluetoothGattWriteType aIn, DaemonSocketPDU& aPDU)
return PackPDU(PackConversion<BluetoothGattWriteType, int32_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHidInfoParam& aIn, DaemonSocketPDU& aPDU)
{
if (MOZ_HAL_IPC_PACK_WARN_IF(
aIn.mDescriptorLength > BLUETOOTH_HID_MAX_DESC_LEN,
BluetoothHidInfoParam)) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult rv = PackPDU(aIn.mAttributeMask,
aIn.mSubclass,
aIn.mApplicationId,
aIn.mVendorId,
aIn.mProductId,
aIn.mVersion,
aIn.mCountryCode,
aIn.mDescriptorLength,
aPDU);
if (NS_FAILED(rv)) {
return rv;
}
return PackPDU(
PackArray<uint8_t>(aIn.mDescriptorValue, aIn.mDescriptorLength), aPDU);
}
nsresult
PackPDU(const BluetoothHidReport& aIn, DaemonSocketPDU& aPDU)
{
uint8_t* reportData =
const_cast<uint8_t*>(aIn.mReportData.Elements());
nsresult rv = PackPDU(
PackConversion<uint32_t, uint16_t>(aIn.mReportData.Length()), aPDU);
if (NS_FAILED(rv)) {
return rv;
}
return PackPDU(
PackArray<uint8_t>(reportData, aIn.mReportData.Length()),
aPDU);
}
nsresult
PackPDU(BluetoothHidProtocolMode aIn, DaemonSocketPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHidProtocolMode, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(BluetoothHidReportType aIn, DaemonSocketPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHidReportType, uint8_t>(aIn), aPDU);
}
//
// Unpacking
//
@ -1813,4 +1981,85 @@ UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattNotifyParam& aOut)
return aPDU.Read(aOut.mValue, aOut.mLength);
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidInfoParam& aOut)
{
/* unpack attribute mask */
nsresult rv = UnpackPDU(aPDU, aOut.mAttributeMask);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack subclass */
rv = UnpackPDU(aPDU, aOut.mSubclass);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack application id */
rv = UnpackPDU(aPDU, aOut.mApplicationId);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack vendor id */
rv = UnpackPDU(aPDU, aOut.mVendorId);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack product id */
rv = UnpackPDU(aPDU, aOut.mProductId);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack version */
rv = UnpackPDU(aPDU, aOut.mVersion);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack country code */
rv = UnpackPDU(aPDU, aOut.mCountryCode);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack descriptor length */
rv = UnpackPDU(aPDU, aOut.mDescriptorLength);
if (NS_FAILED(rv)) {
return rv;
}
if (MOZ_HAL_IPC_PACK_WARN_IF(
aOut.mDescriptorLength > BLUETOOTH_HID_MAX_DESC_LEN,
BluetoothHidInfoParam)) {
return NS_ERROR_ILLEGAL_VALUE;
}
/* unpack descriptor value */
return UnpackPDU(
aPDU,
UnpackArray<uint8_t>(aOut.mDescriptorValue, aOut.mDescriptorLength));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidReport& aOut)
{
return UnpackPDU(aPDU, aOut.mReportData);
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidProtocolMode& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHidProtocolMode>(aOut));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidConnectionState& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHidConnectionState>(aOut));
}
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidStatus& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHidStatus>(aOut));
}
END_BLUETOOTH_NAMESPACE

View File

@ -173,6 +173,15 @@ Convert(uint8_t aIn, BluetoothStatus& aOut);
nsresult
Convert(int32_t aIn, BluetoothAttributeHandle& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHidProtocolMode& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHidConnectionState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHidStatus& aOut);
nsresult
Convert(int32_t aIn, BluetoothGattStatus& aOut);
@ -257,6 +266,12 @@ Convert(BluetoothGattWriteType aIn, int32_t& aOut);
nsresult
Convert(nsresult aIn, BluetoothStatus& aOut);
nsresult
Convert(BluetoothHidProtocolMode aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHidReportType aIn, uint8_t& aOut);
//
// Packing
//
@ -371,6 +386,18 @@ PackPDU(BluetoothGattWriteType aIn, DaemonSocketPDU& aPDU);
nsresult
PackPDU(BluetoothTransport aIn, DaemonSocketPDU& aPDU);
nsresult
PackPDU(const BluetoothHidInfoParam& aIn, DaemonSocketPDU& aPDU);
nsresult
PackPDU(const BluetoothHidReport& aIn, DaemonSocketPDU& aPDU);
nsresult
PackPDU(BluetoothHidProtocolMode aIn, DaemonSocketPDU& aPDU);
nsresult
PackPDU(BluetoothHidReportType aIn, DaemonSocketPDU& aPDU);
/* This implementation of |PackPDU| packs |BluetoothUuid| in reversed order.
* (ex. reversed GATT UUID, see bug 1171866)
*/
@ -513,6 +540,21 @@ UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattWriteParam& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattNotifyParam& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidInfoParam& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidReport& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidProtocolMode& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidConnectionState& aOut);
nsresult
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothHidStatus& aOut);
/* This implementation of |UnpackPDU| unpacks |BluetoothUuid| in reversed
* order. (ex. reversed GATT UUID, see bug 1171866)
*/

View File

@ -0,0 +1,677 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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 "BluetoothDaemonHidInterface.h"
#include "mozilla/unused.h"
BEGIN_BLUETOOTH_NAMESPACE
using namespace mozilla::ipc;
//
// Hid module
//
BluetoothHidNotificationHandler*
BluetoothDaemonHidModule::sNotificationHandler;
void
BluetoothDaemonHidModule::SetNotificationHandler(
BluetoothHidNotificationHandler* aNotificationHandler)
{
sNotificationHandler = aNotificationHandler;
}
void
BluetoothDaemonHidModule::HandleSvc(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes)
{
static void (BluetoothDaemonHidModule::* const HandleOp[])(
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
DaemonSocketResultHandler*) = {
[0] = &BluetoothDaemonHidModule::HandleRsp,
[1] = &BluetoothDaemonHidModule::HandleNtf
};
MOZ_ASSERT(!NS_IsMainThread());
// Negate twice to map bit to 0/1
unsigned long isNtf = !!(aHeader.mOpcode & 0x80);
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
}
// Commands
//
nsresult
BluetoothDaemonHidModule::ConnectCmd(
const BluetoothAddress& aRemoteAddr, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT, 6)); // Address
nsresult rv = PackPDU(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
BluetoothDaemonHidModule::DisconnectCmd(
const BluetoothAddress& aRemoteAddr, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT, 6)); // Address
nsresult rv = PackPDU(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
BluetoothDaemonHidModule::VirtualUnplugCmd(
const BluetoothAddress& aRemoteAddr, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_VIRTUAL_UNPLUG, 6)); // Address
nsresult rv = PackPDU(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
BluetoothDaemonHidModule::SetInfoCmd(
const BluetoothAddress& aRemoteAddr,
const BluetoothHidInfoParam& aHidInfoParam,
BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_INFO, 0));
nsresult rv = PackPDU(aRemoteAddr, aHidInfoParam, *pdu);
if (NS_FAILED(rv)) {
return rv;
}
rv = Send(pdu, aRes);
if (NS_FAILED(rv)) {
return rv;
}
Unused << pdu.forget();
return NS_OK;
}
nsresult
BluetoothDaemonHidModule::GetProtocolCmd(
const BluetoothAddress& aRemoteAddr,
BluetoothHidProtocolMode aHidProtocolMode,
BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PROTOCOL,
6 + // Address
1)); // Protocol Mode
nsresult rv = PackPDU(aRemoteAddr, aHidProtocolMode, *pdu);
if (NS_FAILED(rv)) {
return rv;
}
rv = Send(pdu, aRes);
if (NS_FAILED(rv)) {
return rv;
}
Unused << pdu.forget();
return NS_OK;
}
nsresult
BluetoothDaemonHidModule::SetProtocolCmd(
const BluetoothAddress& aRemoteAddr,
BluetoothHidProtocolMode aHidProtocolMode,
BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PROTOCOL,
6 + // Remote Address
1)); // Protocol Mode
nsresult rv = PackPDU(aRemoteAddr, aHidProtocolMode, *pdu);
if (NS_FAILED(rv)) {
return rv;
}
rv = Send(pdu, aRes);
if (NS_FAILED(rv)) {
return rv;
}
Unused << pdu.forget();
return NS_OK;
}
nsresult
BluetoothDaemonHidModule::GetReportCmd(
const BluetoothAddress& aRemoteAddr, BluetoothHidReportType aType,
uint8_t aReportId, uint16_t aBuffSize, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REPORT,
6 + // Address
1 + // Report Type
1 + // Report ID
2)); // Buffer Size
nsresult rv = PackPDU(aRemoteAddr, aType, aReportId, aBuffSize, *pdu);
if (NS_FAILED(rv)) {
return rv;
}
rv = Send(pdu, aRes);
if (NS_FAILED(rv)) {
return rv;
}
Unused << pdu.forget();
return NS_OK;
}
nsresult
BluetoothDaemonHidModule::SetReportCmd(
const BluetoothAddress& aRemoteAddr, BluetoothHidReportType aType,
const BluetoothHidReport& aReport, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_REPORT, 0));
nsresult rv = PackPDU(aRemoteAddr, aType, aReport, *pdu);
if (NS_FAILED(rv)) {
return rv;
}
rv = Send(pdu, aRes);
if (NS_FAILED(rv)) {
return rv;
}
Unused << pdu.forget();
return NS_OK;
}
nsresult
BluetoothDaemonHidModule::SendDataCmd(
const BluetoothAddress& aRemoteAddr, uint16_t aDataLen, const uint8_t* aData,
BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<DaemonSocketPDU> pdu(
new DaemonSocketPDU(SERVICE_ID, OPCODE_SEND_DATA, 0));
nsresult rv = PackPDU(aRemoteAddr, aDataLen,
PackArray<uint8_t>(aData, aDataLen), *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
BluetoothDaemonHidModule::ErrorRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ErrorRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::OnError, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::ConnectRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::Connect, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::DisconnectRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::Disconnect, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::VirtualUnplugRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::VirtualUnplug, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::SetInfoRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::SetInfo, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::GetProtocolRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::GetProtocol, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::SetProtocolRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::SetProtocol, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::GetReportRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::GetReport, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::SetReportRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::SetReport, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::SendDataRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, BluetoothHidResultHandler* aRes)
{
ResultRunnable::Dispatch(
aRes, &BluetoothHidResultHandler::SendData, UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::HandleRsp(
const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes)
{
static void (BluetoothDaemonHidModule::* const HandleRsp[])(
const DaemonSocketPDUHeader&,
DaemonSocketPDU&,
BluetoothHidResultHandler*) = {
[OPCODE_ERROR] = &BluetoothDaemonHidModule::ErrorRsp,
[OPCODE_CONNECT] = &BluetoothDaemonHidModule::ConnectRsp,
[OPCODE_DISCONNECT] = &BluetoothDaemonHidModule::DisconnectRsp,
[OPCODE_VIRTUAL_UNPLUG] = &BluetoothDaemonHidModule::VirtualUnplugRsp,
[OPCODE_SET_INFO] = &BluetoothDaemonHidModule::SetInfoRsp,
[OPCODE_GET_PROTOCOL] = &BluetoothDaemonHidModule::GetProtocolRsp,
[OPCODE_SET_PROTOCOL] = &BluetoothDaemonHidModule::SetProtocolRsp,
[OPCODE_GET_REPORT] = &BluetoothDaemonHidModule::GetReportRsp,
[OPCODE_SET_REPORT] = &BluetoothDaemonHidModule::SetReportRsp,
[OPCODE_SEND_DATA] = &BluetoothDaemonHidModule::SendDataRsp
};
MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) ||
NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) {
return;
}
RefPtr<BluetoothHidResultHandler> res =
static_cast<BluetoothHidResultHandler*>(aRes);
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 BluetoothDaemonHidModule::NotificationHandlerWrapper final
{
public:
typedef BluetoothHidNotificationHandler ObjectType;
static ObjectType* GetInstance()
{
MOZ_ASSERT(NS_IsMainThread());
return sNotificationHandler;
}
};
void
BluetoothDaemonHidModule::ConnectionStateNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
ConnectionStateNotification::Dispatch(
&BluetoothHidNotificationHandler::ConnectionStateNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::HidInfoNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
HidInfoNotification::Dispatch(
&BluetoothHidNotificationHandler::HidInfoNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::ProtocolModeNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
ProtocolModeNotification::Dispatch(
&BluetoothHidNotificationHandler::ProtocolModeNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::IdleTimeNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
IdleTimeNotification::Dispatch(
&BluetoothHidNotificationHandler::IdleTimeNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::GetReportNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
GetReportNotification::Dispatch(
&BluetoothHidNotificationHandler::GetReportNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::VirtualUnplugNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
VirtualUnplugNotification::Dispatch(
&BluetoothHidNotificationHandler::VirtualUnplugNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::HandshakeNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
{
HandshakeNotification::Dispatch(
&BluetoothHidNotificationHandler::HandshakeNotification,
UnpackPDUInitOp(aPDU));
}
void
BluetoothDaemonHidModule::HandleNtf(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes)
{
static void (BluetoothDaemonHidModule::* const HandleNtf[])(
const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
[0] = &BluetoothDaemonHidModule::ConnectionStateNtf,
[1] = &BluetoothDaemonHidModule::HidInfoNtf,
[2] = &BluetoothDaemonHidModule::ProtocolModeNtf,
[3] = &BluetoothDaemonHidModule::IdleTimeNtf,
[4] = &BluetoothDaemonHidModule::GetReportNtf,
[5] = &BluetoothDaemonHidModule::VirtualUnplugNtf,
[6] = &BluetoothDaemonHidModule::HandshakeNtf
};
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);
}
//
// Hid Interface
//
BluetoothDaemonHidInterface::BluetoothDaemonHidInterface(
BluetoothDaemonHidModule* aModule)
: mModule(aModule)
{ }
BluetoothDaemonHidInterface::~BluetoothDaemonHidInterface()
{ }
void
BluetoothDaemonHidInterface::SetNotificationHandler(
BluetoothHidNotificationHandler* aNotificationHandler)
{
MOZ_ASSERT(mModule);
mModule->SetNotificationHandler(aNotificationHandler);
}
/* Connect / Disconnect */
void
BluetoothDaemonHidInterface::Connect(
const BluetoothAddress& aBdAddr, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->ConnectCmd(aBdAddr, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
void
BluetoothDaemonHidInterface::Disconnect(
const BluetoothAddress& aBdAddr, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->DisconnectCmd(aBdAddr, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
/* Virtual Unplug */
void
BluetoothDaemonHidInterface::VirtualUnplug(
const BluetoothAddress& aBdAddr, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->VirtualUnplugCmd(aBdAddr, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
/* Set Info */
void
BluetoothDaemonHidInterface::SetInfo(
const BluetoothAddress& aBdAddr,
const BluetoothHidInfoParam& aHidInfoParam,
BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->SetInfoCmd(aBdAddr, aHidInfoParam, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
/* Protocol */
void
BluetoothDaemonHidInterface::GetProtocol(
const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtocolMode, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->GetProtocolCmd(aBdAddr, aHidProtocolMode, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
void
BluetoothDaemonHidInterface::SetProtocol(
const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtocolMode, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->SetProtocolCmd(aBdAddr, aHidProtocolMode, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
/* Report */
void
BluetoothDaemonHidInterface::GetReport(
const BluetoothAddress& aBdAddr, BluetoothHidReportType aType,
uint8_t aReportId, uint16_t aBuffSize, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->GetReportCmd(
aBdAddr, aType, aReportId, aBuffSize, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
void
BluetoothDaemonHidInterface::SetReport(
const BluetoothAddress& aBdAddr, BluetoothHidReportType aType,
const BluetoothHidReport& aReport, BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->SetReportCmd(
aBdAddr, aType, aReport, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
/* Send Data */
void
BluetoothDaemonHidInterface::SendData(
const BluetoothAddress& aBdAddr, uint16_t aDataLen, const uint8_t* aData,
BluetoothHidResultHandler* aRes)
{
MOZ_ASSERT(mModule);
nsresult rv = mModule->SendDataCmd(aBdAddr, aDataLen, aData, aRes);
if (NS_FAILED(rv)) {
DispatchError(aRes, rv);
}
}
void
BluetoothDaemonHidInterface::DispatchError(
BluetoothHidResultHandler* aRes, BluetoothStatus aStatus)
{
DaemonResultRunnable1<BluetoothHidResultHandler, void,
BluetoothStatus, BluetoothStatus>::Dispatch(
aRes, &BluetoothHidResultHandler::OnError,
ConstantInitOp1<BluetoothStatus>(aStatus));
}
void
BluetoothDaemonHidInterface::DispatchError(
BluetoothHidResultHandler* aRes, nsresult aRv)
{
BluetoothStatus status;
if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) {
status = STATUS_FAIL;
}
DispatchError(aRes, status);
}
END_BLUETOOTH_NAMESPACE

View File

@ -0,0 +1,298 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_bluedroid_BluetoothDaemonHidInterface_h
#define mozilla_dom_bluetooth_bluedroid_BluetoothDaemonHidInterface_h
#include "BluetoothDaemonHelpers.h"
#include "BluetoothInterface.h"
#include "mozilla/ipc/DaemonRunnables.h"
BEGIN_BLUETOOTH_NAMESPACE
using mozilla::ipc::DaemonSocketPDU;
using mozilla::ipc::DaemonSocketPDUHeader;
using mozilla::ipc::DaemonSocketResultHandler;
class BluetoothDaemonHidModule
{
public:
enum {
SERVICE_ID = 0x03
};
enum {
OPCODE_ERROR = 0x00,
OPCODE_CONNECT = 0x01,
OPCODE_DISCONNECT = 0x02,
OPCODE_VIRTUAL_UNPLUG = 0x03,
OPCODE_SET_INFO = 0x04,
OPCODE_GET_PROTOCOL = 0x05,
OPCODE_SET_PROTOCOL = 0x06,
OPCODE_GET_REPORT = 0x07,
OPCODE_SET_REPORT = 0x08,
OPCODE_SEND_DATA = 0x09
};
virtual nsresult Send(DaemonSocketPDU* aPDU,
DaemonSocketResultHandler* aRes) = 0;
void SetNotificationHandler(
BluetoothHidNotificationHandler* aNotificationHandler);
//
// Commands
//
nsresult ConnectCmd(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes);
nsresult DisconnectCmd(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes);
/* Virtual Unplug */
nsresult VirtualUnplugCmd(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes);
/* Set Info */
nsresult SetInfoCmd(
const BluetoothAddress& aBdAddr,
const BluetoothHidInfoParam& aHidInfoParam,
BluetoothHidResultHandler* aRes);
/* Protocol */
nsresult GetProtocolCmd(const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtocolMode,
BluetoothHidResultHandler* aRes);
nsresult SetProtocolCmd(const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtocolMode,
BluetoothHidResultHandler* aRes);
/* Report */
nsresult GetReportCmd(const BluetoothAddress& aBdAddr,
BluetoothHidReportType aType,
uint8_t aReportId,
uint16_t aBuffSize,
BluetoothHidResultHandler* aRes);
nsresult SetReportCmd(const BluetoothAddress& aBdAddr,
BluetoothHidReportType aType,
const BluetoothHidReport& aReport,
BluetoothHidResultHandler* aRes);
/* Send Data */
nsresult SendDataCmd(const BluetoothAddress& aBdAddr,
uint16_t aDataLen, const uint8_t* aData,
BluetoothHidResultHandler* aRes);
protected:
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes);
//
// Responses
//
typedef mozilla::ipc::DaemonResultRunnable0<
BluetoothHidResultHandler, void>
ResultRunnable;
typedef mozilla::ipc::DaemonResultRunnable1<
BluetoothHidResultHandler, void, BluetoothStatus, BluetoothStatus>
ErrorRunnable;
void ErrorRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void ConnectRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void DisconnectRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void VirtualUnplugRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void SetInfoRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void GetProtocolRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void SetProtocolRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void GetReportRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void SetReportRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void SendDataRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
BluetoothHidResultHandler* aRes);
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes);
//
// Notifications
//
class NotificationHandlerWrapper;
typedef mozilla::ipc::DaemonNotificationRunnable2<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidConnectionState,
const BluetoothAddress&, BluetoothHidConnectionState>
ConnectionStateNotification;
typedef mozilla::ipc::DaemonNotificationRunnable2<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidInfoParam,
const BluetoothAddress&, const BluetoothHidInfoParam&>
HidInfoNotification;
typedef mozilla::ipc::DaemonNotificationRunnable3<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidStatus, BluetoothHidProtocolMode,
const BluetoothAddress&, BluetoothHidStatus, BluetoothHidProtocolMode>
ProtocolModeNotification;
typedef mozilla::ipc::DaemonNotificationRunnable3<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidStatus, uint16_t,
const BluetoothAddress&, BluetoothHidStatus, uint16_t>
IdleTimeNotification;
typedef mozilla::ipc::DaemonNotificationRunnable3<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidStatus, BluetoothHidReport,
const BluetoothAddress&, BluetoothHidStatus,
const BluetoothHidReport&>
GetReportNotification;
typedef mozilla::ipc::DaemonNotificationRunnable2<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidStatus,
const BluetoothAddress&, BluetoothHidStatus>
VirtualUnplugNotification;
typedef mozilla::ipc::DaemonNotificationRunnable2<
NotificationHandlerWrapper, void,
BluetoothAddress, BluetoothHidStatus,
const BluetoothAddress&, BluetoothHidStatus>
HandshakeNotification;
void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void HidInfoNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void ProtocolModeNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void IdleTimeNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void GetReportNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void VirtualUnplugNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void HandshakeNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes);
static BluetoothHidNotificationHandler* sNotificationHandler;
};
class BluetoothDaemonHidInterface final
: public BluetoothHidInterface
{
public:
BluetoothDaemonHidInterface(BluetoothDaemonHidModule* aModule);
~BluetoothDaemonHidInterface();
void SetNotificationHandler(
BluetoothHidNotificationHandler* aNotificationHandler) override;
/* Connect / Disconnect */
void Connect(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes) override;
void Disconnect(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes) override;
/* Virtual Unplug */
void VirtualUnplug(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes) override;
/* Set Info */
void SetInfo(
const BluetoothAddress& aBdAddr,
const BluetoothHidInfoParam& aHidInfoParam,
BluetoothHidResultHandler* aRes) override;
/* Protocol */
void GetProtocol(const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtoclMode,
BluetoothHidResultHandler* aRes) override;
void SetProtocol(const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtocolMode,
BluetoothHidResultHandler* aRes) override;
/* Report */
void GetReport(const BluetoothAddress& aBdAddr,
BluetoothHidReportType aType,
uint8_t aReportId, uint16_t aBuffSize,
BluetoothHidResultHandler* aRes) override;
void SetReport(const BluetoothAddress& aBdAddr,
BluetoothHidReportType aType,
const BluetoothHidReport& aReport,
BluetoothHidResultHandler* aRes) override;
/* Send Data */
void SendData(const BluetoothAddress& aBdAddr,
uint16_t aDataLen, const uint8_t* aData,
BluetoothHidResultHandler* aRes) override;
private:
void DispatchError(BluetoothHidResultHandler* aRes,
BluetoothStatus aStatus);
void DispatchError(BluetoothHidResultHandler* aRes, nsresult aRv);
BluetoothDaemonHidModule* mModule;
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_bluedroid_BluetoothDaemonHidInterface_h

View File

@ -14,6 +14,7 @@
#include "BluetoothDaemonGattInterface.h"
#include "BluetoothDaemonHandsfreeInterface.h"
#include "BluetoothDaemonHelpers.h"
#include "BluetoothDaemonHidInterface.h"
#include "BluetoothDaemonSetupInterface.h"
#include "BluetoothDaemonSocketInterface.h"
#include "mozilla/Hal.h"
@ -80,6 +81,7 @@ class BluetoothDaemonProtocol final
, public BluetoothDaemonA2dpModule
, public BluetoothDaemonAvrcpModule
, public BluetoothDaemonGattModule
, public BluetoothDaemonHidModule
{
public:
BluetoothDaemonProtocol();
@ -124,6 +126,9 @@ private:
void HandleGattSvc(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes);
void HandleHidSvc(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes);
DaemonSocket* mConnection;
nsTArray<RefPtr<DaemonSocketResultHandler>> mResQ;
@ -215,6 +220,14 @@ BluetoothDaemonProtocol::HandleGattSvc(
BluetoothDaemonGattModule::HandleSvc(aHeader, aPDU, aRes);
}
void
BluetoothDaemonProtocol::HandleHidSvc(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
DaemonSocketResultHandler* aRes)
{
BluetoothDaemonHidModule::HandleSvc(aHeader, aPDU, aRes);
}
void
BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU)
{
@ -227,7 +240,8 @@ BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU)
&BluetoothDaemonProtocol::HandleCoreSvc,
[BluetoothDaemonSocketModule::SERVICE_ID] =
&BluetoothDaemonProtocol::HandleSocketSvc,
[0x03] = nullptr, // HID host
[BluetoothDaemonHidModule::SERVICE_ID] =
&BluetoothDaemonProtocol::HandleHidSvc,
[0x04] = nullptr, // PAN
[BluetoothDaemonHandsfreeModule::SERVICE_ID] =
&BluetoothDaemonProtocol::HandleHandsfreeSvc,
@ -634,6 +648,18 @@ BluetoothDaemonInterface::GetBluetoothGattInterface()
return mGattInterface;
}
BluetoothHidInterface*
BluetoothDaemonInterface::GetBluetoothHidInterface()
{
if (mHidInterface) {
return mHidInterface;
}
mHidInterface = new BluetoothDaemonHidInterface(mProtocol);
return mHidInterface;
}
// |DaemonSocketConsumer|, |ListenSocketConsumer|
void

View File

@ -30,6 +30,7 @@ class BluetoothDaemonHandsfreeInterface;
class BluetoothDaemonProtocol;
class BluetoothDaemonSetupInterface;
class BluetoothDaemonSocketInterface;
class BluetoothDaemonHidInterface;
class BluetoothDaemonInterface final
: public BluetoothInterface
@ -58,6 +59,7 @@ public:
BluetoothA2dpInterface* GetBluetoothA2dpInterface() override;
BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() override;
BluetoothGattInterface* GetBluetoothGattInterface() override;
BluetoothHidInterface* GetBluetoothHidInterface() override;
protected:
enum Channel {
@ -97,6 +99,7 @@ private:
nsAutoPtr<BluetoothDaemonA2dpInterface> mA2dpInterface;
nsAutoPtr<BluetoothDaemonAvrcpInterface> mAvrcpInterface;
nsAutoPtr<BluetoothDaemonGattInterface> mGattInterface;
nsAutoPtr<BluetoothDaemonHidInterface> mHidInterface;
};
END_BLUETOOTH_NAMESPACE

View File

@ -0,0 +1,610 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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 "BluetoothHidManager.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "nsIObserverService.h"
using namespace mozilla;
USING_BLUETOOTH_NAMESPACE
namespace {
StaticRefPtr<BluetoothHidManager> sBluetoothHidManager;
static BluetoothHidInterface* sBluetoothHidInterface = nullptr;
bool sInShutdown = false;
} // namesapce
const int BluetoothHidManager::MAX_NUM_CLIENTS = 1;
BluetoothHidManager::BluetoothHidManager()
: mHidConnected(false)
{
}
void
BluetoothHidManager::Reset()
{
mDeviceAddress.Clear();
mController = nullptr;
mHidConnected = false;
}
class BluetoothHidManager::RegisterModuleResultHandler final
: public BluetoothSetupResultHandler
{
public:
RegisterModuleResultHandler(BluetoothHidInterface* aInterface,
BluetoothProfileResultHandler* aRes)
: mInterface(aInterface)
, mRes(aRes)
{
MOZ_ASSERT(mInterface);
}
void OnError(BluetoothStatus aStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
BT_WARNING("BluetoothSetupInterface::RegisterModule failed for HID: %d",
(int)aStatus);
mInterface->SetNotificationHandler(nullptr);
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void RegisterModule() override
{
MOZ_ASSERT(NS_IsMainThread());
sBluetoothHidInterface = mInterface;
if (mRes) {
mRes->Init();
}
}
private:
BluetoothHidInterface* mInterface;
RefPtr<BluetoothProfileResultHandler> mRes;
};
class BluetoothHidManager::InitProfileResultHandlerRunnable final
: public nsRunnable
{
public:
InitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
nsresult aRv)
: mRes(aRes)
, mRv(aRv)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_SUCCEEDED(mRv)) {
mRes->Init();
} else {
mRes->OnError(mRv);
}
return NS_OK;
}
private:
RefPtr<BluetoothProfileResultHandler> mRes;
nsresult mRv;
};
// static
void
BluetoothHidManager::InitHidInterface(BluetoothProfileResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
if (sBluetoothHidInterface) {
BT_LOGR("Bluetooth HID interface is already initialized.");
RefPtr<nsRunnable> r =
new InitProfileResultHandlerRunnable(aRes, NS_OK);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID Init runnable");
}
return;
}
auto btInf = BluetoothInterface::GetInstance();
if (NS_WARN_IF(!btInf)) {
// If there's no backend interface, we dispatch a runnable
// that calls the profile result handler.
RefPtr<nsRunnable> r =
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID OnError runnable");
}
return;
}
auto setupInterface = btInf->GetBluetoothSetupInterface();
if (NS_WARN_IF(!setupInterface)) {
// If there's no Setup interface, we dispatch a runnable
// that calls the profile result handler.
RefPtr<nsRunnable> r =
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID OnError runnable");
}
return;
}
auto hidinterface = btInf->GetBluetoothHidInterface();
if (NS_WARN_IF(!hidinterface)) {
// If there's no HID interface, we dispatch a runnable
// that calls the profile result handler.
RefPtr<nsRunnable> r =
new InitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID OnError runnable");
}
return;
}
// Set notification handler _before_ registering the module. It could
// happen that we receive notifications, before the result handler runs.
hidinterface->SetNotificationHandler(BluetoothHidManager::Get());
setupInterface->RegisterModule(
SETUP_SERVICE_ID_HID, 0, MAX_NUM_CLIENTS,
new RegisterModuleResultHandler(hidinterface, aRes));
}
BluetoothHidManager::~BluetoothHidManager()
{ }
void
BluetoothHidManager::Uninit()
{
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE_VOID(obs);
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
BT_WARNING("Failed to remove shutdown observer!");
}
}
class BluetoothHidManager::UnregisterModuleResultHandler final
: public BluetoothSetupResultHandler
{
public:
UnregisterModuleResultHandler(BluetoothProfileResultHandler* aRes)
: mRes(aRes)
{ }
void OnError(BluetoothStatus aStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
BT_WARNING("BluetoothSetupInterface::UnregisterModule failed for HID: %d",
(int)aStatus);
sBluetoothHidInterface->SetNotificationHandler(nullptr);
sBluetoothHidInterface = nullptr;
sBluetoothHidManager->Uninit();
sBluetoothHidManager = nullptr;
if (mRes) {
mRes->OnError(NS_ERROR_FAILURE);
}
}
void UnregisterModule() override
{
MOZ_ASSERT(NS_IsMainThread());
sBluetoothHidInterface->SetNotificationHandler(nullptr);
sBluetoothHidInterface = nullptr;
sBluetoothHidManager->Uninit();
sBluetoothHidManager = nullptr;
if (mRes) {
mRes->Deinit();
}
}
private:
RefPtr<BluetoothProfileResultHandler> mRes;
};
class BluetoothHidManager::DeinitProfileResultHandlerRunnable final
: public nsRunnable
{
public:
DeinitProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
nsresult aRv)
: mRes(aRes)
, mRv(aRv)
{
MOZ_ASSERT(mRes);
}
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_SUCCEEDED(mRv)) {
mRes->Deinit();
} else {
mRes->OnError(mRv);
}
return NS_OK;
}
private:
RefPtr<BluetoothProfileResultHandler> mRes;
nsresult mRv;
};
// static
void
BluetoothHidManager::DeinitHidInterface(BluetoothProfileResultHandler* aRes)
{
MOZ_ASSERT(NS_IsMainThread());
if (!sBluetoothHidInterface) {
BT_LOGR("Bluetooth Hid interface has not been initialized.");
RefPtr<nsRunnable> r =
new DeinitProfileResultHandlerRunnable(aRes, NS_OK);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID Deinit runnable");
}
return;
}
auto btInf = BluetoothInterface::GetInstance();
if (NS_WARN_IF(!btInf)) {
// If there's no backend interface, we dispatch a runnable
// that calls the profile result handler.
RefPtr<nsRunnable> r =
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID OnError runnable");
}
return;
}
auto setupInterface = btInf->GetBluetoothSetupInterface();
if (NS_WARN_IF(!setupInterface)) {
// If there's no Setup interface, we dispatch a runnable
// that calls the profile result handler.
RefPtr<nsRunnable> r =
new DeinitProfileResultHandlerRunnable(aRes, NS_ERROR_FAILURE);
if (NS_FAILED(NS_DispatchToMainThread(r))) {
BT_LOGR("Failed to dispatch HID OnError runnable");
}
return;
}
setupInterface->UnregisterModule(
SETUP_SERVICE_ID_HID,
new UnregisterModuleResultHandler(aRes));
}
NS_IMETHODIMP
BluetoothHidManager::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(sBluetoothHidManager);
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
HandleShutdown();
return NS_OK;
}
MOZ_ASSERT(false, "BluetoothHidManager got unexpected topic!");
return NS_ERROR_UNEXPECTED;
}
// static
BluetoothHidManager*
BluetoothHidManager::Get()
{
MOZ_ASSERT(NS_IsMainThread());
// If we already exist, exit early
if (sBluetoothHidManager) {
return sBluetoothHidManager;
}
// If we're in shutdown, don't create a new instance
NS_ENSURE_FALSE(sInShutdown, nullptr);
// Create a new instance, register, and return
sBluetoothHidManager = new BluetoothHidManager();
return sBluetoothHidManager;
}
void
BluetoothHidManager::NotifyConnectionStateChanged(const nsAString& aType)
{
MOZ_ASSERT(NS_IsMainThread());
// Notify Gecko observers
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE_VOID(obs);
nsAutoString deviceAddressStr;
AddressToString(mDeviceAddress, deviceAddressStr);
if (NS_FAILED(obs->NotifyObservers(this, NS_ConvertUTF16toUTF8(aType).get(),
deviceAddressStr.get()))) {
BT_WARNING("Failed to notify observsers!");
}
// Dispatch an event of status change
DispatchStatusChangedEvent(
NS_LITERAL_STRING(HID_STATUS_CHANGED_ID), mDeviceAddress, IsConnected());
}
bool
BluetoothHidManager::IsConnected()
{
return mHidConnected;
}
void
BluetoothHidManager::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
Reset();
}
class BluetoothHidManager::ConnectResultHandler final
: public BluetoothHidResultHandler
{
public:
ConnectResultHandler(BluetoothHidManager* aHidManager)
: mHidManager(aHidManager)
{
MOZ_ASSERT(mHidManager);
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING("BluetoothHidInterface::Connect failed: %d",
(int)aStatus);
mHidManager->OnConnectError();
}
private:
BluetoothHidManager* mHidManager;
};
void
BluetoothHidManager::Connect(const BluetoothAddress& aDeviceAddress,
BluetoothProfileController* aController)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsCleared());
MOZ_ASSERT(aController && !mController);
if(sInShutdown) {
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
if(IsConnected()) {
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
return;
}
if(!sBluetoothHidInterface) {
BT_LOGR("sBluetoothHidInterface is null");
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
return;
}
mDeviceAddress = aDeviceAddress;
mController = aController;
sBluetoothHidInterface->Connect(mDeviceAddress,
new ConnectResultHandler(this));
}
void
BluetoothHidManager::OnDisconnectError()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(mController);
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
mController = nullptr;
}
class BluetoothHidManager::DisconnectResultHandler final
: public BluetoothHidResultHandler
{
public:
DisconnectResultHandler(BluetoothHidManager* aHidManager)
: mHidManager(aHidManager)
{
MOZ_ASSERT(mHidManager);
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING("BluetoothHidInterface::Disconnect failed: %d",
(int)aStatus);
mHidManager->OnDisconnectError();
}
private:
BluetoothHidManager* mHidManager;
};
void
BluetoothHidManager::Disconnect(BluetoothProfileController* aController)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mController);
if (!IsConnected()) {
if (aController) {
aController->NotifyCompletion(
NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
}
return;
}
MOZ_ASSERT(!mDeviceAddress.IsCleared());
if (!sBluetoothHidInterface) {
BT_LOGR("sBluetoothHidInterface is null");
if (aController) {
aController->NotifyCompletion(
NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
}
return;
}
mController = aController;
sBluetoothHidInterface->Disconnect(mDeviceAddress,
new DisconnectResultHandler(this));
}
void
BluetoothHidManager::OnConnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->NotifyCompletion(aErrorStr);
mController = nullptr;
}
void
BluetoothHidManager::OnDisconnect(const nsAString& aErrorStr)
{
MOZ_ASSERT(NS_IsMainThread());
/**
* On the one hand, notify the controller that we've done for outbound
* connections. On the other hand, we do nothing for inbound connections.
*/
NS_ENSURE_TRUE_VOID(mController);
mController->NotifyCompletion(aErrorStr);
Reset();
}
void
BluetoothHidManager::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
sInShutdown = true;
Disconnect(nullptr);
sBluetoothHidManager = nullptr;
}
void
BluetoothHidManager::HandleBackendError()
{
MOZ_ASSERT(NS_IsMainThread());
if (mHidConnected) {
ConnectionStateNotification(mDeviceAddress,
HID_CONNECTION_STATE_DISCONNECTED);
}
}
void
BluetoothHidManager::GetAddress(BluetoothAddress& aDeviceAddress)
{
aDeviceAddress = mDeviceAddress;
}
void
BluetoothHidManager::OnUpdateSdpRecords(
const BluetoothAddress& aDeviceAddress)
{
// Bluedroid handles this part
MOZ_ASSERT(false);
}
void
BluetoothHidManager::OnGetServiceChannel(
const BluetoothAddress& aDeviceAddress,
const BluetoothUuid& aServiceUuid,
int aChannel)
{
// Bluedroid handles this part
MOZ_ASSERT(false);
}
//
// Bluetooth notifications
//
/**
* There are totally 10 connection states, and will receive 4 possible
* states: "connected", "connecting", "disconnected", "disconnecting".
* Here we only handle connected and disconnected states. We do nothing
* for remaining states.
*
* Possible cases are listed below:
* CONNECTED:
* 1. Successful inbound or outbound connection
* DISCONNECTED:
* 2. Attempt disconnection succeeded
* 3. Attempt connection failed
* 4. Either unpair from the remote device or the remote device is
* out of range in connected state
*/
void
BluetoothHidManager::ConnectionStateNotification(
const BluetoothAddress& aBdAddr, BluetoothHidConnectionState aState)
{
MOZ_ASSERT(NS_IsMainThread());
BT_LOGR("state %d", aState);
if (aState == HID_CONNECTION_STATE_CONNECTED) {
mHidConnected = true;
mDeviceAddress = aBdAddr;
NotifyConnectionStateChanged(
NS_LITERAL_STRING(BLUETOOTH_HID_STATUS_CHANGED_ID));
OnConnect(EmptyString());
} else if (aState == HID_CONNECTION_STATE_DISCONNECTED) {
mHidConnected = false;
NotifyConnectionStateChanged(
NS_LITERAL_STRING(BLUETOOTH_HID_STATUS_CHANGED_ID));
OnDisconnect(EmptyString());
}
}
NS_IMPL_ISUPPORTS(BluetoothHidManager, nsIObserver)

View File

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=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_bluedroid_BluetoothHidManager_h
#define mozilla_dom_bluetooth_bluedroid_BluetoothHidMnagaer_h
#include "BluetoothCommon.h"
#include "BluetoothInterface.h"
#include "BluetoothProfileController.h"
#include "BluetoothProfileManagerBase.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothHidManager : public BluetoothProfileManagerBase
, public BluetoothHidNotificationHandler
{
public:
BT_DECL_PROFILE_MGR_BASE
static const int MAX_NUM_CLIENTS;
void OnConnectError();
void OnDisconnectError();
virtual void GetName(nsACString& aName)
{
aName.AssignLiteral("HID");
}
static BluetoothHidManager* Get();
static void InitHidInterface(BluetoothProfileResultHandler* aRes);
static void DeinitHidInterface(BluetoothProfileResultHandler* aRes);
void HandleBackendError();
protected:
virtual ~BluetoothHidManager();
private:
class DeinitProfileResultHandlerRunnable;
class InitProfileResultHandlerRunnable;
class RegisterModuleResultHandler;
class UnregisterModuleResultHandler;
class ConnectResultHandler;
class DisconnectResultHandler;
BluetoothHidManager();
void Uninit();
void HandleShutdown();
void NotifyConnectionStateChanged(const nsAString& aType);
//
// Bluetooth notifications
//
void ConnectionStateNotification(
const BluetoothAddress& aBdAddr,
BluetoothHidConnectionState aState) override;
bool mHidConnected;
BluetoothAddress mDeviceAddress;
RefPtr<BluetoothProfileController> mController;
};
END_BLUETOOTH_NAMESPACE
#endif // mozilla_dom_bluetooth_bluedroid_BluetoothHidManager_h

View File

@ -2632,6 +2632,7 @@ BluetoothServiceBluedroid::BackendErrorNotification(bool aCrashed)
* Reset following profile manager states for unexpected backend crash.
* - HFP: connection state and audio state
* - A2DP: connection state
* - HID: connection state
*/
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
NS_ENSURE_TRUE_VOID(hfp);
@ -2639,6 +2640,9 @@ BluetoothServiceBluedroid::BackendErrorNotification(bool aCrashed)
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE_VOID(a2dp);
a2dp->HandleBackendError();
BluetoothHidManager* hid = BluetoothHidManager::Get();
NS_ENSURE_TRUE_VOID(hid);
hid->HandleBackendError();
mIsRestart = true;
BT_LOGR("Recovery step2: stop bluetooth");

View File

@ -207,6 +207,7 @@ extern bool gBluetoothDebugFlag;
*/
#define A2DP_STATUS_CHANGED_ID "a2dpstatuschanged"
#define HFP_STATUS_CHANGED_ID "hfpstatuschanged"
#define HID_STATUS_CHANGED_ID "hidstatuschanged"
#define SCO_STATUS_CHANGED_ID "scostatuschanged"
/**
@ -307,6 +308,13 @@ extern bool gBluetoothDebugFlag;
*/
#define BLUETOOTH_GATT_MAX_ATTR_LEN 600
/**
* The maximum descriptor length defined in BlueZ ipc spec.
* Please refer to http://git.kernel.org/cgit/bluetooth/bluez.git/tree/\
* android/hal-ipc-api.txt#n532
*/
#define BLUETOOTH_HID_MAX_DESC_LEN 884
BEGIN_BLUETOOTH_NAMESPACE
enum BluetoothStatus {
@ -876,6 +884,64 @@ enum BluetoothSocketType {
EL2CAP = 4
};
struct BluetoothHidInfoParam {
uint16_t mAttributeMask;
uint8_t mSubclass;
uint8_t mApplicationId;
uint16_t mVendorId;
uint16_t mProductId;
uint16_t mVersion;
uint8_t mCountryCode;
uint16_t mDescriptorLength;
uint8_t mDescriptorValue[BLUETOOTH_HID_MAX_DESC_LEN];
};
struct BluetoothHidReport {
nsTArray<uint8_t> mReportData;
};
enum BluetoothHidProtocolMode {
HID_PROTOCOL_MODE_REPORT = 0x00,
HID_PROTOCOL_MODE_BOOT = 0x01,
HID_PROTOCOL_MODE_UNSUPPORTED = 0xff
};
enum BluetoothHidReportType {
HID_REPORT_TYPE_INPUT = 0x01,
HID_REPORT_TYPE_OUTPUT = 0x02,
HID_REPORT_TYPE_FEATURE = 0x03
};
enum BluetoothHidConnectionState {
HID_CONNECTION_STATE_CONNECTED,
HID_CONNECTION_STATE_CONNECTING,
HID_CONNECTION_STATE_DISCONNECTED,
HID_CONNECTION_STATE_DISCONNECTING,
HID_CONNECTION_STATE_FAILED_MOUSE_FROM_HOST,
HID_CONNECTION_STATE_FAILED_KEYBOARD_FROM_HOST,
HID_CONNECTION_STATE_FAILED_TOO_MANY_DEVICES,
HID_CONNECTION_STATE_FAILED_NO_HID_DRIVER,
HID_CONNECTION_STATE_FAILED_GENERIC,
HID_CONNECTION_STATE_UNKNOWN
};
enum BluetoothHidStatus {
HID_STATUS_OK,
HID_STATUS_HANDSHAKE_DEVICE_NOT_READY,
HID_STATUS_HANDSHAKE_INVALID_REPORT_ID,
HID_STATUS_HANDSHAKE_TRANSACTION_NOT_SPT,
HID_STATUS_HANDSHAKE_INVALID_PARAMETER,
HID_STATUS_HANDSHAKE_GENERIC_ERROR,
HID_STATUS_GENERAL_ERROR,
HID_STATUS_SDP_ERROR,
HID_STATUS_SET_PROTOCOL_ERROR,
HID_STATUS_DEVICE_DATABASE_FULL,
HID_STATUS_DEVICE_TYPE_NOT_SUPPORTED,
HID_STATUS_NO_RESOURCES,
HID_STATUS_AUTHENTICATION_FAILED,
HID_STATUS_HDL
};
enum BluetoothHandsfreeAtResponse {
HFP_AT_RESPONSE_ERROR,
HFP_AT_RESPONSE_OK

View File

@ -267,6 +267,111 @@ BluetoothSocketResultHandler::Accept(int aSockFd,
BluetoothSocketInterface::~BluetoothSocketInterface()
{ }
//
//Hid Interface
//
//Notification handling
//
BluetoothHidNotificationHandler::BluetoothHidNotificationHandler()
{ }
BluetoothHidNotificationHandler::~BluetoothHidNotificationHandler()
{ }
void
BluetoothHidNotificationHandler::ConnectionStateNotification(
const BluetoothAddress& aBdAddr, BluetoothHidConnectionState aState)
{ }
void
BluetoothHidNotificationHandler::HidInfoNotification(
const BluetoothAddress& aBdAddr,
const BluetoothHidInfoParam& aHidInfoParam)
{ }
void
BluetoothHidNotificationHandler::ProtocolModeNotification(
const BluetoothAddress& aBdAddr, BluetoothHidStatus aStatus,
BluetoothHidProtocolMode aProtocolMode)
{ }
void
BluetoothHidNotificationHandler::IdleTimeNotification(
const BluetoothAddress& aBdAddr,
BluetoothHidStatus aStatus, uint16_t aIdleTime)
{ }
void
BluetoothHidNotificationHandler::GetReportNotification(
const BluetoothAddress& aBdAddr, BluetoothHidStatus aStatus,
const BluetoothHidReport& aReport)
{ }
void
BluetoothHidNotificationHandler::VirtualUnplugNotification(
const BluetoothAddress& aBdAddr, BluetoothHidStatus aStatus)
{ }
void
BluetoothHidNotificationHandler::HandshakeNotification(
const BluetoothAddress& aBdAddr, BluetoothHidStatus aStatus)
{ }
// Result handling
//
void BluetoothHidResultHandler::OnError(BluetoothStatus aStatus)
{
BT_WARNING("Received error code %d", (int)aStatus);
}
void
BluetoothHidResultHandler::Connect()
{ }
void
BluetoothHidResultHandler::Disconnect()
{ }
void
BluetoothHidResultHandler::VirtualUnplug()
{ }
void
BluetoothHidResultHandler::SetInfo()
{ }
void
BluetoothHidResultHandler::GetProtocol()
{ }
void
BluetoothHidResultHandler::SetProtocol()
{ }
void
BluetoothHidResultHandler::GetReport()
{ }
void
BluetoothHidResultHandler::SetReport()
{ }
void
BluetoothHidResultHandler::SendData()
{ }
// Interface
//
BluetoothHidInterface::BluetoothHidInterface()
{ }
BluetoothHidInterface::~BluetoothHidInterface()
{ }
//
// Handsfree Interface
//

View File

@ -276,6 +276,130 @@ protected:
virtual ~BluetoothSocketInterface();
};
//
// HID Interface
//
class BluetoothHidNotificationHandler
{
public:
virtual void
ConnectionStateNotification(const BluetoothAddress& aBdAddr,
BluetoothHidConnectionState aState);
virtual void
HidInfoNotification(
const BluetoothAddress& aBdAddr,
const BluetoothHidInfoParam& aHidInfoParam);
virtual void
ProtocolModeNotification(const BluetoothAddress& aBdAddr,
BluetoothHidStatus aStatus,
BluetoothHidProtocolMode aProtocolMode);
virtual void
IdleTimeNotification(const BluetoothAddress& aBdAddr,
BluetoothHidStatus aStatus,
uint16_t aIdleTime);
virtual void
GetReportNotification(const BluetoothAddress& aBdAddr,
BluetoothHidStatus aStatus,
const BluetoothHidReport& aReport);
virtual void
VirtualUnplugNotification(const BluetoothAddress& aBdAddr,
BluetoothHidStatus aStatus);
virtual void
HandshakeNotification(const BluetoothAddress& aBdAddr,
BluetoothHidStatus aStatus);
protected:
BluetoothHidNotificationHandler();
virtual ~BluetoothHidNotificationHandler();
};
class BluetoothHidResultHandler
: public mozilla::ipc::DaemonSocketResultHandler
{
public:
virtual void OnError(BluetoothStatus aStatus);
virtual void Connect();
virtual void Disconnect();
virtual void VirtualUnplug();
virtual void SetInfo();
virtual void GetProtocol();
virtual void SetProtocol();
virtual void GetReport();
virtual void SetReport();
virtual void SendData();
protected:
virtual ~BluetoothHidResultHandler() { }
};
class BluetoothHidInterface
{
public:
virtual void SetNotificationHandler(
BluetoothHidNotificationHandler* aNotificationHandler) = 0;
/* Connect / Disconnect */
virtual void Connect(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes) = 0;
virtual void Disconnect(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes) = 0;
/* Virtual Unplug */
virtual void VirtualUnplug(const BluetoothAddress& aBdAddr,
BluetoothHidResultHandler* aRes) = 0;
/* Set Info */
virtual void SetInfo(const BluetoothAddress& aBdAddr,
const BluetoothHidInfoParam& aHidInfoParam,
BluetoothHidResultHandler* aRes) = 0;
/* Protocol */
virtual void GetProtocol(const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtoclMode,
BluetoothHidResultHandler* aRes) = 0;
virtual void SetProtocol(const BluetoothAddress& aBdAddr,
BluetoothHidProtocolMode aHidProtocolMode,
BluetoothHidResultHandler* aRes) = 0;
/* Report */
virtual void GetReport(const BluetoothAddress& aBdAddr,
BluetoothHidReportType aType,
uint8_t aReportId,
uint16_t aBuffSize,
BluetoothHidResultHandler* aRes) = 0;
virtual void SetReport(const BluetoothAddress& aBdAddr,
BluetoothHidReportType aType,
const BluetoothHidReport& aReport,
BluetoothHidResultHandler* aRes) = 0;
/* Send Data */
virtual void SendData(const BluetoothAddress& aBdAddr,
uint16_t aDataLen, const uint8_t* aData,
BluetoothHidResultHandler* aRes) = 0;
protected:
BluetoothHidInterface();
virtual ~BluetoothHidInterface();
};
//
// Handsfree Interface
//
@ -1154,6 +1278,7 @@ public:
virtual BluetoothA2dpInterface* GetBluetoothA2dpInterface() = 0;
virtual BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() = 0;
virtual BluetoothGattInterface* GetBluetoothGattInterface() = 0;
virtual BluetoothHidInterface* GetBluetoothHidInterface() = 0;
protected:
BluetoothInterface();

View File

@ -188,6 +188,7 @@ BluetoothProfileController::SetupProfiles(bool aAssignServiceClass)
AddProfile(BluetoothHfpManager::Get());
AddProfile(BluetoothA2dpManager::Get());
AddProfile(BluetoothAvrcpManager::Get()); // register after A2DP
AddProfile(BluetoothHidManager::Get());
return;
}

View File

@ -539,6 +539,7 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
HandleDeviceUnpaired(aData.value());
} else if (aData.name().EqualsLiteral(HFP_STATUS_CHANGED_ID) ||
aData.name().EqualsLiteral(SCO_STATUS_CHANGED_ID) ||
aData.name().EqualsLiteral(HID_STATUS_CHANGED_ID) ||
aData.name().EqualsLiteral(A2DP_STATUS_CHANGED_ID)) {
MOZ_ASSERT(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const InfallibleTArray<BluetoothNamedValue>& arr =

View File

@ -90,9 +90,10 @@ public:
IMPL_EVENT_HANDLER(devicepaired);
IMPL_EVENT_HANDLER(deviceunpaired);
IMPL_EVENT_HANDLER(pairingaborted);
// HFP/A2DP/AVRCP
// HFP/A2DP/AVRCP/HID
IMPL_EVENT_HANDLER(a2dpstatuschanged);
IMPL_EVENT_HANDLER(hfpstatuschanged);
IMPL_EVENT_HANDLER(hidstatuschanged);
IMPL_EVENT_HANDLER(scostatuschanged);
IMPL_EVENT_HANDLER(requestmediaplaystatus);
// PBAP

View File

@ -17,7 +17,6 @@ if CONFIG['MOZ_B2G_BT']:
SOURCES += [
'common/BluetoothGattReplyRunnable.cpp',
'common/BluetoothHidManager.cpp',
'common/BluetoothInterface.cpp',
'common/BluetoothProfileController.cpp',
'common/BluetoothReplyRunnable.cpp',
@ -65,6 +64,7 @@ if CONFIG['MOZ_B2G_BT']:
'bluez/BluetoothAvrcpManager.cpp',
'bluez/BluetoothDBusService.cpp',
'bluez/BluetoothHfpManager.cpp',
'bluez/BluetoothHidManager.cpp',
'bluez/BluetoothOppManager.cpp',
'bluez/BluetoothSocket.cpp',
'bluez/BluetoothUnixSocketConnector.cpp'
@ -83,10 +83,12 @@ if CONFIG['MOZ_B2G_BT']:
'bluedroid/BluetoothDaemonGattInterface.cpp',
'bluedroid/BluetoothDaemonHandsfreeInterface.cpp',
'bluedroid/BluetoothDaemonHelpers.cpp',
'bluedroid/BluetoothDaemonHidInterface.cpp',
'bluedroid/BluetoothDaemonInterface.cpp',
'bluedroid/BluetoothDaemonSetupInterface.cpp',
'bluedroid/BluetoothDaemonSocketInterface.cpp',
'bluedroid/BluetoothGattManager.cpp',
'bluedroid/BluetoothHidManager.cpp',
'bluedroid/BluetoothMapBMessage.cpp',
'bluedroid/BluetoothMapFolder.cpp',
'bluedroid/BluetoothMapSmsManager.cpp',

View File

@ -63,6 +63,9 @@ interface BluetoothAdapter : EventTarget {
// Fired when handsfree connection status changed
attribute EventHandler onhfpstatuschanged;
// Fired when handsfree connection status changed
attribute EventHandler onhidstatuschanged;
// Fired when sco connection status changed
attribute EventHandler onscostatuschanged;