1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "BluetoothHidManager.h"
11 #include "BluetoothCommon.h"
12 #include "BluetoothService.h"
13 #include "BluetoothUtils.h"
15 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
16 #include "mozilla/Services.h"
17 #include "mozilla/StaticPtr.h"
18 #include "nsIObserverService.h"
19 #include "MainThreadUtils.h"
21 using namespace mozilla
;
22 USING_BLUETOOTH_NAMESPACE
25 StaticRefPtr
<BluetoothHidManager
> sBluetoothHidManager
;
26 bool sInShutdown
= false;
27 } // anonymous namespace
30 BluetoothHidManager::Observe(nsISupports
* aSubject
,
32 const char16_t
* aData
)
34 MOZ_ASSERT(sBluetoothHidManager
);
36 if (!strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
41 MOZ_ASSERT(false, "BluetoothHidManager got unexpected topic!");
42 return NS_ERROR_UNEXPECTED
;
45 BluetoothHidManager::BluetoothHidManager()
51 BluetoothHidManager::Reset()
54 mController
= nullptr;
58 BluetoothHidManager::Init()
60 MOZ_ASSERT(NS_IsMainThread());
62 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
63 NS_ENSURE_TRUE(obs
, false);
64 if (NS_FAILED(obs
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, false))) {
65 BT_WARNING("Failed to add shutdown observer!");
72 BluetoothHidManager::~BluetoothHidManager()
74 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
75 NS_ENSURE_TRUE_VOID(obs
);
76 if (NS_FAILED(obs
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
))) {
77 BT_WARNING("Failed to remove shutdown observer!");
83 BluetoothHidManager::Get()
85 MOZ_ASSERT(NS_IsMainThread());
87 // If we already exist, exit early
88 if (sBluetoothHidManager
) {
89 return sBluetoothHidManager
;
92 // If we're in shutdown, don't create a new instance
93 NS_ENSURE_FALSE(sInShutdown
, nullptr);
95 // Create a new instance, register, and return
96 BluetoothHidManager
* manager
= new BluetoothHidManager();
97 NS_ENSURE_TRUE(manager
->Init(), nullptr);
99 sBluetoothHidManager
= manager
;
100 return sBluetoothHidManager
;
104 BluetoothHidManager::HandleShutdown()
106 MOZ_ASSERT(NS_IsMainThread());
109 sBluetoothHidManager
= nullptr;
113 BluetoothHidManager::Connect(const nsAString
& aDeviceAddress
,
114 BluetoothProfileController
* aController
)
116 MOZ_ASSERT(NS_IsMainThread());
117 MOZ_ASSERT(!aDeviceAddress
.IsEmpty());
118 MOZ_ASSERT(aController
&& !mController
);
120 BluetoothService
* bs
= BluetoothService::Get();
121 if (!bs
|| sInShutdown
) {
122 aController
->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE
));
127 aController
->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED
));
131 mDeviceAddress
= aDeviceAddress
;
132 mController
= aController
;
134 if (NS_FAILED(bs
->SendInputMessage(aDeviceAddress
,
135 NS_LITERAL_STRING("Connect")))) {
136 aController
->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE
));
142 BluetoothHidManager::Disconnect(BluetoothProfileController
* aController
)
144 MOZ_ASSERT(NS_IsMainThread());
146 BluetoothService
* bs
= BluetoothService::Get();
149 aController
->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE
));
156 aController
->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED
));
161 MOZ_ASSERT(!mDeviceAddress
.IsEmpty());
162 MOZ_ASSERT(!mController
);
164 mController
= aController
;
166 if (NS_FAILED(bs
->SendInputMessage(mDeviceAddress
,
167 NS_LITERAL_STRING("Disconnect")))) {
168 aController
->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE
));
174 BluetoothHidManager::OnConnect(const nsAString
& aErrorStr
)
176 MOZ_ASSERT(NS_IsMainThread());
179 * On the one hand, notify the controller that we've done for outbound
180 * connections. On the other hand, we do nothing for inbound connections.
182 NS_ENSURE_TRUE_VOID(mController
);
184 nsRefPtr
<BluetoothProfileController
> controller
= mController
.forget();
185 controller
->NotifyCompletion(aErrorStr
);
189 BluetoothHidManager::OnDisconnect(const nsAString
& aErrorStr
)
191 MOZ_ASSERT(NS_IsMainThread());
194 * On the one hand, notify the controller that we've done for outbound
195 * connections. On the other hand, we do nothing for inbound connections.
197 NS_ENSURE_TRUE_VOID(mController
);
199 nsRefPtr
<BluetoothProfileController
> controller
= mController
.forget();
200 controller
->NotifyCompletion(aErrorStr
);
204 BluetoothHidManager::IsConnected()
210 BluetoothHidManager::HandleInputPropertyChanged(const BluetoothSignal
& aSignal
)
212 MOZ_ASSERT(NS_IsMainThread());
213 MOZ_ASSERT(aSignal
.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue
);
215 const InfallibleTArray
<BluetoothNamedValue
>& arr
=
216 aSignal
.value().get_ArrayOfBluetoothNamedValue();
217 MOZ_ASSERT(arr
.Length() == 1);
219 const nsString
& name
= arr
[0].name();
220 const BluetoothValue
& value
= arr
[0].value();
222 if (name
.EqualsLiteral("Connected")) {
223 MOZ_ASSERT(value
.type() == BluetoothValue::Tbool
);
224 MOZ_ASSERT(mConnected
!= value
.get_bool());
226 mConnected
= value
.get_bool();
227 NotifyStatusChanged();
229 OnConnect(EmptyString());
231 OnDisconnect(EmptyString());
237 BluetoothHidManager::NotifyStatusChanged()
239 MOZ_ASSERT(NS_IsMainThread());
241 NS_NAMED_LITERAL_STRING(type
, BLUETOOTH_HID_STATUS_CHANGED_ID
);
242 InfallibleTArray
<BluetoothNamedValue
> parameters
;
244 BT_APPEND_NAMED_VALUE(parameters
, "connected", mConnected
);
245 BT_APPEND_NAMED_VALUE(parameters
, "address", mDeviceAddress
);
247 BT_ENSURE_TRUE_VOID_BROADCAST_SYSMSG(type
, parameters
);
251 BluetoothHidManager::OnGetServiceChannel(const nsAString
& aDeviceAddress
,
252 const nsAString
& aServiceUuid
,
255 // Do nothing here as bluez acquires service channel and connects for us
259 BluetoothHidManager::OnUpdateSdpRecords(const nsAString
& aDeviceAddress
)
261 // Do nothing here as bluez acquires service channel and connects for us
265 BluetoothHidManager::GetAddress(nsAString
& aDeviceAddress
)
267 aDeviceAddress
= mDeviceAddress
;
270 NS_IMPL_ISUPPORTS(BluetoothHidManager
, nsIObserver
)