|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <bluetooth/logger.h> |
|
17 |
|
18 #include "pancoexistenceconnectioncontroller.h" |
|
19 #include "panagtutils.h" |
|
20 |
|
21 #ifdef __FLOG_ACTIVE |
|
22 _LIT8(KLogComponent, LOG_COMPONENT_PAN_AGENT); |
|
23 #endif |
|
24 |
|
25 // This is the identifer of the shared mutex used to allow safe read / write of the coexistence P&S key. |
|
26 // This can only be changed if all other existing definitions of the mutex name are also changed. |
|
27 _LIT(KIPBearerCoexistenceMutex, "IPBearerCoexistenceMutex"); |
|
28 |
|
29 using namespace PanAgent; |
|
30 |
|
31 CPanCoexistenceConnectionController* CPanCoexistenceConnectionController::NewL(MPanCoexistenceConnectionObserver& aObserver) |
|
32 { |
|
33 CPanCoexistenceConnectionController* self = new(ELeave) CPanCoexistenceConnectionController(aObserver); |
|
34 CleanupStack::PushL(self); |
|
35 self->ConstructL(); |
|
36 CleanupStack::Pop(self); |
|
37 return self; |
|
38 } |
|
39 |
|
40 CPanCoexistenceConnectionController::CPanCoexistenceConnectionController(MPanCoexistenceConnectionObserver& aObserver) |
|
41 : CActive(EPriorityStandard),iPanCoexistenceConnectionObserver(aObserver) |
|
42 { |
|
43 CActiveScheduler::Add(this); |
|
44 } |
|
45 |
|
46 CPanCoexistenceConnectionController::~CPanCoexistenceConnectionController() |
|
47 { |
|
48 Cancel(); |
|
49 iProperty.Close(); |
|
50 iMutex.Close(); |
|
51 } |
|
52 |
|
53 void CPanCoexistenceConnectionController::ConstructL() |
|
54 { |
|
55 LOG_FUNC |
|
56 |
|
57 // Creates a global mutex and open a handle to the mutex. |
|
58 // (Note if CreateGlobal returns wirh KErrNone then the mutex is also opened). |
|
59 TInt err = iMutex.CreateGlobal(KIPBearerCoexistenceMutex); |
|
60 if (err==KErrAlreadyExists) |
|
61 { |
|
62 err=iMutex.OpenGlobal(KIPBearerCoexistenceMutex); |
|
63 } |
|
64 |
|
65 User::LeaveIfError(err); |
|
66 |
|
67 // Define property |
|
68 err = DefineProperty(); |
|
69 |
|
70 if(err != KErrNone && err != KErrAlreadyExists) |
|
71 { |
|
72 User::Leave(err); |
|
73 } |
|
74 |
|
75 // Attach to the property |
|
76 TSecureId thisSID = RProcess().SecureId(); |
|
77 User::LeaveIfError(iProperty.Attach(thisSID, KIPBearerCoexistenceProperty)); |
|
78 |
|
79 SubscribeToProperty(); |
|
80 } |
|
81 |
|
82 //Define the P&S key |
|
83 TInt CPanCoexistenceConnectionController::DefineProperty() |
|
84 { |
|
85 TInt err; |
|
86 _LIT_SECURITY_POLICY_PASS(KPassPolicy); |
|
87 _LIT_SECURITY_POLICY_C1(KNetworkControl, ECapabilityNetworkControl); |
|
88 |
|
89 err=iProperty.Define(KIPBearerCoexistenceProperty, |
|
90 RProperty::EInt, |
|
91 KPassPolicy, // Read policy |
|
92 KNetworkControl); // Write policy |
|
93 return err; |
|
94 } |
|
95 |
|
96 // If another IP bearer has not set the key then this method will set the P&S key to indicate |
|
97 // that a PAN connection is active. |
|
98 TInt CPanCoexistenceConnectionController::TryToCreateNewPanConnection() |
|
99 { |
|
100 LOG_FUNC |
|
101 |
|
102 TInt err = KErrNone; |
|
103 |
|
104 // Wait for the Mutex to become free and then acquire it. |
|
105 iMutex.Wait(); |
|
106 |
|
107 //Get the property |
|
108 TIPBearerCoexistenceStatus value = ReadStatus(); |
|
109 |
|
110 switch (value) |
|
111 { |
|
112 case ENoneIsActive: |
|
113 iActivePanConnectionExists = ETrue; |
|
114 iLocallyInitiatedTransition = ETrue; |
|
115 |
|
116 WriteStatus(EBTPanIsActive); |
|
117 break; |
|
118 |
|
119 case EBTPanIsActive: |
|
120 //P&S key is allready set to EBTPanIsActive |
|
121 __ASSERT_DEBUG(EFalse, PanAgentPanic(EBTPanIsAlreadyActive)); |
|
122 break; |
|
123 |
|
124 case ERndisIsActive: |
|
125 //BT PAN cannot be active at the point, since Rndis holds the key |
|
126 __ASSERT_DEBUG(!iActivePanConnectionExists, PanAgentPanic(ERndisIsActiveWhenBTPanTriesToBeActive)); |
|
127 err = KErrAccessDenied; |
|
128 break; |
|
129 |
|
130 default: |
|
131 __ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty)); |
|
132 break; |
|
133 } |
|
134 |
|
135 //Release the mutex |
|
136 iMutex.Signal(); |
|
137 return err; |
|
138 } |
|
139 |
|
140 // If the co-existence P&S key has been set by the PAN service then |
|
141 // clear the P&S key |
|
142 void CPanCoexistenceConnectionController::HandleAllPanConnectionsClosed() |
|
143 { |
|
144 LOG_FUNC |
|
145 |
|
146 // Get the property |
|
147 TIPBearerCoexistenceStatus value = ReadStatus(); |
|
148 |
|
149 switch(value) |
|
150 { |
|
151 case ENoneIsActive: |
|
152 // The P&S key is ENoneIsActive, when BT PAN tries to clear it. |
|
153 __ASSERT_DEBUG(EFalse, PanAgentPanic(EClearKeyWhenNoneIsActive)); |
|
154 break; |
|
155 |
|
156 case ERndisIsActive: |
|
157 // This is the race condition where RNDIS sets the key when BT PAN incoming connection request |
|
158 // goes through the stack, we didn't own the key, do nothing |
|
159 LOG(_L("CPanCoexistenceConnectionController::HandleAllPanConnectionsClosed, enter the race condition")); |
|
160 break; |
|
161 |
|
162 case EBTPanIsActive: |
|
163 __ASSERT_DEBUG(iActivePanConnectionExists, PanAgentPanic(ENoPanConnectionExistsWhileInPanIsActiveCoexistencePandSState)); |
|
164 iActivePanConnectionExists = EFalse; |
|
165 iLocallyInitiatedTransition = ETrue; |
|
166 |
|
167 WriteStatus(ENoneIsActive); |
|
168 break; |
|
169 |
|
170 default: |
|
171 __ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty)); |
|
172 break; |
|
173 } |
|
174 } |
|
175 |
|
176 // Read property and handle error conditions |
|
177 TIPBearerCoexistenceStatus CPanCoexistenceConnectionController::ReadStatus() |
|
178 { |
|
179 LOG_FUNC |
|
180 |
|
181 //Get the property |
|
182 TInt value = ENoneIsActive; |
|
183 TInt err = iProperty.Get(value); |
|
184 |
|
185 if(err) |
|
186 { |
|
187 if (err == KErrNotFound) |
|
188 { |
|
189 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyIsNotDefined)); |
|
190 |
|
191 //Redefine property if property has been deleted |
|
192 err = DefineProperty(); |
|
193 |
|
194 if (err == KErrNone) |
|
195 { |
|
196 value = iActivePanConnectionExists ? EBTPanIsActive : ENoneIsActive; |
|
197 err = iProperty.Set(value); |
|
198 if (err) |
|
199 { |
|
200 //reset failed, log the error and assert the debug |
|
201 LOG1(_L("CPanCoexistenceConnectionController::ReadProperty reset Property with error: %d"), err); |
|
202 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertySetFailed)); |
|
203 } |
|
204 } |
|
205 else |
|
206 { |
|
207 //Define P&S failed, log the error and assert the debug |
|
208 LOG1(_L("CPanCoexistenceConnectionController::ReadProperty Define Property with error: %d"), err); |
|
209 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyCanNotBeDefined)); |
|
210 } |
|
211 } |
|
212 else |
|
213 { |
|
214 //Getter returns error rather than KErrNotFound, log the error and assert the debug |
|
215 LOG1(_L("CPanCoexistenceConnectionController::ReadProperty Get Property with error: %d"), err); |
|
216 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyGetFailed)); |
|
217 } |
|
218 } |
|
219 |
|
220 return static_cast<TIPBearerCoexistenceStatus>(value); |
|
221 } |
|
222 |
|
223 //Write the property and handle setter errors |
|
224 void CPanCoexistenceConnectionController::WriteStatus(TIPBearerCoexistenceStatus aStatus) |
|
225 { |
|
226 LOG_FUNC |
|
227 |
|
228 //Set the property |
|
229 TInt err = iProperty.Set(aStatus); |
|
230 if (err) |
|
231 { |
|
232 if (err == KErrNotFound) |
|
233 { |
|
234 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyIsNotDefined)); |
|
235 |
|
236 //Redefine property if property has been deleted |
|
237 err = DefineProperty(); |
|
238 |
|
239 if (err == KErrNone) |
|
240 { |
|
241 //Reset the property |
|
242 err = iProperty.Set(aStatus); |
|
243 if (err) |
|
244 { |
|
245 LOG1(_L("CPanCoexistenceConnectionController::WriteStatus Set Property with error: %d"), err); |
|
246 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertySetFailed)); |
|
247 } |
|
248 } |
|
249 else |
|
250 { |
|
251 //Define P&S failed, log the error and assert the debug |
|
252 LOG1(_L("CPanCoexistenceConnectionController::ReadProperty Define Property with error: %d"), err); |
|
253 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyCanNotBeDefined)); |
|
254 //Nothing else we can do at this stage |
|
255 } |
|
256 |
|
257 } |
|
258 else |
|
259 { |
|
260 //Setter returns error rather than KErrNotFound |
|
261 LOG1(_L("CPanCoexistenceConnectionController::WriteStatus Set Property with error: %d"), err); |
|
262 __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertySetFailed)); |
|
263 } |
|
264 } |
|
265 } |
|
266 |
|
267 void CPanCoexistenceConnectionController::SubscribeToProperty() |
|
268 { |
|
269 LOG_FUNC |
|
270 iProperty.Subscribe(iStatus); |
|
271 SetActive(); |
|
272 } |
|
273 |
|
274 void CPanCoexistenceConnectionController::DoCancel() |
|
275 { |
|
276 LOG_FUNC |
|
277 iProperty.Cancel(); |
|
278 } |
|
279 |
|
280 void CPanCoexistenceConnectionController::RunL() |
|
281 { |
|
282 LOG_FUNC |
|
283 |
|
284 // Do not check the iStatus, since the ReadStatus() will redefine the P&S key if the key |
|
285 // has been deleted by mistakes |
|
286 |
|
287 //Read the property |
|
288 TIPBearerCoexistenceStatus value = ReadStatus(); |
|
289 |
|
290 switch(value) |
|
291 { |
|
292 case ENoneIsActive: |
|
293 if (!iLocallyInitiatedTransition) |
|
294 { |
|
295 // BT PAN cannot be active at this point, since the P&S key is ENoneIsActive |
|
296 __ASSERT_DEBUG(!iActivePanConnectionExists, PanAgentPanic(EPropertyIsNoneIsActiveWhenBTPanIsActive)); |
|
297 |
|
298 // Notify Agent P&S Key has been updated |
|
299 iPanCoexistenceConnectionObserver.MpccoPanCoexistenceConnectionUpdated(ENoneIsActive); |
|
300 } |
|
301 break; |
|
302 |
|
303 case ERndisIsActive: |
|
304 // BT PAN cannot be active at this point |
|
305 __ASSERT_DEBUG(!iActivePanConnectionExists, PanAgentPanic(ERndisIsActiveWhenBTPanTriesToBeActive)); |
|
306 __ASSERT_DEBUG(!iLocallyInitiatedTransition, PanAgentPanic(EBTPanInitiateDirectTransitionToRndis)); |
|
307 |
|
308 //from non service to Rndis |
|
309 //Notify Agent P&S Key has been updated |
|
310 iPanCoexistenceConnectionObserver.MpccoPanCoexistenceConnectionUpdated(ERndisIsActive); |
|
311 break; |
|
312 |
|
313 case EBTPanIsActive: |
|
314 //Setting the P&S key to EBTPanIsActive when BT PAN is not active or BT PAN is already active |
|
315 __ASSERT_DEBUG(iActivePanConnectionExists && iLocallyInitiatedTransition, PanAgentPanic(EImproperSituationToSetPropertyToBTPanIsActive)); |
|
316 break; |
|
317 |
|
318 default: |
|
319 __ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty)); |
|
320 break; |
|
321 } |
|
322 |
|
323 iLocallyInitiatedTransition = EFalse; |
|
324 |
|
325 //Resubscribe to the property |
|
326 SubscribeToProperty(); |
|
327 } |
|
328 |