|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Bluetooth Toggle application is being used by Telephony for |
|
15 * switching on/off Bluetooth when a long key press of asterisk |
|
16 * is detected |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 // Include Files |
|
23 #include "bttoggle.h" |
|
24 #include "btengprivatecrkeys.h" |
|
25 #include "btengsrvbbconnectionmgr.h" |
|
26 #include "debug.h" |
|
27 |
|
28 #include <e32base.h> |
|
29 #include <e32std.h> |
|
30 |
|
31 void Panic(TBTTogglePanic aPanic) |
|
32 { |
|
33 User::Panic(KBTTogglePanicCat, aPanic); |
|
34 } |
|
35 |
|
36 LOCAL_C void DoStartL() |
|
37 { |
|
38 //Create active scheduler (to run active objects) |
|
39 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); |
|
40 CleanupStack::PushL (scheduler ); |
|
41 CActiveScheduler::Install (scheduler ); |
|
42 |
|
43 CBTToggle* bttoggle = CBTToggle::NewL(); |
|
44 bttoggle->ToggleBT(); |
|
45 |
|
46 CActiveScheduler::Start(); |
|
47 |
|
48 delete bttoggle; |
|
49 CleanupStack::PopAndDestroy (scheduler ); |
|
50 return; |
|
51 } |
|
52 |
|
53 // Global Functions |
|
54 GLDEF_C TInt E32Main() |
|
55 { |
|
56 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
57 |
|
58 // Run application code inside TRAP harness |
|
59 TRAPD(mainError, DoStartL()); |
|
60 if (mainError) |
|
61 { |
|
62 TRACE_INFO((_L("[BTENG][BTTOGGLE]DoStartL error: %d" ), mainError)) |
|
63 } |
|
64 delete cleanup; |
|
65 return KErrNone; |
|
66 } |
|
67 |
|
68 // ========================================================== |
|
69 // CBTToggle::CBTToggle() |
|
70 // Constructor |
|
71 // ========================================================== |
|
72 // |
|
73 CBTToggle::CBTToggle() : CActive(EPriorityStandard) |
|
74 { |
|
75 } |
|
76 |
|
77 // ========================================================== |
|
78 // CBTToggle::~CBTToggle() |
|
79 // Destructor |
|
80 // ========================================================== |
|
81 // |
|
82 CBTToggle::~CBTToggle() |
|
83 { |
|
84 TRACE_FUNC_ENTRY |
|
85 |
|
86 Cancel(); |
|
87 delete iSettings; |
|
88 iNotifier.Close(); |
|
89 iLinkCountProperty.Close(); |
|
90 |
|
91 TRACE_FUNC_EXIT |
|
92 } |
|
93 |
|
94 // ========================================================== |
|
95 // CBTToggle::ConstructL |
|
96 // |
|
97 // ========================================================== |
|
98 // |
|
99 void CBTToggle::ConstructL() |
|
100 { |
|
101 TRACE_FUNC_ENTRY |
|
102 iSettings = CBTEngSettings::NewL(NULL); |
|
103 CActiveScheduler::Add(this); |
|
104 iActiveNotifier = ENoneQuery; |
|
105 TInt errConnect = iNotifier.Connect(); |
|
106 if (errConnect) |
|
107 { |
|
108 TRACE_INFO((_L("[BTENG][BTTOGGLE] iNotifier connect fail: %d" ), errConnect)) |
|
109 User::Leave(errConnect); |
|
110 } |
|
111 User::LeaveIfError( iLinkCountProperty.Attach( KPropertyUidBluetoothCategory, |
|
112 KPropertyKeyBluetoothGetPHYCount ) ); |
|
113 TRACE_FUNC_EXIT |
|
114 } |
|
115 |
|
116 // ========================================================== |
|
117 // CBTToggle::NewL |
|
118 // |
|
119 // ========================================================== |
|
120 // |
|
121 CBTToggle* CBTToggle::NewL() |
|
122 { |
|
123 TRACE_FUNC_ENTRY |
|
124 CBTToggle* self = new ( ELeave ) CBTToggle(); |
|
125 CleanupStack::PushL(self); |
|
126 self->ConstructL(); |
|
127 CleanupStack::Pop(self); |
|
128 TRACE_FUNC_EXIT |
|
129 return self; |
|
130 } |
|
131 |
|
132 // ========================================================== |
|
133 // CBTToggle::ToggleBT |
|
134 // Toggles Bluetooth on or off and shows dialog |
|
135 // (if the BT is switched for the first time after flashing) |
|
136 // and notification |
|
137 // ========================================================== |
|
138 // |
|
139 void CBTToggle::ToggleBT() |
|
140 { |
|
141 TRACE_FUNC_ENTRY |
|
142 |
|
143 TBTPowerStateValue state; |
|
144 iSettings->GetPowerState(state); |
|
145 |
|
146 //BT off |
|
147 if (EBTPowerOff == state) |
|
148 { |
|
149 TBool isInOffline = CheckOfflineMode(); |
|
150 if (isInOffline) //Offline mode |
|
151 { |
|
152 TRACE_INFO((_L("[BTENG][BTTOGGLE]Offline mode") )) |
|
153 SwitchBtOnWithPowerNotif(); |
|
154 } |
|
155 else //other than offline |
|
156 { |
|
157 TBuf<KHCILocalDeviceNameMaxLength> localName; |
|
158 iSettings->GetLocalName(localName); |
|
159 |
|
160 //There is no BT local name defined |
|
161 if (0 >= localName.Length()) |
|
162 { |
|
163 SwitchBtOnWithPowerNotif(); |
|
164 } |
|
165 else //BT name already defined |
|
166 { |
|
167 ChangeBtPowerMode(EBTPowerOn); |
|
168 } |
|
169 } |
|
170 } |
|
171 else //BT on |
|
172 { |
|
173 TInt linkCount = 0; |
|
174 TInt errLinkCount = iLinkCountProperty.Get( linkCount ); |
|
175 TRACE_INFO((_L("[BTENG][BTTOGGLE] linkCount: %d error: %d" ), linkCount, errLinkCount)) |
|
176 |
|
177 //BT Connected or error obtaining link count (in the case of error, we are cautious and assume BT is connected) |
|
178 if (errLinkCount || linkCount > 0) |
|
179 { |
|
180 TRACE_INFO((_L("[BTENG][BTTOGGLE]Ongoing BT connection") )) |
|
181 __ASSERT_DEBUG(iActiveNotifier == ENoneQuery, Panic(EBTToggleInvalidStateCloseConnectionQuery)); |
|
182 |
|
183 iActiveNotifier = ECloseConnectionQuery; |
|
184 iPckgGenericQuery().iMessageType = EBTSwitchOffAnyway; |
|
185 iPckgGenericQuery().iNameExists = EFalse; |
|
186 iNotifier.StartNotifierAndGetResponse(iStatus, KBTGenericQueryNotifierUid, iPckgGenericQuery, iConnQuery ); |
|
187 SetActive(); |
|
188 } |
|
189 //No open connections |
|
190 else |
|
191 { |
|
192 TRACE_INFO((_L("[BTENG][BTTOGGLE] No BT connections") )) |
|
193 ChangeBtPowerMode(EBTPowerOff); |
|
194 } |
|
195 } |
|
196 TRACE_FUNC_EXIT |
|
197 } |
|
198 |
|
199 // ========================================================== |
|
200 // CBTToggle::CheckOfflineMode |
|
201 // Checks whether current profile is Offline |
|
202 // ========================================================== |
|
203 // |
|
204 TBool CBTToggle::CheckOfflineMode() |
|
205 { |
|
206 TRACE_FUNC_ENTRY |
|
207 TCoreAppUIsNetworkConnectionAllowed offline = ECoreAppUIsNetworkConnectionAllowed; |
|
208 TBTEnabledInOfflineMode enabledInOffline; |
|
209 iSettings->GetOfflineModeSettings(offline, enabledInOffline); |
|
210 TRACE_FUNC_EXIT |
|
211 return !offline; |
|
212 } |
|
213 |
|
214 // ========================================================== |
|
215 // CBTToggle::SwitchBtOnWithPowerNotif |
|
216 // Switches BT on using Power Mode notifier |
|
217 // ========================================================== |
|
218 // |
|
219 void CBTToggle::SwitchBtOnWithPowerNotif() |
|
220 { |
|
221 TRACE_FUNC_ENTRY |
|
222 __ASSERT_DEBUG(iActiveNotifier == ENoneQuery, Panic(EBTToggleInvalidStatePowerModeQuery)); |
|
223 |
|
224 iActiveNotifier = EPowerModeQuery; |
|
225 // EBTNameQuery is used here as the message type, since the local device name may be modified by the user upon power-on. |
|
226 iPckgGenericQuery().iMessageType = EBTNameQuery; |
|
227 iNotifier.StartNotifierAndGetResponse(iStatus, KPowerModeSettingNotifierUid, iPckgGenericQuery, iPowerResult ); |
|
228 SetActive(); |
|
229 TRACE_FUNC_EXIT |
|
230 } |
|
231 |
|
232 |
|
233 // ========================================================== |
|
234 // CBTToggle::ChangeBtPowerMode |
|
235 // Change BT Power Mode using CBTEngSettings API |
|
236 // and show notification |
|
237 // ========================================================== |
|
238 // |
|
239 TInt CBTToggle::ChangeBtPowerMode(TBTPowerStateValue aNewPowerState) |
|
240 { |
|
241 TRACE_FUNC_ENTRY |
|
242 __ASSERT_DEBUG(iActiveNotifier == ENoneQuery, Panic(EBTToggleInvalidStateChangeBtPowerMode)); |
|
243 |
|
244 TRequestStatus *stat = &iStatus; |
|
245 TInt errPower = iSettings->SetPowerState(aNewPowerState); |
|
246 |
|
247 if (KErrNone == errPower) |
|
248 { |
|
249 ShowNotification( static_cast<TBool>(aNewPowerState) ); |
|
250 } |
|
251 iActiveNotifier = EFakeNotif; |
|
252 iStatus = KRequestPending; |
|
253 User::RequestComplete(stat, KErrNone); |
|
254 SetActive(); |
|
255 |
|
256 TRACE_FUNC_EXIT |
|
257 return errPower; |
|
258 } |
|
259 |
|
260 // ========================================================== |
|
261 // CBTToggle::ShowNotification |
|
262 // Presents generic info notification about BT on (ETrue) |
|
263 // and BT off (EFalse) |
|
264 // ========================================================== |
|
265 // |
|
266 void CBTToggle::ShowNotification( TBool aStatus ) |
|
267 { |
|
268 TRACE_FUNC_ENTRY |
|
269 TBTGenericInfoNotiferParamsPckg pckgGenericInfo; |
|
270 TBuf8<sizeof(TInt)> result; |
|
271 |
|
272 //BT turned on |
|
273 if (aStatus) |
|
274 { |
|
275 pckgGenericInfo().iMessageType = EBTSwitchedOn; |
|
276 } |
|
277 //BT turned off |
|
278 else |
|
279 { |
|
280 pckgGenericInfo().iMessageType = EBTSwitchedOff; |
|
281 } |
|
282 |
|
283 //Cancel if there is any outstanding notification |
|
284 Cancel(); |
|
285 |
|
286 //Start new notification |
|
287 iNotifier.StartNotifier(KBTGenericInfoNotifierUid, pckgGenericInfo, result); |
|
288 |
|
289 TRACE_FUNC_EXIT |
|
290 } |
|
291 |
|
292 // ========================================================== |
|
293 // CBTToggle::DoCancel |
|
294 // Cancel |
|
295 // ========================================================== |
|
296 // |
|
297 void CBTToggle::DoCancel() |
|
298 { |
|
299 TRACE_FUNC_ENTRY |
|
300 if ( EPowerModeQuery == iActiveNotifier ) |
|
301 { |
|
302 iNotifier.CancelNotifier(KPowerModeSettingNotifierUid); |
|
303 } |
|
304 else if ( ECloseConnectionQuery == iActiveNotifier ) |
|
305 { |
|
306 iNotifier.CancelNotifier(KBTGenericQueryNotifierUid); |
|
307 } |
|
308 |
|
309 // For all cancels, we must reset iActiveNotifier back to ENoneQuery |
|
310 // to permit another request to be made. |
|
311 iActiveNotifier = ENoneQuery; |
|
312 |
|
313 TRACE_FUNC_EXIT |
|
314 } |
|
315 |
|
316 // ========================================================== |
|
317 // CBTToggle::RunL |
|
318 // Inherited from CActive |
|
319 // ========================================================== |
|
320 // |
|
321 void CBTToggle::RunL() |
|
322 { |
|
323 TRACE_FUNC_ENTRY |
|
324 |
|
325 User::LeaveIfError(iStatus.Int()); |
|
326 |
|
327 // For all completes, we must reset iActiveNotifier back to ENoneQuery |
|
328 // to permit another request to be made. |
|
329 switch (iActiveNotifier) |
|
330 { |
|
331 case EPowerModeQuery: |
|
332 iActiveNotifier = ENoneQuery; |
|
333 ShowNotification(ETrue); |
|
334 CActiveScheduler::Stop(); |
|
335 break; |
|
336 case ECloseConnectionQuery: |
|
337 iActiveNotifier = ENoneQuery; |
|
338 if (iConnQuery()) //user wants to stop existing connection |
|
339 { |
|
340 ChangeBtPowerMode(EBTPowerOff); |
|
341 } |
|
342 else |
|
343 { |
|
344 CActiveScheduler::Stop(); |
|
345 } |
|
346 break; |
|
347 default: //ENoneQuery or EFakeNotif |
|
348 iActiveNotifier = ENoneQuery; |
|
349 CActiveScheduler::Stop(); |
|
350 } |
|
351 |
|
352 TRACE_FUNC_EXIT |
|
353 } |
|
354 |
|
355 // ========================================================== |
|
356 // CBTToggle::RunError |
|
357 // Inherited from CActive |
|
358 // ========================================================== |
|
359 // |
|
360 TInt CBTToggle::RunError(TInt aError) |
|
361 { |
|
362 TRACE_INFO((_L("[BTENG][BTTOGGLE]RunL error %d"), aError )) |
|
363 CActiveScheduler::Stop(); |
|
364 |
|
365 return aError; |
|
366 } |