1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package com.intel.bluetooth;
22
23 import java.io.IOException;
24 import java.util.Hashtable;
25 import java.util.Vector;
26
27 import javax.bluetooth.BluetoothStateException;
28 import javax.bluetooth.DataElement;
29 import javax.bluetooth.DeviceClass;
30 import javax.bluetooth.DiscoveryListener;
31 import javax.bluetooth.RemoteDevice;
32 import javax.bluetooth.ServiceRecord;
33 import javax.bluetooth.ServiceRegistrationException;
34 import javax.bluetooth.UUID;
35
36
37
38
39
40
41 class BluetoothStackBlueZ implements BluetoothStack {
42
43 public static final String NATIVE_BLUECOVE_LIB_BLUEZ = "bluecove";
44
45 static final int NATIVE_LIBRARY_VERSION = BlueCoveImpl.nativeLibraryVersionExpected;
46
47
48 private final static int ATTR_RETRIEVABLE_MAX = 256;
49
50 private final static int LISTEN_BACKLOG_RFCOMM = 4;
51
52 private final static int LISTEN_BACKLOG_L2CAP = 4;
53
54 private final static Vector devicesUsed = new Vector();
55
56 private int deviceID = -1;
57
58 private int deviceDescriptor;
59
60 private long localDeviceBTAddress;
61
62 private long sdpSesion;
63
64 private int registeredServicesCount = 0;
65
66 private Hashtable
67
68 private DiscoveryListener discoveryListener;
69
70
71 private Vector
72
73 private boolean deviceInquiryCanceled = false;
74
75 private final int l2cap_receiveMTU_max = 65535;
76
77 BluetoothStackBlueZ() {
78 }
79
80
81
82 public String getStackID() {
83 return BlueCoveImpl.STACK_BLUEZ;
84 }
85
86 public String toString() {
87 if (deviceID >= 0) {
88 return getStackID() + ":" + deviceID;
89 } else {
90 return getStackID();
91 }
92 }
93
94
95
96
97
98
99 public native boolean isNativeCodeLoaded();
100
101
102
103
104
105
106 public LibraryInformation[] requireNativeLibraries() {
107 return LibraryInformation.library(NATIVE_BLUECOVE_LIB_BLUEZ);
108 }
109
110 public native int getLibraryVersionNative();
111
112 public int getLibraryVersion() throws BluetoothStateException {
113 int version = getLibraryVersionNative();
114 if (version != NATIVE_LIBRARY_VERSION) {
115 DebugLog.fatal("BlueCove native library version mismatch " + version + " expected " + NATIVE_LIBRARY_VERSION);
116 throw new BluetoothStateException("BlueCove native library version mismatch");
117 }
118 return version;
119 }
120
121 public int detectBluetoothStack() {
122 return BlueCoveImpl.BLUECOVE_STACK_DETECT_BLUEZ;
123 }
124
125 private native int nativeGetDeviceID(int id, long findLocalDeviceBTAddress) throws BluetoothStateException;
126
127 private native int nativeOpenDevice(int deviceID) throws BluetoothStateException;
128
129 public void initialize() throws BluetoothStateException {
130 long findLocalDeviceBTAddress = -1;
131 int findID = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_LOCAL_DEVICE_ID, -1);
132 String deviceAddressStr = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_LOCAL_DEVICE_ADDRESS);
133 if (deviceAddressStr != null) {
134 findLocalDeviceBTAddress = Long.parseLong(deviceAddressStr, 16);
135 }
136 int foundDeviceID = nativeGetDeviceID(findID, findLocalDeviceBTAddress);
137 if (devicesUsed.contains(new Long(foundDeviceID))) {
138 throw new BluetoothStateException("LocalDevice " + foundDeviceID + " alredy in use");
139 }
140
141 this.deviceID = foundDeviceID;
142 DebugLog.debug("localDeviceID", deviceID);
143 deviceDescriptor = nativeOpenDevice(deviceID);
144 localDeviceBTAddress = getLocalDeviceBluetoothAddressImpl(deviceDescriptor);
145 propertiesMap = new Hashtable
146 final String TRUE = "true";
147 final String FALSE = "false";
148 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX, "7");
149 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_SD_TRANS_MAX, "7");
150 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY_SCAN, TRUE);
151 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE_SCAN, TRUE);
152 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY, TRUE);
153 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE, TRUE);
154 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX, String.valueOf(ATTR_RETRIEVABLE_MAX));
155 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_MASTER_SWITCH, FALSE);
156 propertiesMap.put(BluetoothConsts.PROPERTY_BLUETOOTH_L2CAP_RECEIVEMTU_MAX, String.valueOf(l2cap_receiveMTU_max));
157
158
159
160 propertiesMap.put(BlueCoveLocalDeviceProperties.LOCAL_DEVICE_PROPERTY_DEVICE_ID, String.valueOf(deviceID));
161
162 devicesUsed.addElement(new Long(deviceID));
163 }
164
165 private native void nativeCloseDevice(int deviceDescriptor);
166
167 public void destroy() {
168 if (sdpSesion != 0) {
169 try {
170 long s = sdpSesion;
171 sdpSesion = 0;
172 closeSDPSessionImpl(s, true);
173 } catch (ServiceRegistrationException ignore) {
174 }
175 }
176 nativeCloseDevice(deviceDescriptor);
177 if (deviceID >= 0) {
178 devicesUsed.removeElement(new Long(deviceID));
179 deviceID = -1;
180 }
181 }
182
183 public native void enableNativeDebug(Class nativeDebugCallback, boolean on);
184
185
186
187
188
189
190
191 public boolean isCurrentThreadInterruptedCallback() {
192 return UtilsJavaSE.isCurrentThreadInterrupted();
193 }
194
195
196
197
198
199
200 public int getFeatureSet() {
201 return FEATURE_SERVICE_ATTRIBUTES | FEATURE_L2CAP;
202 }
203
204 private native int[] getLocalDevicesID();
205
206
207
208 private native long getLocalDeviceBluetoothAddressImpl(int deviceDescriptor) throws BluetoothStateException;
209
210 public String getLocalDeviceBluetoothAddress() throws BluetoothStateException {
211 return RemoteDeviceHelper.getBluetoothAddress(getLocalDeviceBluetoothAddressImpl(deviceDescriptor));
212 }
213
214 private native int nativeGetDeviceClass(int deviceDescriptor);
215
216 public DeviceClass getLocalDeviceClass() {
217 int record = nativeGetDeviceClass(deviceDescriptor);
218 if (record == 0xff000000) {
219
220 return null;
221 }
222 return new DeviceClass(record);
223 }
224
225 private native String nativeGetDeviceName(int deviceDescriptor);
226
227 public String getLocalDeviceName() {
228 return nativeGetDeviceName(deviceDescriptor);
229 }
230
231 public boolean isLocalDevicePowerOn() {
232
233
234 return true;
235 }
236
237 public String getLocalDeviceProperty(String property) {
238 if (BlueCoveLocalDeviceProperties.LOCAL_DEVICE_DEVICES_LIST.equals(property)) {
239 int[] ids = getLocalDevicesID();
240 StringBuffer b = new StringBuffer();
241 if (ids != null) {
242 for (int i = 0; i < ids.length; i++) {
243 if (i != 0) {
244 b.append(',');
245 }
246 b.append(String.valueOf(ids[i]));
247 }
248 }
249 return b.toString();
250 }
251
252 if (property.startsWith("bluecove.nativeFunction:")) {
253 String functionDescr = property.substring(property.indexOf(':') + 1, property.length());
254 int paramIdx = functionDescr.indexOf(':');
255 if (paramIdx == -1) {
256 throw new RuntimeException("Invalid native function " + functionDescr + "; arguments expected");
257 }
258 String function = functionDescr.substring(0, paramIdx);
259 long address = RemoteDeviceHelper.getAddress(functionDescr.substring(function.length() + 1, functionDescr.length()));
260 if ("getRemoteDeviceVersionInfo".equals(function)) {
261 return getRemoteDeviceVersionInfo(address);
262 } else if ("getRemoteDeviceRSSI".equals(function)) {
263 return String.valueOf(getRemoteDeviceRSSI(address));
264 }
265 return null;
266 }
267 return (String) propertiesMap.get(property);
268 }
269
270 private native int nativeGetLocalDeviceDiscoverable(int deviceDescriptor);
271
272 public int getLocalDeviceDiscoverable() {
273 return nativeGetLocalDeviceDiscoverable(deviceDescriptor);
274 }
275
276 private native int nativeSetLocalDeviceDiscoverable(int deviceDescriptor, int mode);
277
278
279
280
281
282
283
284
285
286 public boolean setLocalDeviceDiscoverable(int mode) throws BluetoothStateException {
287 int curentMode = getLocalDeviceDiscoverable();
288 if (curentMode == mode) {
289 return true;
290 } else {
291 int error = nativeSetLocalDeviceDiscoverable(deviceDescriptor, mode);
292 if (error != 0) {
293 DebugLog.error("Unable to change discovery mode. It may be because you aren't root; " + error);
294 return false;
295 }
296 return true;
297 }
298 }
299
300
301
302
303
304
305 public void setLocalDeviceServiceClasses(int classOfDevice) {
306 throw new NotSupportedRuntimeException(getStackID());
307 }
308
309
310
311 public boolean authenticateRemoteDevice(long address) throws IOException {
312 return false;
313 }
314
315
316
317
318
319
320
321 public boolean authenticateRemoteDevice(long address, String passkey) throws IOException {
322 return false;
323 }
324
325
326
327
328
329
330
331
332 public void removeAuthenticationWithRemoteDevice(long address) throws IOException {
333
334 throw new NotSupportedIOException(getStackID());
335 }
336
337
338
339 private native String getRemoteDeviceVersionInfoImpl(int deviceDescriptor, long address);
340
341 public String getRemoteDeviceVersionInfo(long address) {
342 return getRemoteDeviceVersionInfoImpl(this.deviceDescriptor, address);
343 }
344
345 private native int getRemoteDeviceRSSIImpl(int deviceDescriptor, long address);
346
347 public int getRemoteDeviceRSSI(long address) {
348 return getRemoteDeviceRSSIImpl(this.deviceDescriptor, address);
349 }
350
351 public RemoteDevice[] retrieveDevices(int option) {
352 return null;
353 }
354
355 public Boolean isRemoteDeviceTrusted(long address) {
356 return null;
357 }
358
359 public Boolean isRemoteDeviceAuthenticated(long address) {
360 return null;
361 }
362
363
364
365 private native int runDeviceInquiryImpl(DeviceInquiryRunnable inquiryRunnable, DeviceInquiryThread startedNotify, int deviceID, int deviceDescriptor, int accessCode, int inquiryLength,
366 int maxResponses, DiscoveryListener listener) throws BluetoothStateException;
367
368 public boolean startInquiry(int accessCode, DiscoveryListener listener) throws BluetoothStateException {
369 if (discoveryListener != null) {
370 throw new BluetoothStateException("Another inquiry already running");
371 }
372 discoveryListener = listener;
373 discoveredDevices = new Vector();
374 deviceInquiryCanceled = false;
375 DeviceInquiryRunnable inquiryRunnable = new DeviceInquiryRunnable() {
376
377 public int runDeviceInquiry(DeviceInquiryThread startedNotify, int accessCode, DiscoveryListener listener) throws BluetoothStateException {
378 try {
379 int discType = runDeviceInquiryImpl(this, startedNotify, deviceID, deviceDescriptor, accessCode, 8, 20, listener);
380 if (deviceInquiryCanceled) {
381 return DiscoveryListener.INQUIRY_TERMINATED;
382 }
383 return discType;
384 } finally {
385 discoveryListener = null;
386 discoveredDevices = null;
387 }
388 }
389
390 public void deviceDiscoveredCallback(DiscoveryListener listener, long deviceAddr, int deviceClass, String deviceName, boolean paired) {
391 RemoteDevice remoteDevice = RemoteDeviceHelper.createRemoteDevice(BluetoothStackBlueZ.this, deviceAddr, deviceName, paired);
392 if (deviceInquiryCanceled || (discoveryListener == null) || (discoveredDevices == null) || (discoveredDevices.contains(remoteDevice))) {
393 return;
394 }
395 discoveredDevices.addElement(remoteDevice);
396 DeviceClass cod = new DeviceClass(deviceClass);
397 DebugLog.debug("deviceDiscoveredCallback address", remoteDevice.getBluetoothAddress());
398 DebugLog.debug("deviceDiscoveredCallback deviceClass", cod);
399 listener.deviceDiscovered(remoteDevice, cod);
400
401 }
402 };
403 return DeviceInquiryThread.startInquiry(this, inquiryRunnable, accessCode, listener);
404 }
405
406 private native boolean deviceInquiryCancelImpl(int deviceDescriptor);
407
408 public boolean cancelInquiry(DiscoveryListener listener) {
409 if (discoveryListener != null && discoveryListener == listener) {
410 deviceInquiryCanceled = true;
411 return deviceInquiryCancelImpl(deviceDescriptor);
412 }
413 return false;
414 }
415
416 private native String getRemoteDeviceFriendlyNameImpl(int deviceDescriptor, long remoteAddress) throws IOException;
417
418 public String getRemoteDeviceFriendlyName(long address) throws IOException {
419 return getRemoteDeviceFriendlyNameImpl(deviceDescriptor, address);
420 }
421
422
423
424 private native int runSearchServicesImpl(SearchServicesThread sst, long localDeviceBTAddress, byte[][] uuidValues, long remoteDeviceAddress)
425 throws SearchServicesException;
426
427 public int searchServices(int[] attrSet, UUID[] uuidSet, RemoteDevice device, DiscoveryListener listener) throws BluetoothStateException {
428
429 SearchServicesRunnable searchRunnable = new SearchServicesRunnable() {
430
431 public int runSearchServices(SearchServicesThread sst, int[] attrSet, UUID[] uuidSet, RemoteDevice device, DiscoveryListener listener)
432 throws BluetoothStateException {
433 sst.searchServicesStartedCallback();
434 try {
435 byte[][] uuidValues = new byte[uuidSet.length][];
436 for (int i = 0; i < uuidSet.length; i++) {
437 uuidValues[i] = Utils.UUIDToByteArray(uuidSet[i]);
438 }
439 int respCode = runSearchServicesImpl(sst, localDeviceBTAddress, uuidValues, RemoteDeviceHelper.getAddress(device));
440 if ((respCode != DiscoveryListener.SERVICE_SEARCH_ERROR) && (sst.isTerminated())) {
441 return DiscoveryListener.SERVICE_SEARCH_TERMINATED;
442 } else if (respCode == DiscoveryListener.SERVICE_SEARCH_COMPLETED) {
443 Vector records = sst.getServicesRecords();
444 if (records.size() != 0) {
445 DebugLog.debug("SearchServices finished", sst.getTransID());
446 ServiceRecord[] servRecordArray = (ServiceRecord[]) Utils.vector2toArray(records, new ServiceRecord[records.size()]);
447 listener.servicesDiscovered(sst.getTransID(), servRecordArray);
448 }
449 if (records.size() != 0) {
450 return DiscoveryListener.SERVICE_SEARCH_COMPLETED;
451 } else {
452 return DiscoveryListener.SERVICE_SEARCH_NO_RECORDS;
453 }
454 } else {
455 return respCode;
456 }
457 } catch (SearchServicesDeviceNotReachableException e) {
458 return DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE;
459 } catch (SearchServicesTerminatedException e) {
460 return DiscoveryListener.SERVICE_SEARCH_TERMINATED;
461 } catch (SearchServicesException e) {
462 return DiscoveryListener.SERVICE_SEARCH_ERROR;
463 }
464 }
465 };
466 return SearchServicesThread.startSearchServices(this, searchRunnable, attrSet, uuidSet, device, listener);
467 }
468
469 public boolean serviceDiscoveredCallback(SearchServicesThread sst, long sdpSession, long handle) {
470 if (sst.isTerminated()) {
471 return true;
472 }
473 ServiceRecordImpl servRecord = new ServiceRecordImpl(this, sst.getDevice(), handle);
474 int[] attrIDs = sst.getAttrSet();
475 long remoteDeviceAddress = RemoteDeviceHelper.getAddress(sst.getDevice());
476 populateServiceRecordAttributeValuesImpl(this.localDeviceBTAddress, remoteDeviceAddress, sdpSession, handle, attrIDs, servRecord);
477 sst.addServicesRecords(servRecord);
478 return false;
479 }
480
481 public boolean cancelServiceSearch(int transID) {
482 SearchServicesThread sst = SearchServicesThread.getServiceSearchThread(transID);
483 if (sst != null) {
484 return sst.setTerminated();
485 } else {
486 return false;
487 }
488 }
489
490 private native boolean populateServiceRecordAttributeValuesImpl(long localDeviceBTAddress, long remoteDeviceAddress, long sdpSession, long handle,
491 int[] attrIDs, ServiceRecordImpl serviceRecord);
492
493 public boolean populateServicesRecordAttributeValues(ServiceRecordImpl serviceRecord, int[] attrIDs) throws IOException {
494 long remoteDeviceAddress = RemoteDeviceHelper.getAddress(serviceRecord.getHostDevice());
495 return populateServiceRecordAttributeValuesImpl(this.localDeviceBTAddress, remoteDeviceAddress, 0, serviceRecord.getHandle(), attrIDs, serviceRecord);
496 }
497
498
499
500 private native long openSDPSessionImpl() throws ServiceRegistrationException;
501
502 private synchronized long getSDPSession() throws ServiceRegistrationException {
503 if (this.sdpSesion == 0) {
504 sdpSesion = openSDPSessionImpl();
505 DebugLog.debug("created SDPSession", sdpSesion);
506 }
507 return sdpSesion;
508 }
509
510 private native void closeSDPSessionImpl(long sdpSesion, boolean quietly) throws ServiceRegistrationException;
511
512 private native long registerSDPServiceImpl(long sdpSesion, long localDeviceBTAddress, byte[] record) throws ServiceRegistrationException;
513
514 private native void updateSDPServiceImpl(long sdpSesion, long localDeviceBTAddress, long handle, byte[] record) throws ServiceRegistrationException;
515
516 private native void unregisterSDPServiceImpl(long sdpSesion, long localDeviceBTAddress, long handle, byte[] record) throws ServiceRegistrationException;
517
518 private byte[] getSDPBinary(ServiceRecordImpl serviceRecord) throws ServiceRegistrationException {
519 byte[] blob;
520 try {
521 blob = serviceRecord.toByteArray();
522 } catch (IOException e) {
523 throw new ServiceRegistrationException(e.toString());
524 }
525 return blob;
526 }
527
528 private synchronized void registerSDPRecord(ServiceRecordImpl serviceRecord) throws ServiceRegistrationException {
529 long handle = registerSDPServiceImpl(getSDPSession(), this.localDeviceBTAddress, getSDPBinary(serviceRecord));
530 serviceRecord.setHandle(handle);
531 serviceRecord.populateAttributeValue(BluetoothConsts.ServiceRecordHandle, new DataElement(DataElement.U_INT_4, handle));
532 registeredServicesCount++;
533 }
534
535 private void updateSDPRecord(ServiceRecordImpl serviceRecord) throws ServiceRegistrationException {
536 updateSDPServiceImpl(getSDPSession(), this.localDeviceBTAddress, serviceRecord.getHandle(), getSDPBinary(serviceRecord));
537 }
538
539 private synchronized void unregisterSDPRecord(ServiceRecordImpl serviceRecord) throws ServiceRegistrationException {
540 try {
541 unregisterSDPServiceImpl(getSDPSession(), this.localDeviceBTAddress, serviceRecord.getHandle(), getSDPBinary(serviceRecord));
542 } finally {
543 registeredServicesCount--;
544 if (registeredServicesCount <= 0) {
545 registeredServicesCount = 0;
546 DebugLog.debug("closeSDPSession", sdpSesion);
547 long s = sdpSesion;
548 sdpSesion = 0;
549 closeSDPSessionImpl(s, false);
550 }
551 }
552 }
553
554
555
556 private native long connectionRfOpenClientConnectionImpl(long localDeviceBTAddress, long address, int channel, boolean authenticate, boolean encrypt,
557 int timeout) throws IOException;
558
559 public long connectionRfOpenClientConnection(BluetoothConnectionParams params) throws IOException {
560 return connectionRfOpenClientConnectionImpl(localDeviceBTAddress, params.address, params.channel, params.authenticate, params.encrypt, params.timeout);
561 }
562
563 public native void connectionRfCloseClientConnection(long handle) throws IOException;
564
565 public native int rfGetSecurityOptImpl(long handle) throws IOException;
566
567 public int rfGetSecurityOpt(long handle, int expected) throws IOException {
568 return rfGetSecurityOptImpl(handle);
569 }
570
571
572
573
574
575
576 public boolean rfEncrypt(long address, long handle, boolean on) throws IOException {
577 return false;
578 }
579
580 private native long rfServerOpenImpl(long localDeviceBTAddress, boolean authorize, boolean authenticate, boolean encrypt, boolean master, boolean timeouts,
581 int backlog) throws IOException;
582
583 private native int rfServerGetChannelIDImpl(long handle) throws IOException;
584
585 public long rfServerOpen(BluetoothConnectionNotifierParams params, ServiceRecordImpl serviceRecord) throws IOException {
586 long socket = rfServerOpenImpl(this.localDeviceBTAddress, params.authorize, params.authenticate, params.encrypt, params.master, params.timeouts,
587 LISTEN_BACKLOG_RFCOMM);
588 boolean success = false;
589 try {
590 int channel = rfServerGetChannelIDImpl(socket);
591 serviceRecord.populateRFCOMMAttributes(0, channel, params.uuid, params.name, params.obex);
592 registerSDPRecord(serviceRecord);
593 success = true;
594 return socket;
595 } finally {
596 if (!success) {
597 rfServerCloseImpl(socket, true);
598 }
599 }
600 }
601
602 private native void rfServerCloseImpl(long handle, boolean quietly) throws IOException;
603
604 public void rfServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException {
605 try {
606 unregisterSDPRecord(serviceRecord);
607 } finally {
608 rfServerCloseImpl(handle, false);
609 }
610 }
611
612 public void rfServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen) throws ServiceRegistrationException {
613 updateSDPRecord(serviceRecord);
614 }
615
616 public native long rfServerAcceptAndOpenRfServerConnection(long handle) throws IOException;
617
618 public void connectionRfCloseServerConnection(long clientHandle) throws IOException {
619 connectionRfCloseClientConnection(clientHandle);
620 }
621
622
623
624 public int connectionRfRead(long handle) throws IOException {
625 byte[] data = new byte[1];
626 int size = connectionRfRead(handle, data, 0, 1);
627 if (size == -1) {
628 return -1;
629 }
630 return 0xFF & data[0];
631 }
632
633 public native int connectionRfRead(long handle, byte[] b, int off, int len) throws IOException;
634
635 public native int connectionRfReadAvailable(long handle) throws IOException;
636
637 public native void connectionRfWrite(long handle, int b) throws IOException;
638
639 public native void connectionRfWrite(long handle, byte[] b, int off, int len) throws IOException;
640
641 public native void connectionRfFlush(long handle) throws IOException;
642
643 public native long getConnectionRfRemoteAddress(long handle) throws IOException;
644
645
646
647 private void validateMTU(int receiveMTU, int transmitMTU) {
648 if (receiveMTU > l2cap_receiveMTU_max) {
649 throw new IllegalArgumentException("invalid ReceiveMTU value " + receiveMTU);
650 }
651 }
652
653 private native long l2OpenClientConnectionImpl(long localDeviceBTAddress, long address, int channel, boolean authenticate, boolean encrypt, int receiveMTU,
654 int transmitMTU, int timeout) throws IOException;
655
656
657
658
659
660
661
662
663 public long l2OpenClientConnection(BluetoothConnectionParams params, int receiveMTU, int transmitMTU) throws IOException {
664 validateMTU(receiveMTU, transmitMTU);
665 return l2OpenClientConnectionImpl(this.localDeviceBTAddress, params.address, params.channel, params.authenticate, params.encrypt, receiveMTU,
666 transmitMTU, params.timeout);
667 }
668
669
670
671
672
673
674 public native void l2CloseClientConnection(long handle) throws IOException;
675
676 private native long l2ServerOpenImpl(long localDeviceBTAddress, boolean authorize, boolean authenticate, boolean encrypt, boolean master, boolean timeouts,
677 int backlog, int receiveMTU, int transmitMTU, int assignPsm) throws IOException;
678
679 public native int l2ServerGetPSMImpl(long handle) throws IOException;
680
681
682
683
684
685
686
687
688 public long l2ServerOpen(BluetoothConnectionNotifierParams params, int receiveMTU, int transmitMTU, ServiceRecordImpl serviceRecord) throws IOException {
689 validateMTU(receiveMTU, transmitMTU);
690 long socket = l2ServerOpenImpl(this.localDeviceBTAddress, params.authorize, params.authenticate, params.encrypt, params.master, params.timeouts,
691 LISTEN_BACKLOG_L2CAP, receiveMTU, transmitMTU, params.bluecove_ext_psm);
692 boolean success = false;
693 try {
694 int channel = l2ServerGetPSMImpl(socket);
695 serviceRecord.populateL2CAPAttributes(0, channel, params.uuid, params.name);
696 registerSDPRecord(serviceRecord);
697 success = true;
698 return socket;
699 } finally {
700 if (!success) {
701 l2ServerCloseImpl(socket, true);
702 }
703 }
704 }
705
706
707
708
709
710
711
712 public void l2ServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen) throws ServiceRegistrationException {
713 updateSDPRecord(serviceRecord);
714 }
715
716
717
718
719
720
721
722
723 public native long l2ServerAcceptAndOpenServerConnection(long handle) throws IOException;
724
725
726
727
728
729
730 public void l2CloseServerConnection(long handle) throws IOException {
731 l2CloseClientConnection(handle);
732 }
733
734 private native void l2ServerCloseImpl(long handle, boolean quietly) throws IOException;
735
736
737
738
739
740
741
742 public void l2ServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException {
743 try {
744 unregisterSDPRecord(serviceRecord);
745 } finally {
746 l2ServerCloseImpl(handle, false);
747 }
748
749 }
750
751
752
753
754
755
756 public native boolean l2Ready(long handle) throws IOException;
757
758
759
760
761
762
763 public native int l2Receive(long handle, byte[] inBuf) throws IOException;
764
765
766
767
768
769
770 public native void l2Send(long handle, byte[] data) throws IOException;
771
772
773
774
775
776
777 public native int l2GetReceiveMTU(long handle) throws IOException;
778
779
780
781
782
783
784 public native int l2GetTransmitMTU(long handle) throws IOException;
785
786
787
788
789
790
791 public native long l2RemoteAddress(long handle) throws IOException;
792
793
794
795
796
797
798 public native int l2GetSecurityOpt(long handle, int expected) throws IOException;
799
800
801
802
803
804
805 public boolean l2Encrypt(long address, long handle, boolean on) throws IOException {
806 return false;
807 }
808 }