|
1 /* |
|
2 * Copyright (c) 1997-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: |
|
15 * Implements a Symbian OS server that exposes the RUsb API |
|
16 * |
|
17 */ |
|
18 |
|
19 /** |
|
20 @file |
|
21 */ |
|
22 |
|
23 #include <e32svr.h> |
|
24 #include "UsbSettings.h" |
|
25 #include "CUsbServer.h" |
|
26 #include "CUsbSession.h" |
|
27 #include "CUsbDevice.h" |
|
28 |
|
29 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
30 #include "CUsbOtg.h" |
|
31 #include "cusbhost.h" |
|
32 #include <e32property.h> //Publish & Subscribe header |
|
33 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
34 |
|
35 #include <usb/usblogger.h> |
|
36 #include "UsbmanServerSecurityPolicy.h" |
|
37 #include <usb/usblogger.h> |
|
38 |
|
39 #ifdef __FLOG_ACTIVE |
|
40 _LIT8(KLogComponent, "USBSVR"); |
|
41 #endif |
|
42 |
|
43 /** |
|
44 * The CUsbServer::NewL method |
|
45 * |
|
46 * Constructs a Usb Server |
|
47 * |
|
48 * @internalComponent |
|
49 * |
|
50 * @return A new Usb Server object |
|
51 */ |
|
52 CUsbServer* CUsbServer::NewLC() |
|
53 { |
|
54 LOG_STATIC_FUNC_ENTRY |
|
55 |
|
56 CUsbServer* self = new(ELeave) CUsbServer; |
|
57 CleanupStack::PushL(self); |
|
58 self->StartL(KUsbServerName); |
|
59 self->ConstructL(); |
|
60 return self; |
|
61 } |
|
62 |
|
63 |
|
64 /** |
|
65 * The CUsbServer::~CUsbServer method |
|
66 * |
|
67 * Destructor |
|
68 * |
|
69 * @internalComponent |
|
70 */ |
|
71 CUsbServer::~CUsbServer() |
|
72 { |
|
73 LOG_FUNC |
|
74 |
|
75 delete iShutdownTimer; |
|
76 delete iUsbDevice; |
|
77 |
|
78 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
79 delete iUsbHost; |
|
80 |
|
81 #ifndef __OVER_DUMMYUSBDI__ |
|
82 // Check that this is A-Device |
|
83 LOGTEXT(_L8("Checking Id-Pin state...")); |
|
84 TInt value = 0; |
|
85 TInt err = RProperty::Get(KUidUsbManCategory, KUsbOtgIdPinPresentProperty,value); |
|
86 if (err == 0 && value == 1) |
|
87 { |
|
88 // Ensure VBus is dropped when Usb server exits |
|
89 LOGTEXT(_L8("Checking VBus state...")); |
|
90 err = RProperty::Get(KUidUsbManCategory, KUsbOtgVBusPoweredProperty,value); |
|
91 if ( err == KErrNone && value != 0 ) |
|
92 { |
|
93 if ( iUsbOtg ) |
|
94 { |
|
95 err = iUsbOtg->BusDrop(); |
|
96 LOGTEXT2(_L8("BusDrop() returned err = %d"),err); |
|
97 LOGTEXT(_L8("USBMAN will wait until VBus is actually dropped")); |
|
98 // Wait 1 second for Hub driver to perform VBus drop |
|
99 RTimer timer; |
|
100 err = timer.CreateLocal(); |
|
101 if ( err == KErrNone ) |
|
102 { |
|
103 TRequestStatus tstatus; |
|
104 timer.After(tstatus, 1000000); |
|
105 User::WaitForRequest(tstatus); |
|
106 timer.Close(); |
|
107 } |
|
108 else |
|
109 { |
|
110 LOGTEXT2(_L8("Failed to create local timer: err = %d"),err); |
|
111 } |
|
112 } |
|
113 else |
|
114 { |
|
115 LOGTEXT(_L8("Unexpected: OTG object is NULL")); |
|
116 } |
|
117 } |
|
118 else |
|
119 { |
|
120 LOGTEXT3(_L8("VBus is already dropped or an error occured: err = %d, value =%d"),err,value); |
|
121 } |
|
122 } |
|
123 else |
|
124 { |
|
125 LOGTEXT3(_L8("No Id-Pin is found or an error occured: err = %d, value = %d"), err, value); |
|
126 } |
|
127 |
|
128 delete iUsbOtg; |
|
129 #endif |
|
130 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
131 |
|
132 #ifdef __FLOG_ACTIVE |
|
133 CUsbLog::Close(); |
|
134 #endif |
|
135 } |
|
136 |
|
137 |
|
138 /** |
|
139 * The CUsbServer::CUsbServer method |
|
140 * |
|
141 * Constructor |
|
142 * |
|
143 * @internalComponent |
|
144 */ |
|
145 CUsbServer::CUsbServer() |
|
146 : CPolicyServer(EPriorityHigh,KUsbmanServerPolicy) |
|
147 { |
|
148 } |
|
149 |
|
150 /** |
|
151 * The CUsbServer::ConstructL method |
|
152 * |
|
153 * 2nd Phase Construction |
|
154 * |
|
155 * @internalComponent |
|
156 */ |
|
157 void CUsbServer::ConstructL() |
|
158 { |
|
159 #ifdef __FLOG_ACTIVE |
|
160 // Set the logger up so that everything in this thread that logs using it |
|
161 // will do so 'connectedly' (i.e. quickly). If this fails, we don't care- |
|
162 // logging will still work, just 'statically' (i.e. slowly). |
|
163 static_cast<void>(CUsbLog::Connect()); |
|
164 #endif |
|
165 |
|
166 iShutdownTimer = new(ELeave) CShutdownTimer; |
|
167 iShutdownTimer->ConstructL(); |
|
168 |
|
169 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
170 #ifndef __OVER_DUMMYUSBDI__ |
|
171 iUsbOtg = CUsbOtg::NewL(); |
|
172 iUsbOtg->StartL(); |
|
173 #endif |
|
174 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
175 |
|
176 iUsbDevice = CUsbDevice::NewL(*this); |
|
177 LOGTEXT(_L8("About to load USB classes")); |
|
178 iUsbDevice->EnumerateClassControllersL(); |
|
179 |
|
180 #ifndef USE_DUMMY_CLASS_CONTROLLER |
|
181 iUsbDevice->ReadPersonalitiesL(); |
|
182 if (iUsbDevice->isPersonalityCfged()) |
|
183 { |
|
184 #ifndef __OVER_DUMMYUSBDI__ |
|
185 iUsbDevice->ValidatePersonalitiesL(); |
|
186 #endif |
|
187 iUsbDevice->SetDefaultPersonalityL(); |
|
188 } |
|
189 else |
|
190 { |
|
191 LOGTEXT(_L8("Personalities unconfigured, so using fallback CCs")); |
|
192 iUsbDevice->LoadFallbackClassControllersL(); |
|
193 } |
|
194 #else // USE_DUMMY_CLASS_CONTROLLER |
|
195 LOGTEXT(_L8("Using Dummy Class Controller, so using fallback CCs")); |
|
196 iUsbDevice->LoadFallbackClassControllersL(); |
|
197 #endif // USE_DUMMY_CLASS_CONTROLLER |
|
198 |
|
199 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
200 iUsbHost = CUsbHost::NewL(); |
|
201 //moved to CUsbSession:StartDeviceL() and similar: iUsbHost->StartL(); |
|
202 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV |
|
203 |
|
204 LOGTEXT(_L8("CUsbServer constructed")); |
|
205 } |
|
206 |
|
207 |
|
208 /** |
|
209 * The CUsbServer::NewSessionL method |
|
210 * |
|
211 * Create a new client on this server |
|
212 * |
|
213 * @internalComponent |
|
214 * @param &aVersion Vesion of client |
|
215 * @param &aMessage Client's IPC message |
|
216 * |
|
217 * @return A new USB session to be used for the client |
|
218 */ |
|
219 CSession2* CUsbServer::NewSessionL(const TVersion &aVersion, const RMessage2& aMessage) const |
|
220 { |
|
221 LOG_LINE |
|
222 LOG_FUNC |
|
223 |
|
224 (void)aMessage;//Remove compiler warning |
|
225 |
|
226 TVersion v(KUsbSrvMajorVersionNumber,KUsbSrvMinorVersionNumber,KUsbSrvBuildVersionNumber); |
|
227 |
|
228 LOGTEXT(_L8("CUsbServer::NewSessionL - creating new session...")); |
|
229 if (!User::QueryVersionSupported(v, aVersion)) |
|
230 { |
|
231 LEAVEL(KErrNotSupported); |
|
232 } |
|
233 |
|
234 CUsbServer* ncThis = const_cast<CUsbServer*>(this); |
|
235 |
|
236 CUsbSession* sess = CUsbSession::NewL(ncThis); |
|
237 |
|
238 return sess; |
|
239 } |
|
240 |
|
241 |
|
242 /** |
|
243 * Inform the client there has been an error. |
|
244 * |
|
245 * @param aError The error that has occurred |
|
246 */ |
|
247 void CUsbServer::Error(TInt aError) |
|
248 { |
|
249 LOGTEXT2(_L8("CUsbServer::Error [aError=%d]"), aError); |
|
250 |
|
251 Message().Complete(aError); |
|
252 ReStart(); |
|
253 } |
|
254 |
|
255 /** |
|
256 * Increment the open session count (iSessionCount) by one. |
|
257 * |
|
258 * @post the number of open sessions is incremented by one |
|
259 */ |
|
260 void CUsbServer::IncrementSessionCount() |
|
261 { |
|
262 LOGTEXT2(_L8(">CUsbServer::IncrementSessionCount %d"), iSessionCount); |
|
263 __ASSERT_DEBUG(iSessionCount >= 0, _USB_PANIC(KUsbSvrPncCat, EICSInvalidCount)); |
|
264 |
|
265 ++iSessionCount; |
|
266 iShutdownTimer->Cancel(); |
|
267 |
|
268 LOGTEXT(_L8("<CUsbServer::IncrementSessionCount")); |
|
269 } |
|
270 |
|
271 /** |
|
272 * Decrement the open session count (iSessionCount) by one. |
|
273 * |
|
274 * @post the number of open sessions is decremented by one |
|
275 */ |
|
276 void CUsbServer::DecrementSessionCount() |
|
277 { |
|
278 LOGTEXT3(_L8("CUsbServer::DecrementSessionCount %d, %d"), iSessionCount, Device().ServiceState()); |
|
279 __ASSERT_DEBUG(iSessionCount > 0, _USB_PANIC(KUsbSvrPncCat, EDCSInvalidCount)); |
|
280 |
|
281 --iSessionCount; |
|
282 |
|
283 if (iSessionCount == 0 && Device().ServiceState() == EUsbServiceIdle) |
|
284 { |
|
285 iShutdownTimer->After(KShutdownDelay); |
|
286 } |
|
287 } |
|
288 |
|
289 /** |
|
290 * If there are no sessions then launch the shutdown timer. This function |
|
291 * is provided for the case where the sole session stops the classes but dies |
|
292 * before they are completely stopped. The server must then be shut down |
|
293 * from CUsbDevice::SetServiceState(). |
|
294 * |
|
295 * @pre the services have been stopped. |
|
296 * @see CUsbDevice::SetServiceStateIdle |
|
297 */ |
|
298 void CUsbServer::LaunchShutdownTimerIfNoSessions() |
|
299 { |
|
300 LOGTEXT(_L8("CUsbServer::LaunchShutdownTimerIfNoSessions")); |
|
301 __ASSERT_DEBUG(Device().ServiceState() == EUsbServiceIdle, _USB_PANIC(KUsbSvrPncCat, ELSTNSNotIdle)); |
|
302 |
|
303 if (iSessionCount == 0) |
|
304 iShutdownTimer->After(KShutdownDelay); |
|
305 } |
|
306 |
|
307 /** |
|
308 * Initialize this shutdown timer as a normal-priority |
|
309 * (EPriorityStandard) active object. |
|
310 */ |
|
311 CUsbServer::CShutdownTimer::CShutdownTimer() |
|
312 : CTimer(EPriorityStandard) |
|
313 { |
|
314 CActiveScheduler::Add(this); |
|
315 } |
|
316 |
|
317 /** |
|
318 * Forwarding function call's CTimer's ConstructL() to initialize the RTimer. |
|
319 */ |
|
320 void CUsbServer::CShutdownTimer::ConstructL() |
|
321 { |
|
322 CTimer::ConstructL(); |
|
323 } |
|
324 |
|
325 /** |
|
326 * Server shutdown callback. This stops the active scheduler, |
|
327 * and so closes down the server. |
|
328 */ |
|
329 void CUsbServer::CShutdownTimer::RunL() |
|
330 { |
|
331 CActiveScheduler::Stop(); |
|
332 } |
|
333 |