mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
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:
parent
4e06af5a13
commit
73c9a25e36
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
*/
|
||||
|
677
dom/bluetooth/bluedroid/BluetoothDaemonHidInterface.cpp
Normal file
677
dom/bluetooth/bluedroid/BluetoothDaemonHidInterface.cpp
Normal 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
|
298
dom/bluetooth/bluedroid/BluetoothDaemonHidInterface.h
Normal file
298
dom/bluetooth/bluedroid/BluetoothDaemonHidInterface.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
610
dom/bluetooth/bluedroid/BluetoothHidManager.cpp
Normal file
610
dom/bluetooth/bluedroid/BluetoothHidManager.cpp
Normal 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)
|
71
dom/bluetooth/bluedroid/BluetoothHidManager.h
Normal file
71
dom/bluetooth/bluedroid/BluetoothHidManager.h
Normal 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
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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();
|
||||
|
@ -188,6 +188,7 @@ BluetoothProfileController::SetupProfiles(bool aAssignServiceClass)
|
||||
AddProfile(BluetoothHfpManager::Get());
|
||||
AddProfile(BluetoothA2dpManager::Get());
|
||||
AddProfile(BluetoothAvrcpManager::Get()); // register after A2DP
|
||||
AddProfile(BluetoothHidManager::Get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user