View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2006-2008 Vlad Skarzhevskyy
4    *
5    *  This library is free software; you can redistribute it and/or
6    *  modify it under the terms of the GNU Lesser General Public
7    *  License as published by the Free Software Foundation; either
8    *  version 2.1 of the License, or (at your option) any later version.
9    *
10   *  This library is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   *  Lesser General Public License for more details.
14   *
15   *  You should have received a copy of the GNU Lesser General Public
16   *  License along with this library; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   *
19   *  @version $Id: BluetoothStackMicrosoft.java 2366 2008-07-21 15:51:14Z skarzhevskyy $
20   */
21  package com.intel.bluetooth;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.IOException;
25  import java.util.Enumeration;
26  import java.util.Hashtable;
27  
28  import javax.bluetooth.BluetoothStateException;
29  import javax.bluetooth.DataElement;
30  import javax.bluetooth.DeviceClass;
31  import javax.bluetooth.DiscoveryAgent;
32  import javax.bluetooth.DiscoveryListener;
33  import javax.bluetooth.RemoteDevice;
34  import javax.bluetooth.ServiceRecord;
35  import javax.bluetooth.ServiceRegistrationException;
36  import javax.bluetooth.UUID;
37  
38  class BluetoothStackMicrosoft implements BluetoothStack, DeviceInquiryRunnable, SearchServicesRunnable {
39  
40  	private static final int BTH_MODE_POWER_OFF = 1;
41  
42  	private static final int BTH_MODE_CONNECTABLE = 2;
43  
44  	private static final int BTH_MODE_DISCOVERABLE = 3;
45  
46  	private static BluetoothStackMicrosoft singleInstance = null;
47  
48  	private boolean peerInitialized = false;
49  
50  	private boolean windowsCE;
51  
52  	private long localBluetoothAddress = 0;
53  
54  	private DiscoveryListener currentDeviceDiscoveryListener;
55  
56  	private Thread limitedDiscoverableTimer;
57  
58  	// TODO what is the real number for Attributes retrievable ?
59  	private final static int ATTR_RETRIEVABLE_MAX = 256;
60  
61  	private Hashtable deviceDiscoveryDevices;
62  
63  	BluetoothStackMicrosoft() {
64  	}
65  
66  	// ---------------------- Library initialization
67  
68  	public String getStackID() {
69  		return BlueCoveImpl.STACK_WINSOCK;
70  	}
71  
72  	/*
73  	 * (non-Javadoc)
74  	 * 
75  	 * @see com.intel.bluetooth.BluetoothStack#isNativeCodeLoaded()
76  	 */
77  	public native boolean isNativeCodeLoaded();
78  
79  	/*
80  	 * (non-Javadoc)
81  	 * 
82  	 * @see com.intel.bluetooth.BluetoothStack#requireNativeLibraries()
83  	 */
84  	public LibraryInformation[] requireNativeLibraries() {
85  		return LibraryInformation.library(BlueCoveImpl.NATIVE_LIB_MS);
86  	}
87  
88  	public String toString() {
89  		return getStackID();
90  	}
91  
92  	public native int getLibraryVersion();
93  
94  	public native int detectBluetoothStack();
95  
96  	public native void enableNativeDebug(Class nativeDebugCallback, boolean on);
97  
98  	private static native int initializationStatus() throws IOException;
99  
100 	private native void uninitialize();
101 
102 	private native boolean isWindowsCE();
103 
104 	public void initialize() throws BluetoothStateException {
105 		if (singleInstance != null) {
106 			throw new BluetoothStateException("Only one instance of " + getStackID() + " stack supported");
107 		}
108 		try {
109 			int status = initializationStatus();
110 			DebugLog.debug("initializationStatus", status);
111 			if (status == 1) {
112 				peerInitialized = true;
113 			}
114 			windowsCE = isWindowsCE();
115 			singleInstance = this;
116 		} catch (BluetoothStateException e) {
117 			throw e;
118 		} catch (IOException e) {
119 			DebugLog.fatal("initialization", e);
120 			throw new BluetoothStateException(e.getMessage());
121 		}
122 	}
123 
124 	public void destroy() {
125 		if (singleInstance != this) {
126 			throw new RuntimeException("Destroy invalid instance");
127 		}
128 		if (peerInitialized) {
129 			peerInitialized = false;
130 			uninitialize();
131 		}
132 		cancelLimitedDiscoverableTimer();
133 		singleInstance = null;
134 	}
135 
136 	private void initialized() throws BluetoothStateException {
137 		if (!peerInitialized) {
138 			throw new BluetoothStateException("Bluetooth system is unavailable");
139 		}
140 	}
141 
142 	/*
143 	 * (non-Javadoc)
144 	 * 
145 	 * @see com.intel.bluetooth.BluetoothStack#getFeatureSet()
146 	 */
147 	public int getFeatureSet() {
148 		return FEATURE_SERVICE_ATTRIBUTES | (windowsCE ? 0 : FEATURE_SET_DEVICE_SERVICE_CLASSES);
149 	}
150 
151 	// ---------------------- LocalDevice
152 
153 	private native int getDeviceClass(long address);
154 
155 	private native void setDiscoverable(boolean on) throws BluetoothStateException;
156 
157 	private native int getBluetoothRadioMode();
158 
159 	private native String getradioname(long address);
160 
161 	private native int getDeviceVersion(long address);
162 
163 	private native int getDeviceManufacturer(long address);
164 
165 	public String getLocalDeviceBluetoothAddress() {
166 		try {
167 			long socket = socket(false, false);
168 			bind(socket);
169 			localBluetoothAddress = getsockaddress(socket);
170 			String address = RemoteDeviceHelper.getBluetoothAddress(localBluetoothAddress);
171 			storesockopt(socket);
172 			close(socket);
173 			return address;
174 		} catch (IOException e) {
175 			DebugLog.error("get local bluetoothAddress", e);
176 			return "000000000000";
177 		}
178 	}
179 
180 	public String getLocalDeviceName() {
181 		if (localBluetoothAddress == 0) {
182 			getLocalDeviceBluetoothAddress();
183 		}
184 		return getradioname(localBluetoothAddress);
185 	}
186 
187 	public String getRemoteDeviceFriendlyName(long address) throws IOException {
188 		return getpeername(address);
189 	}
190 
191 	public DeviceClass getLocalDeviceClass() {
192 		return new DeviceClass(getDeviceClass(localBluetoothAddress));
193 	}
194 
195 	/*
196 	 * (non-Javadoc)
197 	 * 
198 	 * @see com.intel.bluetooth.BluetoothStack#setLocalDeviceServiceClasses(int)
199 	 */
200 	public void setLocalDeviceServiceClasses(int classOfDevice) {
201 		// Done in rfServerUpdateServiceRecord
202 	}
203 
204 	private void cancelLimitedDiscoverableTimer() {
205 		if (limitedDiscoverableTimer != null) {
206 			limitedDiscoverableTimer.interrupt();
207 			limitedDiscoverableTimer = null;
208 		}
209 	}
210 
211 	public boolean setLocalDeviceDiscoverable(int mode) throws BluetoothStateException {
212 		switch (mode) {
213 		case DiscoveryAgent.NOT_DISCOVERABLE:
214 			cancelLimitedDiscoverableTimer();
215 			DebugLog.debug("setDiscoverable(false)");
216 			setDiscoverable(false);
217 			return (DiscoveryAgent.NOT_DISCOVERABLE == getLocalDeviceDiscoverable());
218 		case DiscoveryAgent.GIAC:
219 			cancelLimitedDiscoverableTimer();
220 			DebugLog.debug("setDiscoverable(true)");
221 			setDiscoverable(true);
222 			return (DiscoveryAgent.GIAC == getLocalDeviceDiscoverable());
223 		case DiscoveryAgent.LIAC:
224 			cancelLimitedDiscoverableTimer();
225 			DebugLog.debug("setDiscoverable(LIAC)");
226 			setDiscoverable(true);
227 			if (!(DiscoveryAgent.GIAC == getLocalDeviceDiscoverable())) {
228 				return false;
229 			}
230 			// Timer to turn it off
231 			limitedDiscoverableTimer = Utils.schedule(60 * 1000, new Runnable() {
232 				public void run() {
233 					try {
234 						setDiscoverable(false);
235 					} catch (BluetoothStateException e) {
236 						DebugLog.debug("error setDiscoverable", e);
237 					} finally {
238 						limitedDiscoverableTimer = null;
239 					}
240 				}
241 			});
242 			return true;
243 		}
244 		return false;
245 	}
246 
247 	public boolean isLocalDevicePowerOn() {
248 		int mode = getBluetoothRadioMode();
249 		if (mode == BTH_MODE_POWER_OFF) {
250 			return false;
251 		}
252 		return ((mode == BTH_MODE_CONNECTABLE) || (mode == BTH_MODE_DISCOVERABLE));
253 	}
254 
255 	public int getLocalDeviceDiscoverable() {
256 		int mode = getBluetoothRadioMode();
257 		if (mode == BTH_MODE_DISCOVERABLE) {
258 			if (limitedDiscoverableTimer != null) {
259 				DebugLog.debug("Discoverable = LIAC");
260 				return DiscoveryAgent.LIAC;
261 			} else {
262 				DebugLog.debug("Discoverable = GIAC");
263 				return DiscoveryAgent.GIAC;
264 			}
265 		} else {
266 			DebugLog.debug("Discoverable = NOT_DISCOVERABLE");
267 			return DiscoveryAgent.NOT_DISCOVERABLE;
268 		}
269 	}
270 
271 	public String getLocalDeviceProperty(String property) {
272 		if ("bluetooth.connected.devices.max".equals(property)) {
273 			return "7";
274 		}
275 		if ("bluetooth.sd.trans.max".equals(property)) {
276 			return "7";
277 		}
278 		if ("bluetooth.connected.inquiry.scan".equals(property)) {
279 			return BlueCoveImpl.TRUE;
280 		}
281 		if ("bluetooth.connected.page.scan".equals(property)) {
282 			return BlueCoveImpl.TRUE;
283 		}
284 		if ("bluetooth.connected.inquiry".equals(property)) {
285 			return BlueCoveImpl.TRUE;
286 		}
287 		if ("bluetooth.connected.page".equals(property)) {
288 			return BlueCoveImpl.TRUE;
289 		}
290 
291 		if ("bluetooth.sd.attr.retrievable.max".equals(property)) {
292 			return String.valueOf(ATTR_RETRIEVABLE_MAX);
293 		}
294 		if ("bluetooth.master.switch".equals(property)) {
295 			return BlueCoveImpl.FALSE;
296 		}
297 		if ("bluetooth.l2cap.receiveMTU.max".equals(property)) {
298 			return "0";
299 		}
300 
301 		if ("bluecove.radio.version".equals(property)) {
302 			return String.valueOf(getDeviceVersion(localBluetoothAddress));
303 		}
304 		if ("bluecove.radio.manufacturer".equals(property)) {
305 			return String.valueOf(getDeviceManufacturer(localBluetoothAddress));
306 		}
307 		return null;
308 	}
309 
310 	/*
311 	 * (non-Javadoc)
312 	 * 
313 	 * @see com.intel.bluetooth.BluetoothStack#isCurrentThreadInterruptedCallback()
314 	 */
315 	public boolean isCurrentThreadInterruptedCallback() {
316 		return UtilsJavaSE.isCurrentThreadInterrupted();
317 	}
318 
319 	public boolean authenticateRemoteDevice(long address) throws IOException {
320 		return false;
321 	}
322 
323 	/*
324 	 * (non-Javadoc)
325 	 * 
326 	 * @see com.intel.bluetooth.BluetoothStack#authenticateRemoteDevice(long,
327 	 *      java.lang.String)
328 	 */
329 	public boolean authenticateRemoteDevice(long address, String passkey) throws IOException {
330 		return false;
331 	}
332 
333 	// ---------------------- Device Inquiry
334 
335 	public boolean startInquiry(int accessCode, DiscoveryListener listener) throws BluetoothStateException {
336 		initialized();
337 		if (currentDeviceDiscoveryListener != null) {
338 			throw new BluetoothStateException("Another inquiry already running");
339 		}
340 		currentDeviceDiscoveryListener = listener;
341 		return DeviceInquiryThread.startInquiry(this, this, accessCode, listener);
342 	}
343 
344 	/*
345 	 * cancel current inquiry (if any)
346 	 */
347 	private native boolean cancelInquiry();
348 
349 	public boolean cancelInquiry(DiscoveryListener listener) {
350 		if (currentDeviceDiscoveryListener != listener) {
351 			return false;
352 		}
353 		// no further deviceDiscovered() events will occur for this inquiry
354 		currentDeviceDiscoveryListener = null;
355 		return cancelInquiry();
356 	}
357 
358 	/*
359 	 * perform synchronous inquiry
360 	 */
361 	private native int runDeviceInquiryImpl(DeviceInquiryThread startedNotify, int accessCode, int duration,
362 			DiscoveryListener listener) throws BluetoothStateException;
363 
364 	public int runDeviceInquiry(DeviceInquiryThread startedNotify, int accessCode, DiscoveryListener listener)
365 			throws BluetoothStateException {
366 		try {
367 			deviceDiscoveryDevices = new Hashtable();
368 			int discType = runDeviceInquiryImpl(startedNotify, accessCode, DeviceInquiryThread
369 					.getConfigDeviceInquiryDuration(), listener);
370 			if (discType == DiscoveryListener.INQUIRY_COMPLETED) {
371 				for (Enumeration en = deviceDiscoveryDevices.keys(); en.hasMoreElements();) {
372 					RemoteDevice remoteDevice = (RemoteDevice) en.nextElement();
373 					DeviceClass deviceClass = (DeviceClass) deviceDiscoveryDevices.get(remoteDevice);
374 					listener.deviceDiscovered(remoteDevice, deviceClass);
375 					// If cancelInquiry has been called
376 					if (currentDeviceDiscoveryListener == null) {
377 						return DiscoveryListener.INQUIRY_TERMINATED;
378 					}
379 				}
380 			}
381 			return discType;
382 		} finally {
383 			deviceDiscoveryDevices = null;
384 			currentDeviceDiscoveryListener = null;
385 		}
386 	}
387 
388 	/**
389 	 * This is called when all device discoved by stack. To avoid problems with
390 	 * getpeername we will postpone the calls to User deviceDiscovered function
391 	 * until runDeviceInquiry is finished.
392 	 */
393 	public void deviceDiscoveredCallback(DiscoveryListener listener, long deviceAddr, int deviceClass,
394 			String deviceName, boolean paired) {
395 		RemoteDevice remoteDevice = RemoteDeviceHelper.createRemoteDevice(this, deviceAddr, deviceName, paired);
396 		if ((currentDeviceDiscoveryListener == null) || (deviceDiscoveryDevices == null)
397 				|| (currentDeviceDiscoveryListener != listener)) {
398 			return;
399 		}
400 		DeviceClass cod = new DeviceClass(deviceClass);
401 		DebugLog.debug("deviceDiscoveredCallback address", remoteDevice.getBluetoothAddress());
402 		DebugLog.debug("deviceDiscoveredCallback deviceClass", cod);
403 		deviceDiscoveryDevices.put(remoteDevice, cod);
404 	}
405 
406 	// ---------------------- Service search
407 
408 	/*
409 	 * perform synchronous service discovery
410 	 */
411 	public native int[] runSearchServices(UUID[] uuidSet, long address) throws SearchServicesException;
412 
413 	/*
414 	 * get service attributes
415 	 */
416 	public native byte[] getServiceAttributes(int[] attrIDs, long address, int handle) throws IOException;
417 
418 	public int searchServices(int[] attrSet, UUID[] uuidSet, RemoteDevice device, DiscoveryListener listener)
419 			throws BluetoothStateException {
420 		return SearchServicesThread.startSearchServices(this, this, attrSet, uuidSet, device, listener);
421 	}
422 
423 	public int runSearchServices(SearchServicesThread startedNotify, int[] attrSet, UUID[] uuidSet,
424 			RemoteDevice device, DiscoveryListener listener) throws BluetoothStateException {
425 		startedNotify.searchServicesStartedCallback();
426 		int[] handles;
427 		try {
428 			handles = runSearchServices(uuidSet, RemoteDeviceHelper.getAddress(device));
429 		} catch (SearchServicesDeviceNotReachableException e) {
430 			return DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE;
431 		} catch (SearchServicesTerminatedException e) {
432 			return DiscoveryListener.SERVICE_SEARCH_TERMINATED;
433 		} catch (SearchServicesException e) {
434 			return DiscoveryListener.SERVICE_SEARCH_ERROR;
435 		}
436 		if (handles == null) {
437 			return DiscoveryListener.SERVICE_SEARCH_ERROR;
438 		} else if (handles.length > 0) {
439 			ServiceRecord[] records = new ServiceRecordImpl[handles.length];
440 			int[] requiredAttrIDs = new int[] { BluetoothConsts.ServiceRecordHandle,
441 					BluetoothConsts.ServiceClassIDList, BluetoothConsts.ServiceRecordState, BluetoothConsts.ServiceID,
442 					BluetoothConsts.ProtocolDescriptorList };
443 			boolean hasError = false;
444 			for (int i = 0; i < handles.length; i++) {
445 				records[i] = new ServiceRecordImpl(this, device, handles[i]);
446 				try {
447 					records[i].populateRecord(requiredAttrIDs);
448 					if (attrSet != null) {
449 						records[i].populateRecord(attrSet);
450 					}
451 				} catch (Exception e) {
452 					DebugLog.debug("populateRecord error", e);
453 					hasError = true;
454 				}
455 				if (startedNotify.isTerminated()) {
456 					return DiscoveryListener.SERVICE_SEARCH_TERMINATED;
457 				}
458 			}
459 			listener.servicesDiscovered(startedNotify.getTransID(), records);
460 			if (hasError) {
461 				return DiscoveryListener.SERVICE_SEARCH_ERROR;
462 			} else {
463 				return DiscoveryListener.SERVICE_SEARCH_COMPLETED;
464 			}
465 		} else {
466 			return DiscoveryListener.SERVICE_SEARCH_NO_RECORDS;
467 		}
468 	}
469 
470 	public boolean cancelServiceSearch(int transID) {
471 		SearchServicesThread sst = SearchServicesThread.getServiceSearchThread(transID);
472 		if (sst != null) {
473 			return sst.setTerminated();
474 		} else {
475 			return false;
476 		}
477 	}
478 
479 	public boolean populateServicesRecordAttributeValues(ServiceRecordImpl serviceRecord, int[] attrIDs)
480 			throws IOException {
481 		if (attrIDs.length > ATTR_RETRIEVABLE_MAX) {
482 			throw new IllegalArgumentException();
483 		}
484 		/*
485 		 * retrieve SDP blob
486 		 */
487 		byte[] blob = getServiceAttributes(attrIDs, RemoteDeviceHelper.getAddress(serviceRecord.getHostDevice()),
488 				(int) serviceRecord.getHandle());
489 
490 		if (blob.length > 0) {
491 			try {
492 				boolean anyRetrived = false;
493 				DataElement element = (new SDPInputStream(new ByteArrayInputStream(blob))).readElement();
494 				for (Enumeration e = (Enumeration) element.getValue(); e.hasMoreElements();) {
495 					int attrID = (int) ((DataElement) e.nextElement()).getLong();
496 					serviceRecord.populateAttributeValue(attrID, (DataElement) e.nextElement());
497 					if (!anyRetrived) {
498 						for (int i = 0; i < attrIDs.length; i++) {
499 							if (attrIDs[i] == attrID) {
500 								anyRetrived = true;
501 								break;
502 							}
503 						}
504 					}
505 				}
506 				return anyRetrived;
507 			} catch (IOException e) {
508 				throw e;
509 			} catch (Throwable e) {
510 				throw new IOException();
511 			}
512 		} else {
513 			return false;
514 		}
515 	}
516 
517 	/*
518 	 * socket operations
519 	 */
520 	private native long socket(boolean authenticate, boolean encrypt) throws IOException;
521 
522 	private native long getsockaddress(long socket) throws IOException;
523 
524 	private native void storesockopt(long socket);
525 
526 	private native int getsockchannel(long socket) throws IOException;
527 
528 	private native void connect(long socket, long address, int channel) throws IOException;
529 
530 	private native void bind(long socket) throws IOException;
531 
532 	private native void listen(long socket) throws IOException;
533 
534 	private native long accept(long socket) throws IOException;
535 
536 	private native int recvAvailable(long socket) throws IOException;
537 
538 	private native int recv(long socket) throws IOException;
539 
540 	private native int recv(long socket, byte[] b, int off, int len) throws IOException;
541 
542 	private native void send(long socket, int b) throws IOException;
543 
544 	private native void send(long socket, byte[] b, int off, int len) throws IOException;
545 
546 	private native void close(long socket) throws IOException;
547 
548 	private native String getpeername(long address) throws IOException;
549 
550 	private native long getpeeraddress(long socket) throws IOException;
551 
552 	// ---------------------- Client RFCOMM connections
553 
554 	/*
555 	 * (non-Javadoc)
556 	 * 
557 	 * @see com.intel.bluetooth.BluetoothStack#l2OpenClientConnection(com.intel.bluetooth.BluetoothConnectionParams,
558 	 *      int, int)
559 	 */
560 	public long connectionRfOpenClientConnection(BluetoothConnectionParams params) throws IOException {
561 		long socket = socket(params.authenticate, params.encrypt);
562 		boolean success = false;
563 		try {
564 			connect(socket, params.address, params.channel);
565 			success = true;
566 		} finally {
567 			if (!success) {
568 				close(socket);
569 			}
570 		}
571 		return socket;
572 	}
573 
574 	public void connectionRfCloseClientConnection(long handle) throws IOException {
575 		close(handle);
576 	}
577 
578 	public long rfServerOpen(BluetoothConnectionNotifierParams params, ServiceRecordImpl serviceRecord)
579 			throws IOException {
580 		/*
581 		 * open socket
582 		 */
583 		long socket = socket(params.authenticate, params.encrypt);
584 		boolean success = false;
585 		try {
586 
587 			synchronized (this) {
588 				bind(socket);
589 			}
590 			listen(socket);
591 
592 			int channel = getsockchannel(socket);
593 			DebugLog.debug("service channel ", channel);
594 
595 			long serviceRecordHandle = socket;
596 			serviceRecord.populateRFCOMMAttributes(serviceRecordHandle, channel, params.uuid, params.name, params.obex);
597 
598 			/*
599 			 * register service
600 			 */
601 			serviceRecord.setHandle(registerService(serviceRecord.toByteArray(), serviceRecord.deviceServiceClasses));
602 
603 			success = true;
604 		} finally {
605 			if (!success) {
606 				try {
607 					close(socket);
608 				} catch (IOException e) {
609 					DebugLog.debug("close on failure", e);
610 				}
611 			}
612 		}
613 		return socket;
614 	}
615 
616 	public void rfServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException {
617 		try {
618 			/*
619 			 * close socket
620 			 */
621 			close(handle);
622 		} finally {
623 			/*
624 			 * unregister service
625 			 */
626 			unregisterService(serviceRecord.getHandle());
627 		}
628 	}
629 
630 	/*
631 	 * register service
632 	 */
633 	private native long registerService(byte[] record, int classOfDevice) throws ServiceRegistrationException;
634 
635 	/*
636 	 * unregister service
637 	 */
638 	private native void unregisterService(long handle) throws ServiceRegistrationException;
639 
640 	public long rfServerAcceptAndOpenRfServerConnection(long handle) throws IOException {
641 		return accept(handle);
642 	}
643 
644 	public void rfServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
645 			throws ServiceRegistrationException {
646 		unregisterService(serviceRecord.getHandle());
647 		byte[] blob;
648 		try {
649 			blob = serviceRecord.toByteArray();
650 		} catch (IOException e) {
651 			throw new ServiceRegistrationException(e.toString());
652 		}
653 		serviceRecord.setHandle(registerService(blob, serviceRecord.deviceServiceClasses));
654 		DebugLog.debug("new serviceRecord", serviceRecord);
655 	}
656 
657 	public void connectionRfCloseServerConnection(long handle) throws IOException {
658 		connectionRfCloseClientConnection(handle);
659 	}
660 
661 	public long getConnectionRfRemoteAddress(long handle) throws IOException {
662 		return getpeeraddress(handle);
663 	}
664 
665 	public int connectionRfRead(long handle) throws IOException {
666 		return recv(handle);
667 	}
668 
669 	public int connectionRfRead(long handle, byte[] b, int off, int len) throws IOException {
670 		return recv(handle, b, off, len);
671 	}
672 
673 	public int connectionRfReadAvailable(long handle) throws IOException {
674 		return recvAvailable(handle);
675 	}
676 
677 	public void connectionRfWrite(long handle, int b) throws IOException {
678 		send(handle, b);
679 	}
680 
681 	public void connectionRfWrite(long handle, byte[] b, int off, int len) throws IOException {
682 		send(handle, b, off, len);
683 	}
684 
685 	public void connectionRfFlush(long handle) throws IOException {
686 		// TODO are there any flush
687 	}
688 
689 	public int rfGetSecurityOpt(long handle, int expected) throws IOException {
690 		return expected;
691 	}
692 
693 	/*
694 	 * (non-Javadoc)
695 	 * 
696 	 * @see com.intel.bluetooth.BluetoothStack#l2Encrypt(long,long,boolean)
697 	 */
698 	public boolean rfEncrypt(long address, long handle, boolean on) throws IOException {
699 		return false;
700 	}
701 
702 	// ---------------------- Client and Server L2CAP connections
703 
704 	/*
705 	 * (non-Javadoc)
706 	 * 
707 	 * @see com.intel.bluetooth.BluetoothStack#l2OpenClientConnection(com.intel.bluetooth.BluetoothConnectionParams,
708 	 *      int, int)
709 	 */
710 	public long l2OpenClientConnection(BluetoothConnectionParams params, int receiveMTU, int transmitMTU)
711 			throws IOException {
712 		throw new NotSupportedIOException(getStackID());
713 	}
714 
715 	/*
716 	 * (non-Javadoc)
717 	 * 
718 	 * @see com.intel.bluetooth.BluetoothStack#l2CloseClientConnection(long)
719 	 */
720 	public void l2CloseClientConnection(long handle) throws IOException {
721 		throw new NotSupportedIOException(getStackID());
722 	}
723 
724 	/*
725 	 * (non-Javadoc)
726 	 * 
727 	 * @see com.intel.bluetooth.BluetoothStack#l2ServerOpen(com.intel.bluetooth.BluetoothConnectionNotifierParams,
728 	 *      int, int, com.intel.bluetooth.ServiceRecordImpl)
729 	 */
730 	public long l2ServerOpen(BluetoothConnectionNotifierParams params, int receiveMTU, int transmitMTU,
731 			ServiceRecordImpl serviceRecord) throws IOException {
732 		throw new NotSupportedIOException(getStackID());
733 	}
734 
735 	/*
736 	 * (non-Javadoc)
737 	 * 
738 	 * @see com.intel.bluetooth.BluetoothStack#l2ServerUpdateServiceRecord(long,
739 	 *      com.intel.bluetooth.ServiceRecordImpl, boolean)
740 	 */
741 	public void l2ServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
742 			throws ServiceRegistrationException {
743 		throw new ServiceRegistrationException("Not Supported on" + getStackID());
744 	}
745 
746 	/*
747 	 * (non-Javadoc)
748 	 * 
749 	 * @see com.intel.bluetooth.BluetoothStack#l2ServerAcceptAndOpenServerConnection(long)
750 	 */
751 	public long l2ServerAcceptAndOpenServerConnection(long handle) throws IOException {
752 		throw new NotSupportedIOException(getStackID());
753 	}
754 
755 	/*
756 	 * (non-Javadoc)
757 	 * 
758 	 * @see com.intel.bluetooth.BluetoothStack#l2CloseServerConnection(long)
759 	 */
760 	public void l2CloseServerConnection(long handle) throws IOException {
761 		throw new NotSupportedIOException(getStackID());
762 	}
763 
764 	/*
765 	 * (non-Javadoc)
766 	 * 
767 	 * @see com.intel.bluetooth.BluetoothStack#l2ServerClose(long,
768 	 *      com.intel.bluetooth.ServiceRecordImpl)
769 	 */
770 	public void l2ServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException {
771 		throw new NotSupportedIOException(getStackID());
772 	}
773 
774 	/*
775 	 * (non-Javadoc)
776 	 * 
777 	 * @see com.intel.bluetooth.BluetoothStack#l2GetSecurityOpt(long, int)
778 	 */
779 	public int l2GetSecurityOpt(long handle, int expected) throws IOException {
780 		throw new NotSupportedIOException(getStackID());
781 	}
782 
783 	/*
784 	 * (non-Javadoc)
785 	 * 
786 	 * @see com.intel.bluetooth.BluetoothStack#l2Ready(long)
787 	 */
788 	public boolean l2Ready(long handle) throws IOException {
789 		throw new NotSupportedIOException(getStackID());
790 	}
791 
792 	/*
793 	 * (non-Javadoc)
794 	 * 
795 	 * @see com.intel.bluetooth.BluetoothStack#l2receive(long, byte[])
796 	 */
797 	public int l2Receive(long handle, byte[] inBuf) throws IOException {
798 		throw new NotSupportedIOException(getStackID());
799 	}
800 
801 	/*
802 	 * (non-Javadoc)
803 	 * 
804 	 * @see com.intel.bluetooth.BluetoothStack#l2send(long, byte[])
805 	 */
806 	public void l2Send(long handle, byte[] data) throws IOException {
807 		throw new NotSupportedIOException(getStackID());
808 	}
809 
810 	/*
811 	 * (non-Javadoc)
812 	 * 
813 	 * @see com.intel.bluetooth.BluetoothStack#l2GetReceiveMTU(long)
814 	 */
815 	public int l2GetReceiveMTU(long handle) throws IOException {
816 		throw new NotSupportedIOException(getStackID());
817 	}
818 
819 	/*
820 	 * (non-Javadoc)
821 	 * 
822 	 * @see com.intel.bluetooth.BluetoothStack#l2GetTransmitMTU(long)
823 	 */
824 	public int l2GetTransmitMTU(long handle) throws IOException {
825 		throw new NotSupportedIOException(getStackID());
826 	}
827 
828 	/*
829 	 * (non-Javadoc)
830 	 * 
831 	 * @see com.intel.bluetooth.BluetoothStack#l2RemoteAddress(long)
832 	 */
833 	public long l2RemoteAddress(long handle) throws IOException {
834 		throw new NotSupportedIOException(getStackID());
835 	}
836 
837 	/*
838 	 * (non-Javadoc)
839 	 * 
840 	 * @see com.intel.bluetooth.BluetoothStack#l2Encrypt(long,long,boolean)
841 	 */
842 	public boolean l2Encrypt(long address, long handle, boolean on) throws IOException {
843 		throw new NotSupportedIOException(getStackID());
844 	}
845 }