|
1 // Copyright (c) 2007-2010 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 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #include "fdchctloriginal.h" |
|
22 |
|
23 #include <d32usbdescriptors.h> |
|
24 #include <usbhost/internal/fdcpluginobserver.h> |
|
25 #include <usbhosterrors.h> |
|
26 #include <bluetooth/logger.h> |
|
27 |
|
28 #include "fdchctloriginalserver.h" |
|
29 |
|
30 #include <bluetooth/logger.h> |
|
31 |
|
32 #ifdef __FLOG_ACTIVE |
|
33 _LIT8(KLogComponent, "fdchctloriginal"); |
|
34 #endif |
|
35 |
|
36 |
|
37 CFdcHctlOriginal* CFdcHctlOriginal::NewL(MFdcPluginObserver& aObserver) |
|
38 { |
|
39 LOG_STATIC_FUNC |
|
40 CFdcHctlOriginal* self = new(ELeave) CFdcHctlOriginal(aObserver); |
|
41 CleanupStack::PushL(self); |
|
42 self->ConstructL(); |
|
43 CleanupStack::Pop(); |
|
44 return self; |
|
45 } |
|
46 |
|
47 CFdcHctlOriginal::CFdcHctlOriginal(MFdcPluginObserver& aObserver) |
|
48 : CFdcPlugin(aObserver) |
|
49 { |
|
50 LOG_FUNC |
|
51 } |
|
52 |
|
53 CFdcHctlOriginal::~CFdcHctlOriginal() |
|
54 { |
|
55 LOG_FUNC |
|
56 iHctlSession.Close(); |
|
57 delete iServer; |
|
58 } |
|
59 |
|
60 void CFdcHctlOriginal::ConstructL() |
|
61 { |
|
62 LOG_FUNC |
|
63 iServer = CFdcHctlOriginalServer::NewL(*this); |
|
64 } |
|
65 |
|
66 TAny* CFdcHctlOriginal::GetInterface(TUid aUid) |
|
67 { |
|
68 LOG_FUNC |
|
69 LOG1(_L8("\taUid = 0x%08x"), aUid); |
|
70 |
|
71 TAny* ret = NULL; |
|
72 if(aUid == TUid::Uid(KFdcInterfaceV1)) |
|
73 { |
|
74 ret = reinterpret_cast<TAny*>(static_cast<MFdcInterfaceV1*>(this)); |
|
75 } |
|
76 |
|
77 LOG1(_L8("\tret = [0x%08x]"), ret); |
|
78 return ret; |
|
79 } |
|
80 |
|
81 TInt CFdcHctlOriginal::Mfi1NewFunction(TUint aDeviceId, |
|
82 const TArray<TUint>& aInterfaces, |
|
83 const TUsbDeviceDescriptor& aDeviceDescriptor, |
|
84 const TUsbConfigurationDescriptor& aConfigurationDescriptor) |
|
85 { |
|
86 LOG_FUNC |
|
87 |
|
88 // Normally an FDC is required to claim it's interfaces first. In this |
|
89 // case we need to parse the descriptor tree to determine if the device |
|
90 // firmware update interface is present. (We don't do firmware updates but |
|
91 // we claim it until to provide successful device attachments. If a |
|
92 // firmware update FDC is provided this should be removed.) |
|
93 #ifdef SYMBIAN_FDC_HCTL_ORIGINAL_ACCEPT_FIRMWARE_UPDATE |
|
94 TBool firmwareIntFound = EFalse; |
|
95 TUint8 firmwareIntNum = 0xff; |
|
96 |
|
97 TUint8 KDfuInterfaceClass = 0xfe; |
|
98 TUint8 KDfuInterfaceSubClass = 0x01; |
|
99 |
|
100 // Drop down a level from the configuration descriptor. |
|
101 TUsbGenericDescriptor* descriptor = aConfigurationDescriptor.iFirstChild; |
|
102 // Search across the interface tier (note doesn't handle DFU in IAD). |
|
103 while(descriptor) |
|
104 { |
|
105 TUsbInterfaceDescriptor* interface; |
|
106 if (interface = TUsbInterfaceDescriptor::Cast(descriptor), interface) |
|
107 { |
|
108 if( interface->InterfaceClass() == KDfuInterfaceClass && |
|
109 interface->InterfaceSubClass() == KDfuInterfaceSubClass) |
|
110 { |
|
111 firmwareIntNum = interface->InterfaceNumber(); |
|
112 firmwareIntFound = ETrue; |
|
113 break; |
|
114 } |
|
115 } |
|
116 descriptor = descriptor->iNextPeer; |
|
117 } |
|
118 #endif // SYMBIAN_FDC_HCTL_ORIGINAL_ACCEPT_FIRMWARE_UPDATE |
|
119 |
|
120 // We claim the interfaces we are to represent, we must claim the |
|
121 // first interface given to us as FDF has already determined that |
|
122 // we are to use it. |
|
123 const TUint KNumOfHctlInterfaces = 2; |
|
124 const TUint8 KAclInterfaceNum = 0x00, KScoInterfaceNum = 0x01; |
|
125 TBool gotAcl = EFalse, gotSco = EFalse, fatalError = EFalse; |
|
126 |
|
127 for(TInt i=0; i<aInterfaces.Count(); ++i) |
|
128 { |
|
129 TUint intNum = aInterfaces[i]; |
|
130 if(intNum == KAclInterfaceNum) |
|
131 { |
|
132 fatalError = (fatalError || gotAcl); // The USB device should only report one ACL interface |
|
133 iAclToken = Observer().TokenForInterface(intNum); |
|
134 gotAcl = ETrue; |
|
135 } |
|
136 else if(intNum == KScoInterfaceNum) |
|
137 { |
|
138 fatalError = (fatalError || gotSco); // The USB device should only report one ACL interface |
|
139 iScoToken = Observer().TokenForInterface(intNum); |
|
140 gotSco = ETrue; |
|
141 } |
|
142 else if(i == 0) |
|
143 { |
|
144 // We always need to claim the first interface, this should have |
|
145 // been claimed already, but if we have a funny device then this |
|
146 // might not be the case. We will need to error. |
|
147 TUint32 unknownToken = Observer().TokenForInterface(intNum); |
|
148 return KErrCorrupt; |
|
149 } |
|
150 #ifdef SYMBIAN_FDC_HCTL_ORIGINAL_ACCEPT_FIRMWARE_UPDATE |
|
151 else if(firmwareIntFound && intNum == firmwareIntNum) |
|
152 { |
|
153 TUint32 dfuToken = Observer().TokenForInterface(intNum); |
|
154 } |
|
155 #endif // SYMBIAN_FDC_HCTL_ORIGINAL_ACCEPT_FIRMWARE_UPDATE |
|
156 } |
|
157 // At this point we will have claimed to the interface mandated by FDF and |
|
158 // so we are at liberty to return an error. |
|
159 |
|
160 // firstly, check to see if a fatal error occured. |
|
161 if(fatalError) |
|
162 { |
|
163 LOG(_L8("\tFatal error when retrieving interfaces for driver instance...")); |
|
164 return KErrGeneral; |
|
165 } |
|
166 |
|
167 // Now we perform some validation that the function is what we expect. |
|
168 // There should be two interfaces as part of the function. One is |
|
169 // the standard data and control planes. The other for the sync- |
|
170 // chronous connections. |
|
171 if(aConfigurationDescriptor.NumInterfaces() < KNumOfHctlInterfaces) |
|
172 { |
|
173 LOG(_L8("\tInsufficent interfaces in USB config. descriptor...")); |
|
174 return KErrUsbBadDescriptor; |
|
175 } |
|
176 if(aInterfaces.Count() < KNumOfHctlInterfaces) |
|
177 { |
|
178 LOG(_L8("\tInsufficient interfaces provided to FDC...")); |
|
179 return KErrUnderflow; |
|
180 } |
|
181 |
|
182 // Ensure that we got both interfaces, otherwise the device is malformed. |
|
183 if(!gotAcl || !gotSco) |
|
184 { |
|
185 LOG2(_L8("\tMissing Token [ACL=%d] [SCO=%d]"), gotAcl, gotSco); |
|
186 return KErrNotFound; |
|
187 } |
|
188 |
|
189 // At this point we are set-up to use the device. |
|
190 iReady = ETrue; |
|
191 |
|
192 // We try our best; the Bluetooth stack may not be running, it may not be even using |
|
193 // the USB HCTL. So we accept the tokens and try the best to set-up the HCTL. |
|
194 // If we fail now the HCTL should later inform us to try again. |
|
195 RequestConnection(); |
|
196 |
|
197 return KErrNone; |
|
198 } |
|
199 |
|
200 void CFdcHctlOriginal::Mfi1DeviceDetached(TUint aDeviceId) |
|
201 { |
|
202 LOG_FUNC |
|
203 |
|
204 iReady = EFalse; |
|
205 |
|
206 if(iHctlSession.Handle()) |
|
207 { |
|
208 // Inform of disconnection. |
|
209 iHctlSession.DeviceDetached(); |
|
210 } |
|
211 // Close Hctl Handle |
|
212 iHctlSession.Close(); |
|
213 } |
|
214 |
|
215 void CFdcHctlOriginal::RequestConnection() |
|
216 { |
|
217 LOG_FUNC |
|
218 // Trigger the attempt to connect to the USB HCTL Server. |
|
219 |
|
220 if(!iReady) |
|
221 { |
|
222 // For whatever reason, we have not got the tokens for the USB interfaces. |
|
223 LOG(_L8("\tFDC is not ready")); |
|
224 return; |
|
225 } |
|
226 |
|
227 // Note that this will error if, the bt thread or usb hctl is not running; |
|
228 // or if there is another FDC already connected to it. |
|
229 TInt err = iHctlSession.Connect(); |
|
230 if(err != KErrNone) |
|
231 { |
|
232 LOG1(_L8("\tRHCTLUsbOriginal::Connect error = %d"), err); |
|
233 return; |
|
234 } |
|
235 |
|
236 // Now inform the stack that we have a connected device. |
|
237 err = iHctlSession.DeviceAttached(iAclToken, iScoToken); |
|
238 if(err != KErrNone) |
|
239 { |
|
240 LOG1(_L8("\tRHCTLUsbOriginal::DeviceAttached error = %d"), err); |
|
241 iHctlSession.Close(); |
|
242 return; |
|
243 } |
|
244 } |
|
245 |
|
246 |
|
247 |
|
248 |