|
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 <string> |
|
20 #include <e32base.h> |
|
21 |
|
22 #include "logger.h" |
|
23 #include "fs_methodcall.h" |
|
24 #include "bluetoothconsts.h" |
|
25 #include "bluetoothdevicediscoverer.h" |
|
26 |
|
27 // Constants used to create device class |
|
28 #define SERVICE_CLASS_POS 13 |
|
29 #define MAJOR_CLASS_POS 8 |
|
30 #define MINOR_CLASS_POS 2 |
|
31 |
|
32 #define SOCKETSERVER_CONNECTED 1 |
|
33 |
|
34 namespace java |
|
35 { |
|
36 namespace bluetooth |
|
37 { |
|
38 |
|
39 _LIT(KBTLinkManagerTxt,"BTLinkManager"); |
|
40 |
|
41 BluetoothDeviceDiscoverer* BluetoothDeviceDiscoverer::NewL( |
|
42 BluetoothFunctionServer *aFunctionServer) |
|
43 { |
|
44 JELOG2(EJavaBluetooth); |
|
45 BluetoothDeviceDiscoverer *self = new BluetoothDeviceDiscoverer( |
|
46 aFunctionServer); |
|
47 CleanupStack::PushL(self); |
|
48 self->ConstructL(); |
|
49 CleanupStack::Pop(self); |
|
50 return self; |
|
51 } |
|
52 |
|
53 void BluetoothDeviceDiscoverer::ConstructL() |
|
54 { |
|
55 int result = -1; |
|
56 User::LeaveIfError(mSocketServerStatus = mSocketServer.Connect()); |
|
57 mSocketServer.ShareAuto(); |
|
58 mSocketServerStatus = SOCKETSERVER_CONNECTED; |
|
59 |
|
60 result = pthread_mutex_init(&mMutex, 0); |
|
61 if (result == 0) |
|
62 { |
|
63 result = pthread_cond_init(&mCondVar, 0); |
|
64 } |
|
65 if (0 != result) |
|
66 { |
|
67 User::Leave(result); |
|
68 } |
|
69 } |
|
70 |
|
71 BluetoothDeviceDiscoverer::BluetoothDeviceDiscoverer( |
|
72 BluetoothFunctionServer *aFunctionServer) : |
|
73 CActive(EPriorityStandard) |
|
74 { |
|
75 CActiveScheduler::Add(this); |
|
76 mFunctionServer = aFunctionServer; |
|
77 } |
|
78 |
|
79 BluetoothDeviceDiscoverer::~BluetoothDeviceDiscoverer() |
|
80 { |
|
81 JELOG2(EJavaBluetooth); |
|
82 |
|
83 mHostResolver.Close(); |
|
84 |
|
85 if (SOCKETSERVER_CONNECTED == mSocketServerStatus) |
|
86 mSocketServer.Close(); |
|
87 |
|
88 clearQueue(); |
|
89 pthread_mutex_destroy(&mMutex); |
|
90 pthread_cond_destroy(&mCondVar); |
|
91 |
|
92 |
|
93 } |
|
94 |
|
95 /** |
|
96 * Searches for the next device. |
|
97 * If found, then returns the discovered device information |
|
98 * Otherwise, in case of error or completion, returns INQUIRY_COMAPLETED |
|
99 * and in case of cancele, returnsn INQUIRY_TERMINATED |
|
100 */ |
|
101 int BluetoothDeviceDiscoverer::getNextDevice( |
|
102 DiscoveredDevice &aDiscoveredDevice) |
|
103 { |
|
104 JELOG2(EJavaBluetooth); |
|
105 |
|
106 dequeue(aDiscoveredDevice); |
|
107 return aDiscoveredDevice.mInquiryStatus; |
|
108 } |
|
109 |
|
110 /** |
|
111 * Starts the searching for the next device |
|
112 */ |
|
113 void BluetoothDeviceDiscoverer::setNext() |
|
114 { |
|
115 JELOG2(EJavaBluetooth); |
|
116 |
|
117 if (!IsActive()) |
|
118 { |
|
119 // Get next discovered device |
|
120 mHostResolver.Next(mNameEntry, iStatus); |
|
121 SetActive(); |
|
122 } |
|
123 } |
|
124 |
|
125 /** |
|
126 * Initializes the device inquiry |
|
127 */ |
|
128 void BluetoothDeviceDiscoverer::DiscoverDevicesL(int aAccessCode) |
|
129 { |
|
130 JELOG2(EJavaBluetooth); |
|
131 |
|
132 TInquirySockAddr inquirySockAddr; |
|
133 |
|
134 if (!IsActive()) |
|
135 { |
|
136 LOG(EJavaBluetooth, EInfo, |
|
137 "+ BluetoothDeviceDiscoverer::DiscoverDevicesL Finding protocol"); |
|
138 // Load protocol for discovery |
|
139 TProtocolDesc pdesc; |
|
140 User::LeaveIfError(mSocketServer.FindProtocol(KBTLinkManagerTxt(), |
|
141 pdesc)); |
|
142 |
|
143 // Initialize host resolver |
|
144 mHostResolver.Close(); |
|
145 |
|
146 User::LeaveIfError(mHostResolver.Open(mSocketServer, pdesc.iAddrFamily, |
|
147 pdesc.iProtocol)); |
|
148 |
|
149 // Start device discovery by invoking remote address lookup |
|
150 if (KGIAC == aAccessCode) |
|
151 LOG(EJavaBluetooth, EInfo, |
|
152 " BluetoothDeviceDiscoverer::DiscoverDevicesL GIAC"); |
|
153 else if (KLIAC == aAccessCode) |
|
154 LOG(EJavaBluetooth, EInfo, |
|
155 " BluetoothDeviceDiscoverer::DiscoverDevicesL LIAC"); |
|
156 else |
|
157 LOG1(EJavaBluetooth, EInfo, |
|
158 " BluetoothDeviceDiscoverer::DiscoverDevicesL Val: %X", |
|
159 aAccessCode); |
|
160 |
|
161 inquirySockAddr.SetIAC(aAccessCode); |
|
162 inquirySockAddr.SetAction(KHostResInquiry | KHostResName |
|
163 | KHostResIgnoreCache); |
|
164 |
|
165 mHostResolver.GetByAddress(inquirySockAddr, mNameEntry, iStatus); |
|
166 |
|
167 SetActive(); |
|
168 } |
|
169 else |
|
170 { |
|
171 ELOG(EJavaBluetooth, |
|
172 "- BluetoothDeviceDiscoverer::DiscoverDevicesL Leaving. Not ready!"); |
|
173 User::Leave(KErrNotReady); |
|
174 } |
|
175 } |
|
176 |
|
177 void BluetoothDeviceDiscoverer::RunL() |
|
178 { |
|
179 JELOG2(EJavaBluetooth); |
|
180 bool continueFlag = false; |
|
181 |
|
182 DiscoveredDevice *discoveredDevice = new DiscoveredDevice(); |
|
183 |
|
184 if (iStatus.Int() == KErrCancel) |
|
185 { |
|
186 RThread thread; |
|
187 int error = thread.Open(mThreadName, EOwnerProcess); |
|
188 if (error == KErrNone) |
|
189 { |
|
190 thread.RequestSignal(); |
|
191 } |
|
192 |
|
193 clearQueue(); |
|
194 discoveredDevice->mInquiryStatus = INQUIRY_TERMINATED; |
|
195 } |
|
196 else if (KErrNone == iStatus.Int()) |
|
197 { |
|
198 fillDeviceInfo(*discoveredDevice); |
|
199 continueFlag = true; |
|
200 } |
|
201 else |
|
202 { |
|
203 discoveredDevice->mInquiryStatus = INQUIRY_COMPLETED; |
|
204 } |
|
205 |
|
206 discoveredDevice->mErrVal = iStatus.Int(); |
|
207 |
|
208 enqueue(discoveredDevice); |
|
209 |
|
210 if (continueFlag) |
|
211 { |
|
212 setNext(); |
|
213 } |
|
214 |
|
215 } |
|
216 |
|
217 void BluetoothDeviceDiscoverer::DoCancel() |
|
218 { |
|
219 JELOG2(EJavaBluetooth); |
|
220 |
|
221 RThread thread; |
|
222 thread.FullName(mThreadName); |
|
223 mHostResolver.Cancel(); |
|
224 } |
|
225 |
|
226 /** |
|
227 * Fills the discovered device information into DiscoveredDevice object |
|
228 */ |
|
229 void BluetoothDeviceDiscoverer::fillDeviceInfo( |
|
230 DiscoveredDevice &aDiscoveredDevice) |
|
231 { |
|
232 JELOG2(EJavaBluetooth); |
|
233 |
|
234 // Filling inquiry status |
|
235 aDiscoveredDevice.mInquiryStatus = STATUS_DEVICE_FOUND; |
|
236 |
|
237 // Filling device name |
|
238 std::wstring *deviceName = new std::wstring( |
|
239 (wchar_t*) mNameEntry().iName.Ptr()); |
|
240 deviceName->resize(mNameEntry().iName.Length()); |
|
241 |
|
242 aDiscoveredDevice.mDeviceName = deviceName; |
|
243 |
|
244 LOG1(EJavaBluetooth, EInfo, |
|
245 " BluetoothDeviceDiscoverer::fillDeviceInfo Device Name %S", |
|
246 deviceName->c_str()); |
|
247 |
|
248 // Filling device address |
|
249 TBTDevAddr add = static_cast<TBTSockAddr>(mNameEntry().iAddr).BTAddr(); |
|
250 TBuf<20> buff; |
|
251 |
|
252 add.GetReadable(buff); |
|
253 std::wstring *deviceAddr = new std::wstring((wchar_t*) buff.Ptr()); |
|
254 deviceAddr->resize(buff.Length()); |
|
255 |
|
256 aDiscoveredDevice.mDeviceAddr = deviceAddr; |
|
257 |
|
258 LOG1(EJavaBluetooth, EInfo, |
|
259 " BluetoothDeviceDiscoverer::fillDeviceInfo Device Address %S", |
|
260 deviceAddr->c_str()); |
|
261 |
|
262 // Filling device class |
|
263 TInquirySockAddr& dev = TInquirySockAddr::Cast(mNameEntry().iAddr); |
|
264 |
|
265 int deviceClass = (dev.MajorServiceClass() << SERVICE_CLASS_POS) |
|
266 | (dev.MajorClassOfDevice() << MAJOR_CLASS_POS) |
|
267 | (dev.MajorClassOfDevice() << MINOR_CLASS_POS); |
|
268 |
|
269 aDiscoveredDevice.mDeviceClass = deviceClass; |
|
270 |
|
271 LOG1(EJavaBluetooth, EInfo, |
|
272 " BluetoothDeviceDiscoverer::fillDeviceInfo DeviceClass %d", |
|
273 deviceClass); |
|
274 } |
|
275 |
|
276 void BluetoothDeviceDiscoverer::enqueue(DiscoveredDevice *aDiscoveredDevice) |
|
277 { |
|
278 JELOG2(EJavaBluetooth); |
|
279 |
|
280 pthread_mutex_lock(&mMutex); |
|
281 |
|
282 mDiscoveredDevicesQueue.push(aDiscoveredDevice); |
|
283 if (mWaiting) |
|
284 { |
|
285 LOG(EJavaBluetooth, EInfo, |
|
286 "- BluetoothDeviceDiscoverer::enqueue NOTIFYING"); |
|
287 pthread_cond_signal(&mCondVar); |
|
288 } |
|
289 mWaiting = false; |
|
290 pthread_mutex_unlock(&mMutex); |
|
291 } |
|
292 |
|
293 void BluetoothDeviceDiscoverer::dequeue(DiscoveredDevice& aDiscoveredDevice) |
|
294 { |
|
295 JELOG2(EJavaBluetooth); |
|
296 LOG1(EJavaBluetooth, EInfo, "+ BluetoothDeviceDiscoverer::dequeue :%d", |
|
297 mDiscoveredDevicesQueue.empty()); |
|
298 DiscoveredDevice ret; |
|
299 |
|
300 pthread_mutex_lock(&mMutex); |
|
301 if (mDiscoveredDevicesQueue.empty()) |
|
302 { |
|
303 LOG(EJavaBluetooth, EInfo, |
|
304 "- BluetoothDeviceDiscoverer::dequeue WAITING"); |
|
305 mWaiting = true; |
|
306 |
|
307 while (mWaiting) |
|
308 { |
|
309 pthread_cond_wait(&mCondVar, &mMutex); |
|
310 } |
|
311 } |
|
312 |
|
313 DiscoveredDevice *ptr = mDiscoveredDevicesQueue.front(); |
|
314 aDiscoveredDevice = *ptr; |
|
315 delete ptr; // pop doesn't invoke the destructor |
|
316 mDiscoveredDevicesQueue.pop(); |
|
317 pthread_mutex_unlock(&mMutex); |
|
318 } |
|
319 |
|
320 void BluetoothDeviceDiscoverer::clearQueue() |
|
321 { |
|
322 JELOG2(EJavaBluetooth); |
|
323 pthread_mutex_lock(&mMutex); |
|
324 |
|
325 while (!mDiscoveredDevicesQueue.empty()) |
|
326 { |
|
327 mDiscoveredDevicesQueue.pop(); |
|
328 } |
|
329 pthread_mutex_unlock(&mMutex); |
|
330 } |
|
331 |
|
332 } //end namespace java |
|
333 } //end namespace bluetooth |