|
1 /* |
|
2 * Copyright (c) 2008 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 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <bluetooth/hci/hcierrors.h> |
|
20 |
|
21 #include "bluetoothconsts.h" |
|
22 #include "bluetoothservicesearcher.h" |
|
23 #include "discoveryagent.h" |
|
24 |
|
25 namespace java |
|
26 { |
|
27 namespace bluetooth |
|
28 { |
|
29 |
|
30 #define GET_VALID_HCI_ERR_CODE(err_no) (((err_no) < KHCIErrorBase) ? \ |
|
31 (KHCIErrorBase - (err_no)) : \ |
|
32 (err_no)) |
|
33 |
|
34 BluetoothServiceSearcher* BluetoothServiceSearcher::New( |
|
35 DiscoveryAgent *aDiscoveryAgent, BluetoothFunctionServer* aServer) |
|
36 { |
|
37 JELOG2(EJavaBluetooth); |
|
38 BluetoothServiceSearcher* searcher = new BluetoothServiceSearcher(); |
|
39 searcher->Construct(aDiscoveryAgent, aServer); |
|
40 return searcher; |
|
41 } |
|
42 |
|
43 BluetoothServiceSearcher::BluetoothServiceSearcher() |
|
44 { |
|
45 } |
|
46 |
|
47 void BluetoothServiceSearcher::Construct(DiscoveryAgent *aDiscoveryAgent, |
|
48 BluetoothFunctionServer* aServer) |
|
49 { |
|
50 JELOG2(EJavaBluetooth); |
|
51 mDiscoveryAgent = aDiscoveryAgent; |
|
52 mServer = aServer; |
|
53 mSDPAgent = NULL; |
|
54 mSpat = NULL; |
|
55 mAttributeList = NULL; |
|
56 mSrPopulator = NULL; |
|
57 mFoundServiceRecord = false; |
|
58 mIsPopulateRecordMode = false; |
|
59 |
|
60 mJni = mServer->getValidJniEnv(); |
|
61 mPeer = mServer->getPeer(); |
|
62 |
|
63 jclass peerClass = mJni->GetObjectClass(mPeer); |
|
64 mCreateServiceRecordMethod |
|
65 = mJni->GetMethodID(peerClass, "createServiceRecord", |
|
66 "(J)Lcom/intel/bluetooth/ServiceRecordImpl;"); |
|
67 |
|
68 mServiceRecordImplClass = mJni->FindClass( |
|
69 "com/intel/bluetooth/ServiceRecordImpl"); |
|
70 |
|
71 } |
|
72 |
|
73 BluetoothServiceSearcher::~BluetoothServiceSearcher() |
|
74 { |
|
75 JELOG2(EJavaBluetooth); |
|
76 Cleanup(); |
|
77 } |
|
78 |
|
79 void BluetoothServiceSearcher::SearchServicesL(TInt64 aRemoteAddress, |
|
80 TPtrC8 aUuidsDes, TPtrC16 aAttrIdsDes) |
|
81 { |
|
82 JELOG2(EJavaBluetooth); |
|
83 LOG1(EJavaBluetooth, EInfo, |
|
84 "+ BluetoothServiceSearcher:: SearchServices:%X", |
|
85 (long) aRemoteAddress); |
|
86 |
|
87 mIsPopulateRecordMode = false; |
|
88 |
|
89 TBTDevAddr devAddr(aRemoteAddress); |
|
90 |
|
91 FillSearchPatternL(aUuidsDes); |
|
92 |
|
93 FillAttributeListL(aAttrIdsDes); |
|
94 |
|
95 LOG( |
|
96 EJavaBluetooth, |
|
97 EInfo, |
|
98 " BluetoothServiceSearcher::SearchServicesOnDeviceL: Clearing SDPAgent if any..."); |
|
99 // Init new service discovery agent |
|
100 if (mSDPAgent) |
|
101 { |
|
102 delete mSDPAgent; |
|
103 mSDPAgent = NULL; |
|
104 } |
|
105 mSDPAgent = CSdpAgent::NewL(*this, devAddr); |
|
106 |
|
107 mSDPAgent->SetRecordFilterL(*mSpat); |
|
108 |
|
109 mSDPAgent->NextRecordRequestL(); |
|
110 |
|
111 } |
|
112 |
|
113 void BluetoothServiceSearcher::cancelServiceSearch() |
|
114 { |
|
115 JELOG2(EJavaBluetooth); |
|
116 DiscoveryAgent* tempDiscoveryAgent = mDiscoveryAgent; |
|
117 Cleanup(); |
|
118 if (NULL == tempDiscoveryAgent) |
|
119 return; |
|
120 if (!mIsPopulateRecordMode) |
|
121 { |
|
122 tempDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_TERMINATED); |
|
123 } |
|
124 else |
|
125 { |
|
126 tempDiscoveryAgent->PopulateRecordCompleted(SERVICE_SEARCH_TERMINATED); |
|
127 } |
|
128 } |
|
129 |
|
130 void BluetoothServiceSearcher::Cleanup() |
|
131 { |
|
132 JELOG2(EJavaBluetooth); |
|
133 if (mSDPAgent) |
|
134 { |
|
135 delete mSDPAgent; |
|
136 mSDPAgent = NULL; |
|
137 } |
|
138 if (mSpat) |
|
139 { |
|
140 mSpat->Reset(); |
|
141 delete mSpat; |
|
142 mSpat = NULL; |
|
143 } |
|
144 if (mAttributeList) |
|
145 { |
|
146 delete mAttributeList; |
|
147 mAttributeList = NULL; |
|
148 } |
|
149 if (mSrPopulator) |
|
150 { |
|
151 delete mSrPopulator; |
|
152 mSrPopulator = NULL; |
|
153 } |
|
154 |
|
155 mDiscoveryAgent = NULL; |
|
156 } |
|
157 |
|
158 void BluetoothServiceSearcher::NextRecordRequestComplete(TInt aError, |
|
159 TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/) |
|
160 { |
|
161 JELOG2(EJavaBluetooth); |
|
162 LOG1( |
|
163 EJavaBluetooth, |
|
164 EInfo, |
|
165 " BluetoothServiceSearcher::NextRecordRequestComplete aError=%d", |
|
166 aError); |
|
167 |
|
168 if (KErrEof == aError && !mFoundServiceRecord) |
|
169 { |
|
170 LOG( |
|
171 EJavaBluetooth, |
|
172 EInfo, |
|
173 " BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_NO_RECORDS"); |
|
174 mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_NO_RECORDS); |
|
175 } |
|
176 else if (KErrNone == aError) |
|
177 { |
|
178 TInt64 servRecHandle = MAKE_TINT64(0, aHandle); |
|
179 mServiceRecordImpl = (*mJni).CallObjectMethod(mPeer, |
|
180 mCreateServiceRecordMethod, servRecHandle); |
|
181 if (NULL == mServiceRecordImpl) |
|
182 { |
|
183 LOG(EJavaBluetooth, EInfo, |
|
184 " BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_ERROR"); |
|
185 mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_ERROR); |
|
186 } |
|
187 else |
|
188 { |
|
189 LOG(EJavaBluetooth, EInfo, |
|
190 " BluetoothServiceSearcher::NextRecordRequestComplete Populating record"); |
|
191 delete mSrPopulator; |
|
192 mSrPopulator = BTServiceRecordPopulator::New(mJni, |
|
193 mServiceRecordImpl); |
|
194 TRAPD(attrRequestErr, mSDPAgent->AttributeRequestL(mSrPopulator, |
|
195 aHandle, *mAttributeList)); |
|
196 if (KErrNone != attrRequestErr) |
|
197 { |
|
198 delete mSrPopulator; |
|
199 mSrPopulator = NULL; |
|
200 mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_ERROR); |
|
201 } |
|
202 } |
|
203 } |
|
204 else if (EPageTimedOut == GET_VALID_HCI_ERR_CODE(aError)) |
|
205 { |
|
206 LOG( |
|
207 EJavaBluetooth, |
|
208 EInfo, |
|
209 " BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_DEVICE_NOT_REACHABLE"); |
|
210 mDiscoveryAgent->ServiceSearchCompleted( |
|
211 SERVICE_SEARCH_DEVICE_NOT_REACHABLE); |
|
212 } |
|
213 else |
|
214 { |
|
215 LOG1( |
|
216 EJavaBluetooth, |
|
217 EInfo, |
|
218 " BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_COMPLETED %d", |
|
219 aError); |
|
220 mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_COMPLETED); |
|
221 } |
|
222 } |
|
223 |
|
224 void BluetoothServiceSearcher::PopulateServiceRecordsL(TInt64 aRemoteAddress, |
|
225 long aHandle, TPtrC16 aAttrIdsDes, jobject aServiceRecordImpl) |
|
226 { |
|
227 JELOG2(EJavaBluetooth); |
|
228 |
|
229 mIsPopulateRecordMode = true; |
|
230 |
|
231 TBTDevAddr devAddr(aRemoteAddress); |
|
232 |
|
233 FillAttributeListL(aAttrIdsDes); |
|
234 |
|
235 LOG( |
|
236 EJavaBluetooth, |
|
237 EInfo, |
|
238 " BluetoothServiceSearcher::PopulateServiceRecords: Clearing SDPAgent if any..."); |
|
239 |
|
240 if (mSDPAgent) |
|
241 { |
|
242 mSDPAgent->Cancel(); |
|
243 delete mSDPAgent; |
|
244 mSDPAgent = NULL; |
|
245 } |
|
246 mSDPAgent = CSdpAgent::NewL(*this, devAddr); |
|
247 |
|
248 mServiceRecordImpl = aServiceRecordImpl; |
|
249 |
|
250 delete mSrPopulator; |
|
251 mSrPopulator = BTServiceRecordPopulator::New(mJni, mServiceRecordImpl); |
|
252 |
|
253 mSDPAgent->AttributeRequestL(mSrPopulator, aHandle, *mAttributeList); |
|
254 } |
|
255 |
|
256 void BluetoothServiceSearcher::AttributeRequestResult( |
|
257 TSdpServRecordHandle /*aHandle*/, TSdpAttributeID /*aAttrID*/, |
|
258 CSdpAttrValue* /*aAttrValue*/) |
|
259 { |
|
260 // No implementation required... |
|
261 } |
|
262 |
|
263 void BluetoothServiceSearcher::AttributeRequestComplete( |
|
264 TSdpServRecordHandle /*aHandle*/, TInt aError) |
|
265 { |
|
266 JELOG2(EJavaBluetooth); |
|
267 LOG1(EJavaBluetooth, EInfo, |
|
268 " BluetoothServiceSearcher::AttributeRequestComplete aError=%d", |
|
269 aError); |
|
270 |
|
271 int status = 0; |
|
272 bool attributeFound = mSrPopulator->isAttributesFound(); |
|
273 |
|
274 delete mSrPopulator; |
|
275 mSrPopulator = NULL; |
|
276 |
|
277 if (KErrNone == aError && !mIsPopulateRecordMode) |
|
278 { |
|
279 mFoundServiceRecord = true; |
|
280 LOG( |
|
281 EJavaBluetooth, |
|
282 EInfo, |
|
283 " BluetoothServiceSearcher::AttributeRequestComplete Callback serviceDiscoveredCallback"); |
|
284 jclass peerClass = mJni->GetObjectClass(mPeer); |
|
285 jmethodID serviceDiscoveredMethod = mJni->GetMethodID(peerClass, |
|
286 "serviceDiscoveredCallback", |
|
287 "(Lcom/intel/bluetooth/ServiceRecordImpl;)V"); |
|
288 (*mJni).CallVoidMethod(mPeer, serviceDiscoveredMethod, |
|
289 mServiceRecordImpl); |
|
290 |
|
291 LOG( |
|
292 EJavaBluetooth, |
|
293 EInfo, |
|
294 " BluetoothServiceSearcher::AttributeRequestComplete. Trying for the next record if any"); |
|
295 |
|
296 // In case of any leave, then this will terminates the search for the next record. |
|
297 TRAP_IGNORE(mSDPAgent->NextRecordRequestL()); |
|
298 } |
|
299 else |
|
300 { |
|
301 if (KErrNone == aError) |
|
302 { |
|
303 mFoundServiceRecord = true; |
|
304 status = SERVICE_SEARCH_COMPLETED; |
|
305 } |
|
306 else if (EPageTimedOut == GET_VALID_HCI_ERR_CODE(aError)) |
|
307 { |
|
308 LOG( |
|
309 EJavaBluetooth, |
|
310 EInfo, |
|
311 " BluetoothServiceSearcher::AttributeRequestComplete SERVICE_SEARCH_DEVICE_NOT_REACHABLE"); |
|
312 status = SERVICE_SEARCH_DEVICE_NOT_REACHABLE; |
|
313 } |
|
314 else |
|
315 { |
|
316 LOG(EJavaBluetooth, EInfo, |
|
317 " BluetoothServiceSearcher::AttributeRequestComplete SERVICE_SEARCH_ERROR"); |
|
318 status = SERVICE_SEARCH_ERROR; |
|
319 } |
|
320 |
|
321 if (!mIsPopulateRecordMode) |
|
322 { |
|
323 mDiscoveryAgent->ServiceSearchCompleted(status); |
|
324 } |
|
325 else |
|
326 { |
|
327 if (false == attributeFound) |
|
328 status = SERVICE_SEARCH_NO_RECORDS; |
|
329 mDiscoveryAgent->PopulateRecordCompleted(status); |
|
330 } |
|
331 } |
|
332 } |
|
333 |
|
334 void BluetoothServiceSearcher::BluetoothServiceSearcher::FillSearchPatternL( |
|
335 TDesC8& uuidsBytes) |
|
336 { |
|
337 JELOG2(EJavaBluetooth); |
|
338 |
|
339 const TInt numBytes = uuidsBytes.Length(); |
|
340 const TInt numberOfUUIDs = numBytes / KSdpUUIDMaxLength; |
|
341 |
|
342 TInt uuidsConverted = 0; |
|
343 TInt startByte = 0; |
|
344 |
|
345 if (mSpat) |
|
346 { |
|
347 mSpat->Reset(); |
|
348 delete mSpat; |
|
349 mSpat = NULL; |
|
350 } |
|
351 mSpat = CSdpSearchPattern::NewL(); |
|
352 CleanupStack::PushL(mSpat); |
|
353 |
|
354 while (uuidsConverted < numberOfUUIDs) |
|
355 { |
|
356 TUUID uuid; |
|
357 uuid.SetL(uuidsBytes.Mid(startByte, KSdpUUIDMaxLength)); |
|
358 |
|
359 mSpat->AddL(uuid); |
|
360 startByte += KSdpUUIDMaxLength; |
|
361 uuidsConverted++; |
|
362 } |
|
363 CleanupStack::Pop(mSpat); |
|
364 } |
|
365 |
|
366 void BluetoothServiceSearcher::BluetoothServiceSearcher::FillAttributeListL( |
|
367 TDesC16& attrIds) |
|
368 { |
|
369 JELOG2(EJavaBluetooth); |
|
370 delete mAttributeList; |
|
371 mAttributeList = NULL; |
|
372 mAttributeList = CSdpAttrIdMatchList::NewL(); |
|
373 CleanupStack::PushL(mAttributeList); |
|
374 |
|
375 TInt numElements = attrIds.Length(); |
|
376 |
|
377 for (TInt attrIndex = 0; attrIndex < numElements; attrIndex += 2) |
|
378 { |
|
379 const TUint16* attrIdStartPtr = (attrIds.Mid(attrIndex, 2)).Ptr(); |
|
380 const TInt* attrId = reinterpret_cast<const TInt*>(attrIdStartPtr); |
|
381 const TUint16 attrId16 = static_cast<TUint16>(*attrId); |
|
382 TAttrRange attrRange(static_cast<TSdpAttributeID>(attrId16)); |
|
383 |
|
384 mAttributeList->AddL(attrRange); |
|
385 } |
|
386 CleanupStack::Pop(mAttributeList); |
|
387 |
|
388 } |
|
389 |
|
390 } //end namespace bluetooth |
|
391 } //end namespace java |