1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package com.intel.bluetooth;
25
26 import java.io.IOException;
27
28 import javax.bluetooth.BluetoothStateException;
29 import javax.bluetooth.DeviceClass;
30 import javax.bluetooth.DiscoveryAgent;
31 import javax.bluetooth.DiscoveryListener;
32 import javax.bluetooth.RemoteDevice;
33 import javax.bluetooth.ServiceRecord;
34 import javax.bluetooth.ServiceRegistrationException;
35 import javax.bluetooth.UUID;
36
37 class BluetoothStackBlueSoleil implements BluetoothStack, DeviceInquiryRunnable, SearchServicesRunnable {
38
39 private static BluetoothStackBlueSoleil singleInstance = null;
40
41 private boolean initialized = false;
42
43 private DiscoveryListener currentDeviceDiscoveryListener;
44
45 BluetoothStackBlueSoleil() {
46 }
47
48 public String getStackID() {
49 return BlueCoveImpl.STACK_BLUESOLEIL;
50 }
51
52 public String toString() {
53 return getStackID();
54 }
55
56
57
58
59
60
61
62
63 public native boolean isNativeCodeLoaded();
64
65
66
67
68
69
70 public LibraryInformation[] requireNativeLibraries() {
71 return LibraryInformation.library(BlueCoveImpl.NATIVE_LIB_BLUESOLEIL);
72 }
73
74 public native int getLibraryVersion();
75
76 public native int detectBluetoothStack();
77
78 public native void enableNativeDebug(Class nativeDebugCallback, boolean on);
79
80 public native boolean initializeImpl();
81
82 public void initialize() throws BluetoothStateException {
83 if (singleInstance != null) {
84 throw new BluetoothStateException("Only one instance of " + getStackID() + " stack supported");
85 }
86 if (!initializeImpl()) {
87 DebugLog.fatal("Can't initialize BlueSoleil");
88 throw new BluetoothStateException("BlueSoleil BluetoothStack not found");
89 }
90 initialized = true;
91 singleInstance = this;
92 }
93
94 private native void uninitialize();
95
96 public void destroy() {
97 if (singleInstance != this) {
98 throw new RuntimeException("Destroy invalid instance");
99 }
100 if (initialized) {
101 uninitialize();
102 initialized = false;
103 DebugLog.debug("BlueSoleil destroyed");
104 }
105 singleInstance = null;
106 }
107
108 protected void finalize() {
109 destroy();
110 }
111
112 public native String getLocalDeviceBluetoothAddress();
113
114 public native String getLocalDeviceName();
115
116 public native int getDeviceClassImpl();
117
118
119
120
121 public DeviceClass getLocalDeviceClass() {
122 return new DeviceClass(getDeviceClassImpl());
123 }
124
125
126
127
128
129
130 public void setLocalDeviceServiceClasses(int classOfDevice) {
131 throw new NotSupportedRuntimeException(getStackID());
132 }
133
134
135
136
137 public boolean setLocalDeviceDiscoverable(int mode) throws BluetoothStateException {
138 return true;
139 }
140
141 native boolean isBlueSoleilStarted(int seconds);
142
143 private native boolean isBluetoothReady(int seconds);
144
145
146
147
148 public int getLocalDeviceDiscoverable() {
149 if (isBluetoothReady(2)) {
150 return DiscoveryAgent.GIAC;
151 } else {
152 return DiscoveryAgent.NOT_DISCOVERABLE;
153 }
154 }
155
156 public boolean isLocalDevicePowerOn() {
157 return isBluetoothReady(15);
158 }
159
160 native int getStackVersionInfo();
161
162 native int getDeviceVersion();
163
164 native int getDeviceManufacturer();
165
166
167
168
169
170
171 public int getFeatureSet() {
172 return 0;
173 }
174
175 public String getLocalDeviceProperty(String property) {
176 if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX.equals(property)) {
177 return "7";
178 }
179 if (BluetoothConsts.PROPERTY_BLUETOOTH_SD_TRANS_MAX.equals(property)) {
180 return "1";
181 }
182 if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY_SCAN.equals(property)) {
183 return BlueCoveImpl.TRUE;
184 }
185 if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE_SCAN.equals(property)) {
186 return BlueCoveImpl.TRUE;
187 }
188 if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY.equals(property)) {
189 return BlueCoveImpl.TRUE;
190 }
191
192
193 if (BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX.equals(property)) {
194 return "0";
195 }
196
197
198
199
200
201
202
203 if ("bluecove.stack.version".equals(property)) {
204 return String.valueOf(getStackVersionInfo());
205 }
206
207 return null;
208 }
209
210
211
212
213
214
215 public boolean isCurrentThreadInterruptedCallback() {
216 return UtilsJavaSE.isCurrentThreadInterrupted();
217 }
218
219 public RemoteDevice[] retrieveDevices(int option) {
220 return null;
221 }
222
223 public Boolean isRemoteDeviceTrusted(long address) {
224 return null;
225 }
226
227 public Boolean isRemoteDeviceAuthenticated(long address) {
228 return null;
229 }
230
231 public boolean authenticateRemoteDevice(long address) throws IOException {
232 return false;
233 }
234
235 public boolean authenticateRemoteDevice(long address, String passkey) throws IOException {
236 return false;
237 }
238
239
240
241
242
243
244 public void removeAuthenticationWithRemoteDevice(long address) throws IOException {
245 throw new NotSupportedIOException(getStackID());
246 }
247
248
249
250 public boolean startInquiry(int accessCode, DiscoveryListener listener) throws BluetoothStateException {
251 if (currentDeviceDiscoveryListener != null) {
252 throw new BluetoothStateException("Another inquiry already running");
253 }
254 currentDeviceDiscoveryListener = listener;
255 return DeviceInquiryThread.startInquiry(this, this, accessCode, listener);
256 }
257
258 public int runDeviceInquiry(DeviceInquiryThread startedNotify, int accessCode, DiscoveryListener listener)
259 throws BluetoothStateException {
260 try {
261 startedNotify.deviceInquiryStartedCallback();
262 return runDeviceInquiryImpl(startedNotify, accessCode, listener);
263 } finally {
264 currentDeviceDiscoveryListener = null;
265 }
266 }
267
268 public native int runDeviceInquiryImpl(DeviceInquiryThread startedNotify, int accessCode, DiscoveryListener listener)
269 throws BluetoothStateException;
270
271 public void deviceDiscoveredCallback(DiscoveryListener listener, long deviceAddr, int deviceClass,
272 String deviceName, boolean paired) {
273 DebugLog.debug("deviceDiscoveredCallback", deviceName);
274 RemoteDevice remoteDevice = RemoteDeviceHelper.createRemoteDevice(this, deviceAddr, deviceName, paired);
275 if ((currentDeviceDiscoveryListener == null) || (currentDeviceDiscoveryListener != listener)) {
276 return;
277 }
278 listener.deviceDiscovered(remoteDevice, new DeviceClass(deviceClass));
279 }
280
281 public native boolean cancelInquirympl();
282
283 public boolean cancelInquiry(DiscoveryListener listener) {
284 if (currentDeviceDiscoveryListener != listener) {
285 return false;
286 }
287
288 currentDeviceDiscoveryListener = null;
289 return cancelInquirympl();
290 }
291
292 public String getRemoteDeviceFriendlyName(long address) throws IOException {
293
294 return null;
295 }
296
297
298
299 public int searchServices(int[] attrSet, UUID[] uuidSet, RemoteDevice device, DiscoveryListener listener)
300 throws BluetoothStateException {
301 return SearchServicesThread.startSearchServices(this, this, attrSet, uuidSet, device, listener);
302 }
303
304 public boolean cancelServiceSearch(int transID) {
305 return false;
306 }
307
308 private native int runSearchServicesImpl(SearchServicesThread startedNotify, DiscoveryListener listener,
309 byte[] uuidValue, long address, RemoteDevice device) throws BluetoothStateException;
310
311 public int runSearchServices(SearchServicesThread startedNotify, int[] attrSet, UUID[] uuidSet,
312 RemoteDevice device, DiscoveryListener listener) throws BluetoothStateException {
313 startedNotify.searchServicesStartedCallback();
314 UUID uuid = null;
315 if ((uuidSet != null) && (uuidSet.length > 0)) {
316 uuid = uuidSet[uuidSet.length - 1];
317 }
318 return runSearchServicesImpl(startedNotify, listener, Utils.UUIDToByteArray(uuid), RemoteDeviceHelper
319 .getAddress(device), device);
320 }
321
322
323
324
325
326
327 public void servicesFoundCallback(SearchServicesThread startedNotify, DiscoveryListener listener,
328 RemoteDevice device, String serviceName, byte[] uuidValue, int channel, long recordHanlde) {
329
330 ServiceRecordImpl record = new ServiceRecordImpl(this, device, 0);
331
332 UUID uuid = new UUID(Utils.UUIDByteArrayToString(uuidValue), false);
333
334 record.populateRFCOMMAttributes(recordHanlde, channel, uuid, serviceName, BluetoothConsts.obexUUIDs
335 .contains(uuid));
336 DebugLog.debug("servicesFoundCallback", record);
337
338 RemoteDevice listedDevice = RemoteDeviceHelper.createRemoteDevice(this, device);
339 RemoteDeviceHelper.setStackAttributes(this, listedDevice, "RFCOMM_channel" + channel, uuid);
340
341 ServiceRecord[] records = new ServiceRecordImpl[1];
342 records[0] = record;
343 listener.servicesDiscovered(startedNotify.getTransID(), records);
344 }
345
346 public boolean populateServicesRecordAttributeValues(ServiceRecordImpl serviceRecord, int[] attrIDs)
347 throws IOException {
348 return false;
349 }
350
351
352
353 private native long connectionRfOpenImpl(long address, byte[] uuidValue) throws IOException;
354
355 public long connectionRfOpenClientConnection(BluetoothConnectionParams params) throws IOException {
356 if (params.authenticate || params.encrypt) {
357 throw new IOException("authenticate not supported on BlueSoleil");
358 }
359 RemoteDevice listedDevice = RemoteDeviceHelper.getCashedDevice(this, params.address);
360 if (listedDevice == null) {
361 throw new IOException("Device not discovered");
362 }
363 UUID uuid = (UUID) RemoteDeviceHelper.getStackAttributes(this, listedDevice, "RFCOMM_channel" + params.channel);
364 if (uuid == null) {
365 throw new IOException("Device service not discovered");
366 }
367 DebugLog.debug("Connect to service UUID", uuid);
368 return connectionRfOpenImpl(params.address, Utils.UUIDToByteArray(uuid));
369 }
370
371 public native void connectionRfCloseClientConnection(long handle) throws IOException;
372
373 private native long rfServerOpenImpl(byte[] uuidValue, String name, boolean authenticate, boolean encrypt)
374 throws IOException;
375
376 private native int rfServerSCN(long handle) throws IOException;
377
378 public long rfServerOpen(BluetoothConnectionNotifierParams params, ServiceRecordImpl serviceRecord)
379 throws IOException {
380 if (params.authenticate || params.encrypt) {
381 throw new IOException("authenticate not supported on BlueSoleil");
382 }
383 byte[] uuidValue = Utils.UUIDToByteArray(params.uuid);
384 long handle = rfServerOpenImpl(uuidValue, params.name, params.authenticate, params.encrypt);
385 int channel = rfServerSCN(handle);
386 DebugLog.debug("serverSCN", channel);
387 int serviceRecordHandle = (int) handle;
388
389 serviceRecord.populateRFCOMMAttributes(serviceRecordHandle, channel, params.uuid, params.name, false);
390
391 return handle;
392 }
393
394 public void rfServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
395 throws ServiceRegistrationException {
396 if (!acceptAndOpen) {
397 throw new ServiceRegistrationException("Not Supported on " + getStackID());
398 }
399 }
400
401 public native long rfServerAcceptAndOpenRfServerConnection(long handle) throws IOException;
402
403 public void connectionRfCloseServerConnection(long handle) throws IOException {
404 connectionRfCloseClientConnection(handle);
405 }
406
407 public native void rfServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException;
408
409 public native long getConnectionRfRemoteAddress(long handle) throws IOException;
410
411 public native int connectionRfRead(long handle) throws IOException;
412
413 public native int connectionRfRead(long handle, byte[] b, int off, int len) throws IOException;
414
415 public native int connectionRfReadAvailable(long handle) throws IOException;
416
417 public native void connectionRfWrite(long handle, int b) throws IOException;
418
419 public native void connectionRfWrite(long handle, byte[] b, int off, int len) throws IOException;
420
421 public native void connectionRfFlush(long handle) throws IOException;
422
423 public int rfGetSecurityOpt(long handle, int expected) throws IOException {
424 return ServiceRecord.NOAUTHENTICATE_NOENCRYPT;
425 }
426
427
428
429
430
431
432 public boolean rfEncrypt(long address, long handle, boolean on) throws IOException {
433 return false;
434 }
435
436
437
438
439
440
441
442
443
444 public long l2OpenClientConnection(BluetoothConnectionParams params, int receiveMTU, int transmitMTU)
445 throws IOException {
446 throw new NotSupportedIOException(getStackID());
447 }
448
449
450
451
452
453
454 public void l2CloseClientConnection(long handle) throws IOException {
455 throw new NotSupportedIOException(getStackID());
456 }
457
458
459
460
461
462
463
464 public long l2ServerOpen(BluetoothConnectionNotifierParams params, int receiveMTU, int transmitMTU,
465 ServiceRecordImpl serviceRecord) throws IOException {
466 throw new NotSupportedIOException(getStackID());
467 }
468
469
470
471
472
473
474
475 public void l2ServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
476 throws ServiceRegistrationException {
477 throw new ServiceRegistrationException("Not Supported on" + getStackID());
478 }
479
480
481
482
483
484
485 public long l2ServerAcceptAndOpenServerConnection(long handle) throws IOException {
486 throw new NotSupportedIOException(getStackID());
487 }
488
489
490
491
492
493
494 public void l2CloseServerConnection(long handle) throws IOException {
495 throw new NotSupportedIOException(getStackID());
496 }
497
498
499
500
501
502
503 public void l2ServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException {
504 throw new NotSupportedIOException(getStackID());
505 }
506
507
508
509
510
511
512 public int l2GetSecurityOpt(long handle, int expected) throws IOException {
513 throw new NotSupportedIOException(getStackID());
514 }
515
516
517
518
519
520
521 public boolean l2Ready(long handle) throws IOException {
522 throw new NotSupportedIOException(getStackID());
523 }
524
525
526
527
528
529
530 public int l2Receive(long handle, byte[] inBuf) throws IOException {
531 throw new NotSupportedIOException(getStackID());
532 }
533
534
535
536
537
538
539 public void l2Send(long handle, byte[] data) throws IOException {
540 throw new NotSupportedIOException(getStackID());
541 }
542
543
544
545
546
547
548 public int l2GetReceiveMTU(long handle) throws IOException {
549 throw new NotSupportedIOException(getStackID());
550 }
551
552
553
554
555
556
557 public int l2GetTransmitMTU(long handle) throws IOException {
558 throw new NotSupportedIOException(getStackID());
559 }
560
561
562
563
564
565
566 public long l2RemoteAddress(long handle) throws IOException {
567 throw new NotSupportedIOException(getStackID());
568 }
569
570
571
572
573
574
575 public boolean l2Encrypt(long address, long handle, boolean on) throws IOException {
576 throw new NotSupportedIOException(getStackID());
577 }
578
579 }