/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2006-2009 Vlad Skarzhevskyy
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @version $Id$
*/
package com.intel.bluetooth;
import java.io.IOException;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.ServiceRegistrationException;
import javax.bluetooth.UUID;
class BluetoothStackBlueSoleil implements BluetoothStack, DeviceInquiryRunnable, SearchServicesRunnable {
private static BluetoothStackBlueSoleil singleInstance = null;
private boolean initialized = false;
private DiscoveryListener currentDeviceDiscoveryListener;
BluetoothStackBlueSoleil() {
}
public String getStackID() {
return BlueCoveImpl.STACK_BLUESOLEIL;
}
public String toString() {
return getStackID();
}
// ---------------------- Library initialization
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#isNativeCodeLoaded()
*/
public native boolean isNativeCodeLoaded();
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#requireNativeLibraries()
*/
public LibraryInformation[] requireNativeLibraries() {
return LibraryInformation.library(BlueCoveImpl.NATIVE_LIB_BLUESOLEIL);
}
public native int getLibraryVersion();
public native int detectBluetoothStack();
public native void enableNativeDebug(Class nativeDebugCallback, boolean on);
public native boolean initializeImpl();
public void initialize() throws BluetoothStateException {
if (singleInstance != null) {
throw new BluetoothStateException("Only one instance of " + getStackID() + " stack supported");
}
if (!initializeImpl()) {
DebugLog.fatal("Can't initialize BlueSoleil");
throw new BluetoothStateException("BlueSoleil BluetoothStack not found");
}
initialized = true;
singleInstance = this;
}
private native void uninitialize();
public void destroy() {
if (singleInstance != this) {
throw new RuntimeException("Destroy invalid instance");
}
if (initialized) {
uninitialize();
initialized = false;
DebugLog.debug("BlueSoleil destroyed");
}
singleInstance = null;
}
protected void finalize() {
destroy();
}
public native String getLocalDeviceBluetoothAddress();
public native String getLocalDeviceName();
public native int getDeviceClassImpl();
/**
* There are no functions in BlueSoleil stack.
*/
public DeviceClass getLocalDeviceClass() {
return new DeviceClass(getDeviceClassImpl());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#setLocalDeviceServiceClasses(int)
*/
public void setLocalDeviceServiceClasses(int classOfDevice) {
throw new NotSupportedRuntimeException(getStackID());
}
/**
* There are no functions to set BlueSoleil stack discoverable status.
*/
public boolean setLocalDeviceDiscoverable(int mode) throws BluetoothStateException {
return true;
}
native boolean isBlueSoleilStarted(int seconds);
private native boolean isBluetoothReady(int seconds);
/**
* There are no functions to find BlueSoleil discoverable status.
*/
public int getLocalDeviceDiscoverable() {
if (isBluetoothReady(2)) {
return DiscoveryAgent.GIAC;
} else {
return DiscoveryAgent.NOT_DISCOVERABLE;
}
}
public boolean isLocalDevicePowerOn() {
return isBluetoothReady(15);
}
native int getStackVersionInfo();
native int getDeviceVersion();
native int getDeviceManufacturer();
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#getFeatureSet()
*/
public int getFeatureSet() {
return 0;
}
public String getLocalDeviceProperty(String property) {
if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX.equals(property)) {
return "7";
}
if (BluetoothConsts.PROPERTY_BLUETOOTH_SD_TRANS_MAX.equals(property)) {
return "1";
}
if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY_SCAN.equals(property)) {
return BlueCoveImpl.TRUE;
}
if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE_SCAN.equals(property)) {
return BlueCoveImpl.TRUE;
}
if (BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY.equals(property)) {
return BlueCoveImpl.TRUE;
}
// service attributes are not supported.
if (BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX.equals(property)) {
return "0";
}
// if ("bluecove.radio.version".equals(property)) {
// return String.valueOf(getDeviceVersion());
// }
// if ("bluecove.radio.manufacturer".equals(property)) {
// return String.valueOf(getDeviceManufacturer());
// }
if ("bluecove.stack.version".equals(property)) {
return String.valueOf(getStackVersionInfo());
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#isCurrentThreadInterruptedCallback()
*/
public boolean isCurrentThreadInterruptedCallback() {
return UtilsJavaSE.isCurrentThreadInterrupted();
}
public RemoteDevice[] retrieveDevices(int option) {
return null;
}
public Boolean isRemoteDeviceTrusted(long address) {
return null;
}
public Boolean isRemoteDeviceAuthenticated(long address) {
return null;
}
public boolean authenticateRemoteDevice(long address) throws IOException {
return false;
}
public boolean authenticateRemoteDevice(long address, String passkey) throws IOException {
return false;
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#removeAuthenticationWithRemoteDevice (long)
*/
public void removeAuthenticationWithRemoteDevice(long address) throws IOException {
throw new NotSupportedIOException(getStackID());
}
// --- Device Inquiry
public boolean startInquiry(int accessCode, DiscoveryListener listener) throws BluetoothStateException {
if (currentDeviceDiscoveryListener != null) {
throw new BluetoothStateException("Another inquiry already running");
}
currentDeviceDiscoveryListener = listener;
return DeviceInquiryThread.startInquiry(this, this, accessCode, listener);
}
public int runDeviceInquiry(DeviceInquiryThread startedNotify, int accessCode, DiscoveryListener listener)
throws BluetoothStateException {
try {
startedNotify.deviceInquiryStartedCallback();
return runDeviceInquiryImpl(startedNotify, accessCode, listener);
} finally {
currentDeviceDiscoveryListener = null;
}
}
public native int runDeviceInquiryImpl(DeviceInquiryThread startedNotify, int accessCode, DiscoveryListener listener)
throws BluetoothStateException;
public void deviceDiscoveredCallback(DiscoveryListener listener, long deviceAddr, int deviceClass,
String deviceName, boolean paired) {
DebugLog.debug("deviceDiscoveredCallback", deviceName);
RemoteDevice remoteDevice = RemoteDeviceHelper.createRemoteDevice(this, deviceAddr, deviceName, paired);
if ((currentDeviceDiscoveryListener == null) || (currentDeviceDiscoveryListener != listener)) {
return;
}
listener.deviceDiscovered(remoteDevice, new DeviceClass(deviceClass));
}
public native boolean cancelInquirympl();
public boolean cancelInquiry(DiscoveryListener listener) {
if (currentDeviceDiscoveryListener != listener) {
return false;
}
// no further deviceDiscovered() events will occur for this inquiry
currentDeviceDiscoveryListener = null;
return cancelInquirympl();
}
public String getRemoteDeviceFriendlyName(long address) throws IOException {
// TODO Properly if possible
return null;
}
// --- Service search
public int searchServices(int[] attrSet, UUID[] uuidSet, RemoteDevice device, DiscoveryListener listener)
throws BluetoothStateException {
return SearchServicesThread.startSearchServices(this, this, attrSet, uuidSet, device, listener);
}
public boolean cancelServiceSearch(int transID) {
return false;
}
private native int runSearchServicesImpl(SearchServicesThread startedNotify, DiscoveryListener listener,
byte[] uuidValue, long address, RemoteDevice device) throws BluetoothStateException;
public int runSearchServices(SearchServicesThread startedNotify, int[] attrSet, UUID[] uuidSet,
RemoteDevice device, DiscoveryListener listener) throws BluetoothStateException {
startedNotify.searchServicesStartedCallback();
UUID uuid = null;
if ((uuidSet != null) && (uuidSet.length > 0)) {
uuid = uuidSet[uuidSet.length - 1];
}
return runSearchServicesImpl(startedNotify, listener, Utils.UUIDToByteArray(uuid), RemoteDeviceHelper
.getAddress(device), device);
}
/*
* This is all we have under the BlueSoleil. struct SPPEX_SERVICE_INFO { DWORD dwSize; DWORD dwSDAPRecordHanlde;
* UUID serviceClassUuid128; CHAR szServiceName[MAX_SERVICE_NAME_LENGTH]; UCHAR ucServiceChannel; }
*/
public void servicesFoundCallback(SearchServicesThread startedNotify, DiscoveryListener listener,
RemoteDevice device, String serviceName, byte[] uuidValue, int channel, long recordHanlde) {
ServiceRecordImpl record = new ServiceRecordImpl(this, device, 0);
UUID uuid = new UUID(Utils.UUIDByteArrayToString(uuidValue), false);
record.populateRFCOMMAttributes(recordHanlde, channel, uuid, serviceName, BluetoothConsts.obexUUIDs
.contains(uuid));
DebugLog.debug("servicesFoundCallback", record);
RemoteDevice listedDevice = RemoteDeviceHelper.createRemoteDevice(this, device);
RemoteDeviceHelper.setStackAttributes(this, listedDevice, "RFCOMM_channel" + channel, uuid);
ServiceRecord[] records = new ServiceRecordImpl[1];
records[0] = record;
listener.servicesDiscovered(startedNotify.getTransID(), records);
}
public boolean populateServicesRecordAttributeValues(ServiceRecordImpl serviceRecord, int[] attrIDs)
throws IOException {
return false;
}
// --- Client RFCOMM connections
private native long connectionRfOpenImpl(long address, byte[] uuidValue) throws IOException;
public long connectionRfOpenClientConnection(BluetoothConnectionParams params) throws IOException {
if (params.authenticate || params.encrypt) {
throw new IOException("authenticate not supported on BlueSoleil");
}
RemoteDevice listedDevice = RemoteDeviceHelper.getCashedDevice(this, params.address);
if (listedDevice == null) {
throw new IOException("Device not discovered");
}
UUID uuid = (UUID) RemoteDeviceHelper.getStackAttributes(this, listedDevice, "RFCOMM_channel" + params.channel);
if (uuid == null) {
throw new IOException("Device service not discovered");
}
DebugLog.debug("Connect to service UUID", uuid);
return connectionRfOpenImpl(params.address, Utils.UUIDToByteArray(uuid));
}
public native void connectionRfCloseClientConnection(long handle) throws IOException;
private native long rfServerOpenImpl(byte[] uuidValue, String name, boolean authenticate, boolean encrypt)
throws IOException;
private native int rfServerSCN(long handle) throws IOException;
public long rfServerOpen(BluetoothConnectionNotifierParams params, ServiceRecordImpl serviceRecord)
throws IOException {
if (params.authenticate || params.encrypt) {
throw new IOException("authenticate not supported on BlueSoleil");
}
byte[] uuidValue = Utils.UUIDToByteArray(params.uuid);
long handle = rfServerOpenImpl(uuidValue, params.name, params.authenticate, params.encrypt);
int channel = rfServerSCN(handle);
DebugLog.debug("serverSCN", channel);
int serviceRecordHandle = (int) handle;
serviceRecord.populateRFCOMMAttributes(serviceRecordHandle, channel, params.uuid, params.name, false);
return handle;
}
public void rfServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
throws ServiceRegistrationException {
if (!acceptAndOpen) {
throw new ServiceRegistrationException("Not Supported on " + getStackID());
}
}
public native long rfServerAcceptAndOpenRfServerConnection(long handle) throws IOException;
public void connectionRfCloseServerConnection(long handle) throws IOException {
connectionRfCloseClientConnection(handle);
}
public native void rfServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException;
public native long getConnectionRfRemoteAddress(long handle) throws IOException;
public native int connectionRfRead(long handle) throws IOException;
public native int connectionRfRead(long handle, byte[] b, int off, int len) throws IOException;
public native int connectionRfReadAvailable(long handle) throws IOException;
public native void connectionRfWrite(long handle, int b) throws IOException;
public native void connectionRfWrite(long handle, byte[] b, int off, int len) throws IOException;
public native void connectionRfFlush(long handle) throws IOException;
public int rfGetSecurityOpt(long handle, int expected) throws IOException {
return ServiceRecord.NOAUTHENTICATE_NOENCRYPT;
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2Encrypt(long,long,boolean)
*/
public boolean rfEncrypt(long address, long handle, boolean on) throws IOException {
return false;
}
// ---------------------- Client and Server L2CAP connections
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2OpenClientConnection(com.intel.bluetooth .BluetoothConnectionParams,
* int, int)
*/
public long l2OpenClientConnection(BluetoothConnectionParams params, int receiveMTU, int transmitMTU)
throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2CloseClientConnection(long)
*/
public void l2CloseClientConnection(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @seecom.intel.bluetooth.BluetoothStack#l2ServerOpen(com.intel.bluetooth. BluetoothConnectionNotifierParams, int,
* int, com.intel.bluetooth.ServiceRecordImpl)
*/
public long l2ServerOpen(BluetoothConnectionNotifierParams params, int receiveMTU, int transmitMTU,
ServiceRecordImpl serviceRecord) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2ServerUpdateServiceRecord(long, com.intel.bluetooth.ServiceRecordImpl,
* boolean)
*/
public void l2ServerUpdateServiceRecord(long handle, ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
throws ServiceRegistrationException {
throw new ServiceRegistrationException("Not Supported on" + getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2ServerAcceptAndOpenServerConnection (long)
*/
public long l2ServerAcceptAndOpenServerConnection(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2CloseServerConnection(long)
*/
public void l2CloseServerConnection(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2ServerClose(long, com.intel.bluetooth.ServiceRecordImpl)
*/
public void l2ServerClose(long handle, ServiceRecordImpl serviceRecord) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2GetSecurityOpt(long, int)
*/
public int l2GetSecurityOpt(long handle, int expected) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2Ready(long)
*/
public boolean l2Ready(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2receive(long, byte[])
*/
public int l2Receive(long handle, byte[] inBuf) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2send(long, byte[])
*/
public void l2Send(long handle, byte[] data, int transmitMTU) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2GetReceiveMTU(long)
*/
public int l2GetReceiveMTU(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2GetTransmitMTU(long)
*/
public int l2GetTransmitMTU(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2RemoteAddress(long)
*/
public long l2RemoteAddress(long handle) throws IOException {
throw new NotSupportedIOException(getStackID());
}
/*
* (non-Javadoc)
*
* @see com.intel.bluetooth.BluetoothStack#l2Encrypt(long,long,boolean)
*/
public boolean l2Encrypt(long address, long handle, boolean on) throws IOException {
throw new NotSupportedIOException(getStackID());
}
}