aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/CMakeLists.txt3
-rw-r--r--java/direct_bt/tinyb/Adapter.java417
-rw-r--r--java/direct_bt/tinyb/DBTEvent.java (renamed from java/tinyb/hci/HCIEvent.java)10
-rw-r--r--java/direct_bt/tinyb/DBTObject.java (renamed from java/tinyb/hci/HCIObject.java)31
-rw-r--r--java/direct_bt/tinyb/Device.java (renamed from java/tinyb/hci/HCIDevice.java)64
-rw-r--r--java/direct_bt/tinyb/GattCharacteristic.java (renamed from java/tinyb/hci/HCIGattCharacteristic.java)28
-rw-r--r--java/direct_bt/tinyb/GattDescriptor.java (renamed from java/tinyb/hci/HCIGattDescriptor.java)25
-rw-r--r--java/direct_bt/tinyb/GattService.java (renamed from java/tinyb/hci/HCIGattService.java)30
-rw-r--r--java/direct_bt/tinyb/Manager.java (renamed from java/tinyb/hci/HCIManager.java)48
-rw-r--r--java/direct_bt/tinyb/NativeDownlink.java87
-rw-r--r--java/jni/BluetoothUtils.cxx53
-rw-r--r--java/jni/CMakeLists.txt38
-rw-r--r--java/jni/HCIManager.cxx30
-rw-r--r--java/jni/HCIObject.cxx34
-rw-r--r--java/jni/JNIMem.cxx31
-rw-r--r--java/jni/JNIMem.hpp28
-rw-r--r--java/jni/direct_bt/CMakeLists.txt53
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx259
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx78
-rw-r--r--java/jni/direct_bt/DBTEvent.cxx (renamed from java/jni/HCIEvent.cxx)20
-rw-r--r--java/jni/direct_bt/DBTGattCharacteristic.cxx (renamed from java/jni/HCIGattCharacteristic.cxx)6
-rw-r--r--java/jni/direct_bt/DBTGattDescriptor.cxx (renamed from java/jni/HCIDevice.cxx)6
-rw-r--r--java/jni/direct_bt/DBTGattService.cxx (renamed from java/jni/HCIGattService.cxx)6
-rw-r--r--java/jni/direct_bt/DBTManager.cxx106
-rw-r--r--java/jni/direct_bt/DBTNativeDownlink.cxx58
-rw-r--r--java/jni/direct_bt/DBTObject.cxx (renamed from java/jni/HCIAdapter.cxx)6
-rw-r--r--java/jni/direct_bt/helper_dbt.cxx65
-rw-r--r--java/jni/direct_bt/helper_dbt.hpp113
-rw-r--r--java/jni/helper_base.cxx27
-rw-r--r--java/jni/helper_base.hpp68
-rw-r--r--java/jni/tinyb/CMakeLists.txt54
-rw-r--r--java/jni/tinyb/DBusAdapter.cxx (renamed from java/jni/DBusAdapter.cxx)0
-rw-r--r--java/jni/tinyb/DBusDevice.cxx (renamed from java/jni/DBusDevice.cxx)0
-rw-r--r--java/jni/tinyb/DBusEvent.cxx (renamed from java/jni/DBusEvent.cxx)0
-rw-r--r--java/jni/tinyb/DBusGattCharacteristic.cxx (renamed from java/jni/DBusGattCharacteristic.cxx)0
-rw-r--r--java/jni/tinyb/DBusGattDescriptor.cxx (renamed from java/jni/DBusGattDescriptor.cxx)0
-rw-r--r--java/jni/tinyb/DBusGattService.cxx (renamed from java/jni/DBusGattService.cxx)0
-rw-r--r--java/jni/tinyb/DBusManager.cxx (renamed from java/jni/DBusManager.cxx)0
-rw-r--r--java/jni/tinyb/DBusObject.cxx (renamed from java/jni/DBusObject.cxx)0
-rw-r--r--java/jni/tinyb/helper_tinyb.cxx (renamed from java/jni/helper_tinyb.cxx)36
-rw-r--r--java/jni/tinyb/helper_tinyb.hpp (renamed from java/jni/helper_tinyb.hpp)12
-rw-r--r--java/org/tinyb/BluetoothAdapter.java6
-rw-r--r--java/org/tinyb/BluetoothDeviceDiscoveryListener.java42
-rw-r--r--java/org/tinyb/BluetoothFactory.java10
-rw-r--r--java/org/tinyb/BluetoothManager.java9
-rw-r--r--java/org/tinyb/BluetoothUtils.java (renamed from java/jni/HCIGattDescriptor.cxx)16
-rw-r--r--java/tinyb/dbus/DBusAdapter.java6
-rw-r--r--java/tinyb/dbus/DBusManager.java5
-rw-r--r--java/tinyb/hci/HCIAdapter.java199
49 files changed, 1754 insertions, 469 deletions
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
index 1f3b1771..ba7c017b 100644
--- a/java/CMakeLists.txt
+++ b/java/CMakeLists.txt
@@ -27,4 +27,5 @@ add_custom_command (TARGET tinybjar
set(JNI_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/tinybjar.dir/jni")
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/tinyb2.jar DESTINATION ${CMAKE_INSTALL_LIBDIR}/../lib/java)
-add_subdirectory (jni)
+add_subdirectory (jni/direct_bt)
+add_subdirectory (jni/tinyb)
diff --git a/java/direct_bt/tinyb/Adapter.java b/java/direct_bt/tinyb/Adapter.java
new file mode 100644
index 00000000..b953c318
--- /dev/null
+++ b/java/direct_bt/tinyb/Adapter.java
@@ -0,0 +1,417 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package direct_bt.tinyb;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.tinyb.BluetoothAdapter;
+import org.tinyb.BluetoothDevice;
+import org.tinyb.BluetoothException;
+import org.tinyb.BluetoothManager;
+import org.tinyb.BluetoothNotification;
+import org.tinyb.BluetoothType;
+import org.tinyb.BluetoothDeviceDiscoveryListener;
+import org.tinyb.TransportType;
+
+public class Adapter extends DBTObject implements BluetoothAdapter
+{
+ private final String address;
+ private final String name;
+ private final DiscoveryThread discoveryThread;
+
+ /* pp */ Adapter(final long nativeInstance, final String address, final String name)
+ {
+ super(nativeInstance, compHash(address, name));
+ this.address = address;
+ this.name = name;
+ this.discoveryThread = new DiscoveryThread();
+ this.discoveryThread.start(null);
+ initImpl(this.discoveryThread.deviceDiscoveryListener);
+ }
+
+ @Override
+ public synchronized void close() {
+ discoveryThread.stop();
+ super.close();
+ }
+
+ @Override
+ public boolean equals(final Object obj)
+ {
+ if (obj == null || !(obj instanceof Device)) {
+ return false;
+ }
+ final Adapter other = (Adapter)obj;
+ return address.equals(other.address) && name.equals(other.name);
+ }
+
+ @Override
+ public String getAddress() { return address; }
+
+ @Override
+ public String getName() { return name; }
+
+ public String getInterfaceName() {
+ throw new UnsupportedOperationException(); // FIXME
+ }
+
+ @Override
+ public BluetoothType getBluetoothType() { return class_type(); }
+
+ static BluetoothType class_type() { return BluetoothType.ADAPTER; }
+
+ @Override
+ public final BluetoothAdapter clone()
+ { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
+ public BluetoothDevice find(final String name, final String address, final long timeoutMS) {
+ final BluetoothManager manager = Manager.getBluetoothManager();
+ return (BluetoothDevice) manager.find(BluetoothType.DEVICE, name, address, this, timeoutMS);
+ }
+
+ @Override
+ public BluetoothDevice find(final String name, final String address) {
+ return find(name, address, 0);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder out = new StringBuilder();
+ out.append("Adapter[").append(getAddress()).append(", '").append(getName()).append("', id=").append("]");
+ synchronized(discoveryThread.discoveredDevicesLock) {
+ final int count = discoveryThread.discoveredDevices.size();
+ if( count > 0 ) {
+ out.append("\n");
+ for(final Iterator<BluetoothDevice> iter=discoveryThread.discoveredDevices.iterator(); iter.hasNext(); ) {
+ final BluetoothDevice device = iter.next();
+ out.append(" ").append(device.toString()).append("\n");
+ }
+ }
+ }
+ return out.toString();
+ }
+
+ /* property accessors: */
+
+ @Override
+ public String getAlias() { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
+ public void setAlias(final String value) { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
+ public long getBluetoothClass() { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
+ public native boolean getPowered();
+
+ @Override
+ public native void enablePoweredNotifications(BluetoothNotification<Boolean> callback);
+
+ @Override
+ public native void disablePoweredNotifications();
+
+ @Override
+ public native void setPowered(boolean value);
+
+ @Override
+ public native boolean getDiscoverable();
+
+ @Override
+ public native void enableDiscoverableNotifications(BluetoothNotification<Boolean> callback);
+
+ @Override
+ public native void disableDiscoverableNotifications();
+
+ @Override
+ public native void setDiscoverable(boolean value);
+
+ @Override
+ public native long getDiscoverableTimeout();
+
+ @Override
+ public native void setDiscoverableTimout(long value);
+
+ @Override
+ public native BluetoothDevice connectDevice(String address, String addressType);
+
+ @Override
+ public native boolean getPairable();
+
+ @Override
+ public native void enablePairableNotifications(BluetoothNotification<Boolean> callback);
+
+ @Override
+ public native void disablePairableNotifications();
+
+ @Override
+ public native void setPairable(boolean value);
+
+ @Override
+ public native long getPairableTimeout();
+
+ @Override
+ public native void setPairableTimeout(long value);
+
+ @Override
+ public native String[] getUUIDs();
+
+ @Override
+ public native String getModalias();
+
+ /* internal */
+
+ private native void initImpl(final BluetoothDeviceDiscoveryListener l);
+
+ @Override
+ protected native void deleteImpl();
+
+ /* discovery */
+
+ @Override
+ public boolean startDiscovery() throws BluetoothException {
+ return discoveryThread.doDiscovery(true);
+ }
+ private native boolean startDiscoveryImpl() throws BluetoothException;
+
+ @Override
+ public boolean stopDiscovery() throws BluetoothException {
+ return discoveryThread.doDiscovery(false);
+ }
+ private native boolean stopDiscoveryImpl() throws BluetoothException;
+
+ @Override
+ public List<BluetoothDevice> getDevices() {
+ return discoveryThread.getDiscoveredDevices();
+ }
+
+ @Override
+ public int removeDevices() throws BluetoothException {
+ final int cj = discoveryThread.removeDiscoveredDevices();
+ final int cn = removeDevicesImpl();
+ if( cj != cn ) {
+ throw new InternalError("Inconsistent discovered device count: Native "+cn+", callback "+cj);
+ }
+ return cn;
+ }
+ private native int removeDevicesImpl() throws BluetoothException;
+
+ @Override
+ public boolean getDiscovering() { return discoveryThread.running && discoveryThread.doDiscovery; }
+
+ @Override
+ public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener l) {
+ discoveryThread.setDeviceDiscoveryListener(l);
+ }
+
+ @Override
+ public void enableDiscoveringNotifications(final BluetoothNotification<Boolean> callback) {
+ discoveryThread.setDiscoveringNotificationCallback(callback);
+ }
+
+ @Override
+ public void disableDiscoveringNotifications() {
+ discoveryThread.setDiscoveringNotificationCallback(null);
+ }
+
+ @Override
+ public void setDiscoveryFilter(final List<UUID> uuids, final int rssi, final int pathloss, final TransportType transportType) {
+ final List<String> uuidsFmt = new ArrayList<>(uuids.size());
+ for (final UUID uuid : uuids) {
+ uuidsFmt.add(uuid.toString());
+ }
+ setDiscoveryFilter(uuidsFmt, rssi, pathloss, transportType.ordinal());
+ }
+
+ public void setRssiDiscoveryFilter(final int rssi) {
+ setDiscoveryFilter(Collections.EMPTY_LIST, rssi, 0, TransportType.AUTO);
+ }
+
+ private native void setDiscoveryFilter(List<String> uuids, int rssi, int pathloss, int transportType);
+
+ private native int discoverAnyDeviceImpl(final int timeoutMS) throws BluetoothException;
+ // std::vector<std::shared_ptr<direct_bt::HCIDevice>> discoveredDevices = adapter.getDiscoveredDevices();
+ private native List<BluetoothDevice> getDiscoveredDevicesImpl();
+
+ private class DiscoveryThread implements Runnable {
+ private int instanceID=-1;
+
+ private volatile boolean running = false;
+ private volatile boolean doDiscovery = false;
+ private final Object stateLock = new Object();
+ private volatile BluetoothDeviceDiscoveryListener userDeviceDiscoveryListener = null;
+ private volatile BluetoothNotification<Boolean> discoveringNotificationCB = null;
+ private List<BluetoothDevice> discoveredDevices = new ArrayList<BluetoothDevice>();
+ private final Object discoveredDevicesLock = new Object();
+
+ private final BluetoothDeviceDiscoveryListener deviceDiscoveryListener = new BluetoothDeviceDiscoveryListener() {
+ @Override
+ public void deviceAdded(final BluetoothAdapter a, final BluetoothDevice device) {
+ final BluetoothDeviceDiscoveryListener l = userDeviceDiscoveryListener;
+ System.err.println("DBTAdapter.DeviceDiscoveryListener.added: "+device+" on "+a);
+ synchronized(discoveredDevicesLock) {
+ discoveredDevices.add(device);
+ }
+ if( null != l ) {
+ l.deviceAdded(a, device);
+ }
+ }
+
+ @Override
+ public void deviceUpdated(final BluetoothAdapter a, final BluetoothDevice device) {
+ System.err.println("DBTAdapter.DeviceDiscoveryListener.updated: "+device+" on "+a);
+ // nop on discoveredDevices
+ userDeviceDiscoveryListener.deviceUpdated(a, device);
+ }
+
+ @Override
+ public void deviceRemoved(final BluetoothAdapter a, final BluetoothDevice device) {
+ final BluetoothDeviceDiscoveryListener l = userDeviceDiscoveryListener;
+ System.err.println("DBTAdapter.DeviceDiscoveryListener.removed: "+device+" on "+a);
+ synchronized(discoveredDevicesLock) {
+ discoveredDevices.remove(device);
+ }
+ if( null != l ) {
+ l.deviceRemoved(a, device);
+ }
+ }
+ };
+
+ public void start(final ThreadGroup tg) {
+ synchronized( stateLock ) {
+ if ( !running ) {
+ instanceID = globThreadID.addAndGet(1);
+ final Thread t = new Thread(tg, this, "Adapter-"+instanceID); // Thread name aligned w/ 'Thread-#'
+ t.setDaemon(true);
+ t.start();
+ while( !running ) {
+ try {
+ stateLock.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener l) {
+ synchronized( stateLock ) {
+ userDeviceDiscoveryListener = l;
+ stateLock.notifyAll();
+ }
+ }
+ public void setDiscoveringNotificationCallback(final BluetoothNotification<Boolean> cb) {
+ synchronized( stateLock ) {
+ discoveringNotificationCB = cb;
+ stateLock.notifyAll();
+ }
+ }
+ public List<BluetoothDevice> getDiscoveredDevices() {
+ synchronized(discoveredDevicesLock) {
+ return new ArrayList<BluetoothDevice>(discoveredDevices);
+ }
+ }
+ public int removeDiscoveredDevices() {
+ synchronized(discoveredDevicesLock) {
+ final int n = discoveredDevices.size();
+ discoveredDevices = new ArrayList<BluetoothDevice>();
+ return n;
+ }
+ }
+ public boolean doDiscovery(final boolean v) {
+ synchronized( stateLock ) {
+ if( v == doDiscovery ) {
+ return v;
+ }
+ final BluetoothNotification<Boolean> cb = discoveringNotificationCB;
+ final boolean enable;
+ if( v ) {
+ enable = startDiscoveryImpl();
+ } else {
+ enable = false;
+ stopDiscoveryImpl();
+ }
+ doDiscovery = enable;
+ if( null != cb ) {
+ cb.run(enable);
+ }
+ stateLock.notifyAll();
+ return enable;
+ }
+ }
+ public void stop() {
+ synchronized( stateLock ) {
+ stopDiscoveryImpl();
+ running = false;
+ doDiscovery = false;
+ stateLock.notifyAll();
+ }
+ }
+
+ @Override
+ public void run() {
+ synchronized( stateLock ) {
+ running = true;
+ stateLock.notifyAll();
+ }
+ while (running) {
+ synchronized( stateLock ) {
+ while( running && !doDiscovery ) {
+ try {
+ stateLock.wait();
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if( !running ) {
+ break; // end loop and thread
+ }
+
+ try {
+ if( doDiscovery ) {
+ // will trigger all discovery callbacks!
+ discoverAnyDeviceImpl(discoverTimeoutMS);
+ }
+ } catch (final Exception e) {
+ System.err.println(e.toString());
+ e.printStackTrace();
+ doDiscovery = false;
+ }
+ } // loop
+
+ instanceID = -1;
+ }
+ }
+ private static AtomicInteger globThreadID = new AtomicInteger(0);
+ private static int discoverTimeoutMS = 100;
+}
diff --git a/java/tinyb/hci/HCIEvent.java b/java/direct_bt/tinyb/DBTEvent.java
index 4dc30ec3..66317ea9 100644
--- a/java/tinyb/hci/HCIEvent.java
+++ b/java/direct_bt/tinyb/DBTEvent.java
@@ -23,13 +23,13 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
import org.tinyb.BluetoothCallback;
import org.tinyb.BluetoothEvent;
import org.tinyb.BluetoothType;
-public class HCIEvent implements BluetoothEvent
+public class DBTEvent implements BluetoothEvent
{
private long nativeInstance;
@@ -45,11 +45,11 @@ public class HCIEvent implements BluetoothEvent
public native boolean hasCallback();
private native void init(BluetoothType type, String name, String identifier,
- HCIObject parent, BluetoothCallback cb, Object data);
+ DBTObject parent, BluetoothCallback cb, Object data);
private native void delete();
- public HCIEvent(final BluetoothType type, final String name, final String identifier,
- final HCIObject parent, final BluetoothCallback cb, final Object data)
+ public DBTEvent(final BluetoothType type, final String name, final String identifier,
+ final DBTObject parent, final BluetoothCallback cb, final Object data)
{
init(type, name, identifier, parent, cb, data);
}
diff --git a/java/tinyb/hci/HCIObject.java b/java/direct_bt/tinyb/DBTObject.java
index 85a903e5..93b10245 100644
--- a/java/tinyb/hci/HCIObject.java
+++ b/java/direct_bt/tinyb/DBTObject.java
@@ -23,28 +23,14 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
-import org.tinyb.BluetoothFactory;
import org.tinyb.BluetoothObject;
import org.tinyb.BluetoothType;
-public abstract class HCIObject implements BluetoothObject
+public abstract class DBTObject extends NativeDownlink implements BluetoothObject
{
private final int hashValue;
- private boolean isValid;
-
- static {
- try {
- System.loadLibrary(BluetoothFactory.JavaNativeLibBasename);
- } catch (final Throwable e) {
- System.err.println("Failed to load native library "+BluetoothFactory.JavaNativeLibBasename);
- e.printStackTrace();
- throw e; // fwd exception - end here
- }
- }
-
- static BluetoothType class_type() { return BluetoothType.NONE; }
/* pp */ static int compHash(final String a, final String b) {
// 31 * x == (x << 5) - x
@@ -52,12 +38,14 @@ public abstract class HCIObject implements BluetoothObject
return ((hash << 5) - hash) + b.hashCode();
}
- protected HCIObject(final int hashValue)
+ protected DBTObject(final long nativeInstance, final int hashValue)
{
+ super(nativeInstance);
this.hashValue = hashValue;
- isValid = true;
}
+ static BluetoothType class_type() { return BluetoothType.NONE; }
+
@Override
public abstract boolean equals(final Object obj);
@@ -74,18 +62,11 @@ public abstract class HCIObject implements BluetoothObject
@Override
public synchronized void close() {
- if (!isValid) {
- return;
- }
- isValid = false;
delete();
}
- @Override
- public native BluetoothType getBluetoothType();
@Override
public BluetoothObject clone()
{ throw new UnsupportedOperationException(); } // FIXME
- private native void delete();
}
diff --git a/java/tinyb/hci/HCIDevice.java b/java/direct_bt/tinyb/Device.java
index b9a41a53..f3a90d6b 100644
--- a/java/tinyb/hci/HCIDevice.java
+++ b/java/direct_bt/tinyb/Device.java
@@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
import java.util.List;
import java.util.Map;
@@ -34,30 +34,34 @@ import org.tinyb.BluetoothGattService;
import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothNotification;
import org.tinyb.BluetoothType;
+import org.tinyb.BluetoothUtils;
-import tinyb.dbus.DBusObject;
-
-public class HCIDevice extends HCIObject implements BluetoothDevice
+public class Device extends DBTObject implements BluetoothDevice
{
- private final HCIAdapter adapter;
+ private final Adapter adapter;
private final String address;
private final String name;
+ private final long ts_creation;
+ long ts_update;
- /* pp */ HCIDevice(final HCIAdapter adptr, final String address, final String name)
+ /* pp */ Device(final long nativeInstance, final Adapter adptr, final String address, final String name, final long ts_creation)
{
- super(compHash(address, name));
+ super(nativeInstance, compHash(address, name));
this.adapter = adptr;
this.address = address;
this.name = name;
+ this.ts_creation = ts_creation;
+ ts_update = ts_creation;
+ initImpl();
}
@Override
public boolean equals(final Object obj)
{
- if (obj == null || !(obj instanceof HCIDevice)) {
+ if (obj == null || !(obj instanceof Device)) {
return false;
}
- final HCIDevice other = (HCIDevice)obj;
+ final Device other = (Device)obj;
return address.equals(other.address) && name.equals(other.name);
}
@@ -70,14 +74,15 @@ public class HCIDevice extends HCIObject implements BluetoothDevice
@Override
public BluetoothType getBluetoothType() { return class_type(); }
- @Override
- public native HCIDevice clone();
-
static BluetoothType class_type() { return BluetoothType.DEVICE; }
@Override
+ public final BluetoothDevice clone()
+ { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
public BluetoothGattService find(final String UUID, final long timeoutMS) {
- final BluetoothManager manager = HCIManager.getBluetoothManager();
+ final BluetoothManager manager = Manager.getBluetoothManager();
return (BluetoothGattService) manager.find(BluetoothType.GATT_SERVICE,
null, UUID, this, timeoutMS);
}
@@ -87,6 +92,34 @@ public class HCIDevice extends HCIObject implements BluetoothDevice
return find(UUID, 0);
}
+ @Override
+ public String toString() {
+ final StringBuilder out = new StringBuilder();
+ final long t0 = BluetoothUtils.getCurrentMilliseconds();
+ // std::string msdstr = nullptr != msd ? msd->toString() : "MSD[null]";
+ final String msdstr = "MSD[null]";
+ out.append("Device[").append(getAddress()).append(", '").append(getName())
+ .append("', age ").append(t0-ts_creation).append(" ms, lup ").append(t0-ts_update).append(" ms, rssi ").append(getRSSI())
+ .append(", tx-power ").append(getTxPower()).append(", ").append(msdstr).append("]");
+ /**
+ if(services.size() > 0 ) {
+ out.append("\n");
+ final int i=0;
+ for(final auto it = services.begin(); it != services.end(); it++, i++) {
+ if( 0 < i ) {
+ out.append("\n");
+ }
+ std::shared_ptr<uuid_t> p = *it;
+ out.append(" ").append(p->toUUID128String()).append(", ").append(std::to_string(static_cast<int>(p->getTypeSize()))).append(" bytes");
+ }
+ } */
+ return out.toString();
+ }
+
+ /* internal */
+
+ private native void initImpl();
+
/* D-Bus method calls: */
@Override
@@ -194,7 +227,7 @@ public class HCIDevice extends HCIObject implements BluetoothDevice
public native String getModalias();
@Override
- public native HCIAdapter getAdapter();
+ public native Adapter getAdapter();
@Override
public native Map<Short, byte[]> getManufacturerData();
@@ -227,5 +260,6 @@ public class HCIDevice extends HCIObject implements BluetoothDevice
@Override
public native void disableServicesResolvedNotifications();
- private native void delete();
+ @Override
+ protected native void deleteImpl();
}
diff --git a/java/tinyb/hci/HCIGattCharacteristic.java b/java/direct_bt/tinyb/GattCharacteristic.java
index a2047e1e..801dac33 100644
--- a/java/tinyb/hci/HCIGattCharacteristic.java
+++ b/java/direct_bt/tinyb/GattCharacteristic.java
@@ -23,10 +23,11 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
import java.util.List;
+import org.tinyb.BluetoothDevice;
import org.tinyb.BluetoothException;
import org.tinyb.BluetoothGattCharacteristic;
import org.tinyb.BluetoothGattDescriptor;
@@ -35,23 +36,23 @@ import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothNotification;
import org.tinyb.BluetoothType;
-public class HCIGattCharacteristic extends HCIObject implements BluetoothGattCharacteristic
+public class GattCharacteristic extends DBTObject implements BluetoothGattCharacteristic
{
private final String uuid;
- /* pp */ HCIGattCharacteristic(final String uuid)
+ /* pp */ GattCharacteristic(final long nativeInstance, final String uuid)
{
- super(uuid.hashCode());
+ super(nativeInstance, uuid.hashCode());
this.uuid = uuid;
}
@Override
public boolean equals(final Object obj)
{
- if (obj == null || !(obj instanceof HCIGattCharacteristic)) {
+ if (obj == null || !(obj instanceof GattCharacteristic)) {
return false;
}
- final HCIGattCharacteristic other = (HCIGattCharacteristic)obj;
+ final GattCharacteristic other = (GattCharacteristic)obj;
return uuid.equals(other.uuid);
}
@@ -59,15 +60,17 @@ public class HCIGattCharacteristic extends HCIObject implements BluetoothGattCha
public String getUUID() { return uuid; }
@Override
- public native BluetoothType getBluetoothType();
- @Override
- public native HCIGattCharacteristic clone();
+ public BluetoothType getBluetoothType() { return class_type(); }
static BluetoothType class_type() { return BluetoothType.GATT_CHARACTERISTIC; }
@Override
+ public final GattCharacteristic clone()
+ { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
public BluetoothGattDescriptor find(final String UUID, final long timeoutMS) {
- final BluetoothManager manager = HCIManager.getBluetoothManager();
+ final BluetoothManager manager = Manager.getBluetoothManager();
return (BluetoothGattDescriptor) manager.find(BluetoothType.GATT_DESCRIPTOR,
null, UUID, this, timeoutMS);
}
@@ -108,8 +111,9 @@ public class HCIGattCharacteristic extends HCIObject implements BluetoothGattCha
@Override
public native List<BluetoothGattDescriptor> getDescriptors();
- private native void init(HCIGattCharacteristic obj);
+ private native void init(GattCharacteristic obj);
- private native void delete();
+ @Override
+ protected native void deleteImpl();
}
diff --git a/java/tinyb/hci/HCIGattDescriptor.java b/java/direct_bt/tinyb/GattDescriptor.java
index b04816a4..5b0d2898 100644
--- a/java/tinyb/hci/HCIGattDescriptor.java
+++ b/java/direct_bt/tinyb/GattDescriptor.java
@@ -23,30 +23,30 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
import org.tinyb.BluetoothException;
import org.tinyb.BluetoothGattDescriptor;
import org.tinyb.BluetoothNotification;
import org.tinyb.BluetoothType;
-public class HCIGattDescriptor extends HCIObject implements BluetoothGattDescriptor
+public class GattDescriptor extends DBTObject implements BluetoothGattDescriptor
{
private final String uuid;
- /* pp */ HCIGattDescriptor(final String uuid)
+ /* pp */ GattDescriptor(final long nativeInstance, final String uuid)
{
- super(uuid.hashCode());
+ super(nativeInstance, uuid.hashCode());
this.uuid = uuid;
}
@Override
public boolean equals(final Object obj)
{
- if (obj == null || !(obj instanceof HCIGattDescriptor)) {
+ if (obj == null || !(obj instanceof GattDescriptor)) {
return false;
}
- final HCIGattDescriptor other = (HCIGattDescriptor)obj;
+ final GattDescriptor other = (GattDescriptor)obj;
return uuid.equals(other.uuid);
}
@@ -54,12 +54,14 @@ public class HCIGattDescriptor extends HCIObject implements BluetoothGattDescrip
public String getUUID() { return uuid; }
@Override
- public native BluetoothType getBluetoothType();
- @Override
- public native BluetoothGattDescriptor clone();
+ public BluetoothType getBluetoothType() { return class_type(); }
static BluetoothType class_type() { return BluetoothType.GATT_DESCRIPTOR; }
+ @Override
+ public final GattDescriptor clone()
+ { throw new UnsupportedOperationException(); } // FIXME
+
/* D-Bus method calls: */
@Override
@@ -77,10 +79,11 @@ public class HCIGattDescriptor extends HCIObject implements BluetoothGattDescrip
/* D-Bus property accessors: */
@Override
- public native HCIGattCharacteristic getCharacteristic();
+ public native GattCharacteristic getCharacteristic();
@Override
public native byte[] getValue();
- private native void delete();
+ @Override
+ protected native void deleteImpl();
}
diff --git a/java/tinyb/hci/HCIGattService.java b/java/direct_bt/tinyb/GattService.java
index 584f68b3..8377c806 100644
--- a/java/tinyb/hci/HCIGattService.java
+++ b/java/direct_bt/tinyb/GattService.java
@@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
import java.util.List;
@@ -32,23 +32,23 @@ import org.tinyb.BluetoothGattService;
import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothType;
-public class HCIGattService extends HCIObject implements BluetoothGattService
+public class GattService extends DBTObject implements BluetoothGattService
{
private final String uuid;
- /* pp */ HCIGattService(final String uuid)
+ /* pp */ GattService(final long nativeInstance, final String uuid)
{
- super(uuid.hashCode());
+ super(nativeInstance, uuid.hashCode());
this.uuid = uuid;
}
@Override
public boolean equals(final Object obj)
{
- if (obj == null || !(obj instanceof HCIGattService)) {
+ if (obj == null || !(obj instanceof GattService)) {
return false;
}
- final HCIGattService other = (HCIGattService)obj;
+ final GattService other = (GattService)obj;
return uuid.equals(other.uuid);
}
@@ -56,17 +56,18 @@ public class HCIGattService extends HCIObject implements BluetoothGattService
public String getUUID() { return uuid; }
@Override
- public native BluetoothType getBluetoothType();
-
- @Override
- public native BluetoothGattService clone();
+ public BluetoothType getBluetoothType() { return class_type(); }
static BluetoothType class_type() { return BluetoothType.GATT_SERVICE; }
@Override
+ public final GattService clone()
+ { throw new UnsupportedOperationException(); } // FIXME
+
+ @Override
public BluetoothGattCharacteristic find(final String UUID, final long timeoutMS) {
- final BluetoothManager manager = HCIManager.getBluetoothManager();
- return (HCIGattCharacteristic) manager.find(BluetoothType.GATT_CHARACTERISTIC,
+ final BluetoothManager manager = Manager.getBluetoothManager();
+ return (GattCharacteristic) manager.find(BluetoothType.GATT_CHARACTERISTIC,
null, UUID, this, timeoutMS);
}
@@ -78,7 +79,7 @@ public class HCIGattService extends HCIObject implements BluetoothGattService
/* D-Bus property accessors: */
@Override
- public native HCIDevice getDevice();
+ public native Device getDevice();
@Override
public native boolean getPrimary();
@@ -86,5 +87,6 @@ public class HCIGattService extends HCIObject implements BluetoothGattService
@Override
public native List<BluetoothGattCharacteristic> getCharacteristics();
- private native void delete();
+ @Override
+ protected native void deleteImpl();
}
diff --git a/java/tinyb/hci/HCIManager.java b/java/direct_bt/tinyb/Manager.java
index 7afba39c..99ea2cce 100644
--- a/java/tinyb/hci/HCIManager.java
+++ b/java/direct_bt/tinyb/Manager.java
@@ -23,7 +23,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package tinyb.hci;
+package direct_bt.tinyb;
import java.util.ArrayList;
import java.util.List;
@@ -36,30 +36,31 @@ import org.tinyb.BluetoothObject;
import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothType;
-public class HCIManager implements BluetoothManager
+public class Manager implements BluetoothManager
{
- private static HCIManager inst;
+ private long nativeInstance;
+ private static Manager inst;
private final List<BluetoothAdapter> adapters = new ArrayList<BluetoothAdapter>();
- public native BluetoothType getBluetoothType();
+ public BluetoothType getBluetoothType() { return BluetoothType.NONE; }
- private HCIObject find(final int type, final String name, final String identifier, final BluetoothObject parent, final long milliseconds)
+ private DBTObject find(final int type, final String name, final String identifier, final BluetoothObject parent, final long milliseconds)
{ throw new UnsupportedOperationException(); } // FIXME
@Override
- public HCIObject find(final BluetoothType type, final String name, final String identifier, final BluetoothObject parent, final long timeoutMS) {
+ public DBTObject find(final BluetoothType type, final String name, final String identifier, final BluetoothObject parent, final long timeoutMS) {
return find(type.ordinal(), name, identifier, parent, timeoutMS);
}
@Override
- public HCIObject find(final BluetoothType type, final String name, final String identifier, final BluetoothObject parent) {
+ public DBTObject find(final BluetoothType type, final String name, final String identifier, final BluetoothObject parent) {
return find(type, name, identifier, parent, 0);
}
@SuppressWarnings("unchecked")
@Override
public <T extends BluetoothObject> T find(final String name, final String identifier, final BluetoothObject parent, final long timeoutMS) {
- return (T) find(HCIObject.class_type().ordinal(), name, identifier, parent, timeoutMS);
+ return (T) find(DBTObject.class_type().ordinal(), name, identifier, parent, timeoutMS);
}
@SuppressWarnings("unchecked")
@@ -108,12 +109,22 @@ public class HCIManager implements BluetoothManager
@Override
public boolean getDiscovering() throws BluetoothException { return getDefaultAdapter().getDiscovering(); }
- private native HCIAdapter init() throws BluetoothException;
- private native void delete();
+ /**
+ * Returns an opened default adapter instance!
+ * @throws BluetoothException in case adapter is invalid or could not have been opened.
+ */
+ private native Adapter getDefaultAdapterImpl() throws BluetoothException;
- private HCIManager()
+ private native void initImpl() throws BluetoothException;
+ private native void deleteImpl();
+ private Manager()
{
- adapters.add(init());
+ initImpl();
+ try {
+ adapters.add(getDefaultAdapterImpl());
+ } catch (final BluetoothException be) {
+ be.printStackTrace();
+ }
}
/** Returns an instance of BluetoothManager, to be used instead of constructor.
@@ -123,15 +134,20 @@ public class HCIManager implements BluetoothManager
{
if (inst == null)
{
- inst = new HCIManager();
+ inst = new Manager();
}
return inst;
}
@Override
- protected void finalize()
- {
+ protected void finalize() {
+ shutdown();
+ }
+
+ @Override
+ public void shutdown() {
adapters.clear();
- delete();
+ deleteImpl();
}
+
}
diff --git a/java/direct_bt/tinyb/NativeDownlink.java b/java/direct_bt/tinyb/NativeDownlink.java
new file mode 100644
index 00000000..72e4e137
--- /dev/null
+++ b/java/direct_bt/tinyb/NativeDownlink.java
@@ -0,0 +1,87 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package direct_bt.tinyb;
+
+import org.tinyb.BluetoothFactory;
+
+public abstract class NativeDownlink
+{
+ protected long nativeInstance;
+ private boolean isValid;
+
+ static {
+ try {
+ System.loadLibrary(BluetoothFactory.JavaNativeLibBasename);
+ } catch (final Throwable e) {
+ System.err.println("Failed to load native library "+BluetoothFactory.JavaNativeLibBasename);
+ e.printStackTrace();
+ throw e; // fwd exception - end here
+ }
+ }
+
+ protected NativeDownlink(final long nativeInstance)
+ {
+ this.nativeInstance = nativeInstance;
+ isValid = true;
+ initNativeJavaObject(nativeInstance);
+ }
+
+ @Override
+ protected void finalize()
+ {
+ delete();
+ }
+
+ /**
+ * Deletes the native instance in the following order
+ * <ol>
+ * <li>Removes this java reference from the native instance</li>
+ * <li>Deletes the native instance via {@link #deleteImpl()}</li>
+ * <li>Sets the nativeInstance := 0</li>
+ * </ol>
+ */
+ public synchronized void delete() {
+ if (!isValid) {
+ return;
+ }
+ isValid = false;
+ clearNativeJavaObject(nativeInstance);
+ deleteImpl();
+ nativeInstance = 0;
+ }
+
+ /**
+ * Deletes the native instance.
+ * <p>
+ * Called via {@link #delete()} and at this point this java reference
+ * has been removed from the native instance.
+ * </p>
+ */
+ protected abstract void deleteImpl();
+
+ private native void initNativeJavaObject(final long nativeInstance);
+ private native void clearNativeJavaObject(final long nativeInstance);
+}
diff --git a/java/jni/BluetoothUtils.cxx b/java/jni/BluetoothUtils.cxx
new file mode 100644
index 00000000..83e71dd0
--- /dev/null
+++ b/java/jni/BluetoothUtils.cxx
@@ -0,0 +1,53 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "org_tinyb_BluetoothUtils.h"
+
+#include <cstdint>
+#include <cinttypes>
+
+#include <time.h>
+
+static const int64_t NanoPerMilli = 1000000L;
+static const int64_t MilliPerOne = 1000L;
+
+/**
+ * See <http://man7.org/linux/man-pages/man2/clock_gettime.2.html>
+ * <p>
+ * Regarding avoiding kernel via VDSO,
+ * see <http://man7.org/linux/man-pages/man7/vdso.7.html>,
+ * clock_gettime seems to be well supported at least on kernel >= 4.4.
+ * Only bfin and sh are missing, while ia64 seems to be complicated.
+ */
+jlong Java_org_tinyb_BluetoothUtils_getCurrentMilliseconds(JNIEnv *env, jclass clazz) {
+ (void)env;
+ (void)clazz;
+
+ struct timespec t;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ int64_t res = t.tv_sec * MilliPerOne + t.tv_nsec / NanoPerMilli;
+ return (jlong)res;
+}
+
diff --git a/java/jni/CMakeLists.txt b/java/jni/CMakeLists.txt
deleted file mode 100644
index cd715a5a..00000000
--- a/java/jni/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-find_package(JNI REQUIRED)
-
-if (JNI_FOUND)
- message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
- message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
-endif (JNI_FOUND)
-
-set (tinyb_LIB_INCLUDE_DIRS
- ${PROJECT_SOURCE_DIR}/api
- ${PROJECT_SOURCE_DIR}/api/tinyb
- ${PROJECT_SOURCE_DIR}/api/direct_bt
- ${PROJECT_SOURCE_DIR}/include
-)
-
-include_directories(
- ${JNI_INCLUDE_DIRS}
- ${tinyb_LIB_INCLUDE_DIRS}
- ${JNI_HEADER_PATH}
-)
-
-file(GLOB JNI_SOURCES "*.cxx")
-
-set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
-
-add_library (javatinyb SHARED ${JNI_SOURCES})
-target_link_libraries(javatinyb ${JNI_LIBRARIES} tinyb)
-
-set_target_properties(
- javatinyb
- PROPERTIES
- SOVERSION ${tinyb_VERSION_MAJOR}
- VERSION ${tinyb_VERSION_STRING}
- CXX_STANDARD 11
- COMPILE_FLAGS "-Wall -Wextra"
-)
-
-install(TARGETS javatinyb LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-
diff --git a/java/jni/HCIManager.cxx b/java/jni/HCIManager.cxx
deleted file mode 100644
index 57865644..00000000
--- a/java/jni/HCIManager.cxx
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2020 Gothel Software e.K.
- * Copyright (c) 2020 ZAFENA AB
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "direct_bt/HCITypes.hpp"
-
-#include "JNIMem.hpp"
-#include "helper_base.hpp"
-
diff --git a/java/jni/HCIObject.cxx b/java/jni/HCIObject.cxx
deleted file mode 100644
index 1f420eea..00000000
--- a/java/jni/HCIObject.cxx
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2020 Gothel Software e.K.
- * Copyright (c) 2020 ZAFENA AB
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "direct_bt/HCITypes.hpp"
-
-#include "tinyb_hci_HCIObject.h"
-
-#include "JNIMem.hpp"
-#include "helper_base.hpp"
-
-using namespace direct_bt;
-
diff --git a/java/jni/JNIMem.cxx b/java/jni/JNIMem.cxx
index 9861995c..ecea39aa 100644
--- a/java/jni/JNIMem.cxx
+++ b/java/jni/JNIMem.cxx
@@ -2,6 +2,10 @@
* Author: Petre Eftime <[email protected]>
* Copyright (c) 2016 Intel Corporation.
*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -60,14 +64,14 @@ void JNIEnvContainer::attach() {
if( JNI_EDETACHED == envRes ) {
envRes = vm->AttachCurrentThreadAsDaemon((void**) &newEnv, NULL);
if( JNI_OK != envRes ) {
- throw std::runtime_error("Attach to VM failed");
+ throw direct_bt::RuntimeException("Attach to VM failed", E_FILE_LINE);
}
env = newEnv;
} else if( JNI_OK != envRes ) {
- throw std::runtime_error("GetEnv of VM failed");
+ throw direct_bt::RuntimeException("GetEnv of VM failed", E_FILE_LINE);
}
if (env==NULL) {
- throw std::runtime_error("GetEnv of VM is NULL");
+ throw direct_bt::RuntimeException("GetEnv of VM is NULL", E_FILE_LINE);
}
needsDetach = NULL != newEnv;
}
@@ -84,13 +88,24 @@ void JNIEnvContainer::detach() {
}
JNIGlobalRef::JNIGlobalRef(jobject object) {
+ if( nullptr == object ) {
+ throw direct_bt::RuntimeException("JNIGlobalRef ctor null jobject", E_FILE_LINE);
+ }
this->object = jni_env->NewGlobalRef(object);
}
JNIGlobalRef::~JNIGlobalRef() {
- jni_env->DeleteGlobalRef(object);
-}
-
-jobject JNIGlobalRef::operator*() {
- return object;
+ try {
+ JNIEnv * env = *jni_env;
+ if( nullptr == env ) {
+ throw direct_bt::RuntimeException("JNIGlobalRef dtor null JNIEnv", E_FILE_LINE);
+ }
+ if( nullptr == object ) {
+ throw direct_bt::RuntimeException("JNIGlobalRef dtor null jobject", E_FILE_LINE);
+ } else {
+ env->DeleteGlobalRef(object);
+ }
+ } catch (std::exception &e) {
+ fprintf(stderr, "JNIGlobalRef dtor: Caught %s\n", e.what());
+ }
}
diff --git a/java/jni/JNIMem.hpp b/java/jni/JNIMem.hpp
index 389a9157..a133bd9a 100644
--- a/java/jni/JNIMem.hpp
+++ b/java/jni/JNIMem.hpp
@@ -2,6 +2,10 @@
* Author: Petre Eftime <[email protected]>
* Copyright (c) 2016 Intel Corporation.
*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -22,10 +26,14 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#pragma once
+#ifndef JNIMEM__HPP_
+#define JNIMEM__HPP_
+
#include <jni.h>
#include <stdexcept>
+#include "BasicTypes.hpp"
+
extern JavaVM* vm;
@@ -67,12 +75,26 @@ private:
jobject object;
public:
+ static inline void check(jobject object, const char* file, int line) {
+ if( nullptr == object ) {
+ throw direct_bt::RuntimeException("JNIGlobalRef::check: Null jobject", file, line);
+ }
+ }
+
/* Creates a GlobalRef from an object passed to it */
JNIGlobalRef(jobject object);
+
/* Deletes the stored GlobalRef */
~JNIGlobalRef();
- /* Provides access to the stored GlobalRef */
- jobject operator*();
+ /* Provides access to the stored GlobalRef as an jobject. */
+ jobject operator*() { return object; }
+
+ /* Provides access to the stored GlobalRef as an jobject. */
+ jobject getObject() const { return object; }
+ /* Provides access to the stored GlobalRef as a jclass. */
+ jclass getClass() const { return (jclass)object; }
};
+#endif /* JNIMEM__HPP_ */
+
diff --git a/java/jni/direct_bt/CMakeLists.txt b/java/jni/direct_bt/CMakeLists.txt
new file mode 100644
index 00000000..7622569f
--- /dev/null
+++ b/java/jni/direct_bt/CMakeLists.txt
@@ -0,0 +1,53 @@
+find_package(JNI REQUIRED)
+
+if (JNI_FOUND)
+ message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
+ message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
+endif (JNI_FOUND)
+
+set (direct_bt_LIB_INCLUDE_DIRS
+ ${PROJECT_SOURCE_DIR}/api
+ ${PROJECT_SOURCE_DIR}/api/direct_bt
+ ${PROJECT_SOURCE_DIR}/include
+ ${PROJECT_SOURCE_DIR}/java/jni
+)
+
+include_directories(
+ ${JNI_INCLUDE_DIRS}
+ ${direct_bt_LIB_INCLUDE_DIRS}
+ ${JNI_HEADER_PATH}
+)
+
+set (direct_bt_JNI_SRCS
+ ${PROJECT_SOURCE_DIR}/java/jni/JNIMem.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/helper_base.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/BluetoothFactory.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/BluetoothUtils.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/helper_dbt.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTNativeDownlink.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTAdapter.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTDevice.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTEvent.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTGattCharacteristic.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTGattDescriptor.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTGattService.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTManager.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/direct_bt/DBTObject.cxx
+)
+
+set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
+
+add_library (javadirect_bt SHARED ${direct_bt_JNI_SRCS})
+target_link_libraries(javadirect_bt ${JNI_LIBRARIES} direct_bt)
+
+set_target_properties(
+ javadirect_bt
+ PROPERTIES
+ SOVERSION ${tinyb_VERSION_MAJOR}
+ VERSION ${tinyb_VERSION_STRING}
+ CXX_STANDARD 11
+ COMPILE_FLAGS "-Wall -Wextra"
+)
+
+install(TARGETS javadirect_bt LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx
new file mode 100644
index 00000000..3f634dc2
--- /dev/null
+++ b/java/jni/direct_bt/DBTAdapter.cxx
@@ -0,0 +1,259 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "direct_bt_tinyb_Adapter.h"
+
+// #define VERBOSE_ON 1
+#include <dbt_debug.hpp>
+
+#include "JNIMem.hpp"
+#include "helper_base.hpp"
+#include "helper_dbt.hpp"
+
+#include "direct_bt/HCITypes.hpp"
+
+using namespace direct_bt;
+
+static const std::string _deviceClazzCtorArgs("(JLdirect_bt/tinyb/Adapter;Ljava/lang/String;Ljava/lang/String;J)V");
+static const std::string _deviceDiscoveryMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/BluetoothDevice;)V");
+
+class DeviceDiscoveryCallbackListener : public HCIDeviceDiscoveryListener {
+ public:
+ /**
+ package org.tinyb;
+
+ public interface BluetoothDeviceDiscoveryListener {
+ public void deviceAdded(final BluetoothAdapter adapter, final BluetoothDevice device);
+ public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device);
+ public void deviceRemoved(final BluetoothAdapter adapter, final BluetoothDevice device);
+ };
+ */
+ std::shared_ptr<JavaAnonObj> adapterObjRef;
+ std::unique_ptr<JNIGlobalRef> deviceClazzRef;
+ jmethodID deviceClazzCtor;
+ jfieldID deviceClazzTSUpdateField;
+ std::unique_ptr<JNIGlobalRef> listenerObjRef;
+ std::unique_ptr<JNIGlobalRef> listenerClazzRef;
+ jmethodID mDeviceAdded = nullptr;
+ jmethodID mDeviceUpdated = nullptr;
+ jmethodID mDeviceRemoved = nullptr;
+
+ DeviceDiscoveryCallbackListener(JNIEnv *env, HCIAdapter *adapter, jobject deviceDiscoveryListener) {
+ adapterObjRef = adapter->getJavaObject();
+ JavaGlobalObj::check(adapterObjRef, E_FILE_LINE);
+ {
+ jclass deviceClazz = search_class(*jni_env, HCIDevice::java_class().c_str());
+ if( nullptr == deviceClazz ) {
+ throw InternalError("HCIDevice::java_class not found: "+HCIDevice::java_class(), E_FILE_LINE);
+ }
+ deviceClazzRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(deviceClazz));
+ env->DeleteLocalRef(deviceClazz);
+ }
+ deviceClazzCtor = search_method(*jni_env, deviceClazzRef->getClass(), "<init>", _deviceClazzCtorArgs.c_str(), false);
+ if( nullptr == deviceClazzCtor ) {
+ throw InternalError("HCIDevice::java_class ctor not found: "+HCIDevice::java_class()+".<init>"+_deviceClazzCtorArgs, E_FILE_LINE);
+ }
+ deviceClazzTSUpdateField = jni_env->GetFieldID(deviceClazzRef->getClass(), "ts_update", "J");
+ if( nullptr == deviceClazzTSUpdateField ) {
+ throw InternalError("HCIDevice::java_class field not found: "+HCIDevice::java_class()+".ts_update", E_FILE_LINE);
+ }
+
+ listenerObjRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(deviceDiscoveryListener));
+ {
+ jclass listenerClazz = search_class(env, listenerObjRef->getObject());
+ if( nullptr == listenerClazz ) {
+ throw InternalError("BluetoothDeviceDiscoveryListener not found", E_FILE_LINE);
+ }
+ listenerClazzRef = std::unique_ptr<JNIGlobalRef>(new JNIGlobalRef(listenerClazz));
+ env->DeleteLocalRef(listenerClazz);
+ }
+ mDeviceAdded = search_method(env, listenerClazzRef->getClass(), "deviceAdded", _deviceDiscoveryMethodArgs.c_str(), false);
+ mDeviceUpdated = search_method(env, listenerClazzRef->getClass(), "deviceUpdated", _deviceDiscoveryMethodArgs.c_str(), false);
+ mDeviceRemoved = search_method(env, listenerClazzRef->getClass(), "deviceRemoved", _deviceDiscoveryMethodArgs.c_str(), false);
+ if( nullptr == mDeviceAdded ) {
+ throw InternalError("BluetoothDeviceDiscoveryListener has no deviceAdded"+_deviceDiscoveryMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE);
+ }
+ if( nullptr == mDeviceUpdated ) {
+ throw InternalError("BluetoothDeviceDiscoveryListener has no deviceUpdated"+_deviceDiscoveryMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE);
+ }
+ if( nullptr == mDeviceRemoved ) {
+ throw InternalError("BluetoothDeviceDiscoveryListener has no deviceRemoved"+_deviceDiscoveryMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE);
+ }
+ exception_check_raise_and_throw(env, E_FILE_LINE);
+ }
+
+ void deviceAdded(HCIAdapter const &a, std::shared_ptr<HCIDevice> device) override {
+ try {
+ #ifdef VERBOSE_ON
+ fprintf(stderr, "****** Native Adapter Device ADDED__: %s\n", device->toString().c_str());
+ fprintf(stderr, "Status HCIAdapter:\n");
+ fprintf(stderr, "%s\n", a.toString().c_str());
+ #endif
+
+ // Device(final long nativeInstance, final Adapter adptr, final String address, final String name)
+ const jstring addr = from_string_to_jstring(*jni_env, device->getAddressString());
+ const jstring name = from_string_to_jstring(*jni_env, device->getName());
+ jobject jDevice = jni_env->NewObject(deviceClazzRef->getClass(), deviceClazzCtor,
+ (jlong)device.get(), adapterObjRef, addr, name, (jlong)device->ts_creation);
+ exception_check_raise_and_throw(*jni_env, E_FILE_LINE);
+ JNIGlobalRef::check(jDevice, E_FILE_LINE);
+ std::shared_ptr<JavaAnonObj> jDeviceRef = device->getJavaObject();
+ JavaGlobalObj::check(jDeviceRef, E_FILE_LINE);
+
+ jni_env->CallVoidMethod(listenerObjRef->getObject(), mDeviceAdded, JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef));
+ exception_check_raise_and_throw(*jni_env, E_FILE_LINE);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(*jni_env, e)
+ }
+ void deviceUpdated(HCIAdapter const &a, std::shared_ptr<HCIDevice> device) override {
+ try {
+ #ifdef VERBOSE_ON
+ fprintf(stderr, "****** Native Adapter Device UPDATED: %s\n", device->toString().c_str());
+ fprintf(stderr, "Status HCIAdapter:\n");
+ fprintf(stderr, "%s\n", a.toString().c_str());
+ #endif
+ std::shared_ptr<JavaAnonObj> jDeviceRef = device->getJavaObject();
+ JavaGlobalObj::check(jDeviceRef, E_FILE_LINE);
+ jni_env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)device->getUpdateTimestamp());
+ jni_env->CallVoidMethod(listenerObjRef->getObject(), mDeviceUpdated, JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef));
+ exception_check_raise_and_throw(*jni_env, E_FILE_LINE);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(*jni_env, e)
+ }
+ void deviceRemoved(HCIAdapter const &a, std::shared_ptr<HCIDevice> device) override {
+ try {
+ #ifdef VERBOSE_ON
+ fprintf(stderr, "****** DBTAdapter Device REMOVED: %s\n", device->toString().c_str());
+ fprintf(stderr, "Status HCIAdapter:\n");
+ fprintf(stderr, "%s\n", a.toString().c_str());
+ #endif
+ std::shared_ptr<JavaAnonObj> jDeviceRef = device->getJavaObject();
+ JavaGlobalObj::check(jDeviceRef, E_FILE_LINE);
+ jni_env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)device->getUpdateTimestamp());
+ jni_env->CallVoidMethod(listenerObjRef->getObject(), mDeviceRemoved, JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef));
+ exception_check_raise_and_throw(*jni_env, E_FILE_LINE);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(*jni_env, e)
+ }
+};
+
+void Java_direct_1bt_tinyb_Adapter_initImpl(JNIEnv *env, jobject obj, jobject deviceDiscoveryListener)
+{
+ // org.tinyb.BluetoothDeviceDiscoveryListener
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ JavaGlobalObj::check(adapter->getJavaObject(), E_FILE_LINE);
+
+ // set our callback discovery listener.
+ DeviceDiscoveryCallbackListener *l = new DeviceDiscoveryCallbackListener(env, adapter, deviceDiscoveryListener);
+ adapter->setDeviceDiscoveryListener(std::shared_ptr<HCIDeviceDiscoveryListener>(l));
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+void Java_direct_1bt_tinyb_Adapter_deleteImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ DBG_PRINT("Java_direct_1bt_tinyb_Adapter_deleteImpl %s", adapter->toString().c_str());
+ delete adapter;
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+jboolean Java_direct_1bt_tinyb_Adapter_startDiscoveryImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ std::shared_ptr<direct_bt::HCISession> session = adapter->getOpenSession();
+ if( nullptr == session ) {
+ throw BluetoothException("No adapter session: "+adapter->toString(), E_FILE_LINE);
+ }
+ if( !session->isOpen() ) {
+ throw BluetoothException("No open adapter session: "+adapter->toString(), E_FILE_LINE);
+ }
+ return adapter->startDiscovery(*session);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return JNI_FALSE;
+}
+
+jboolean Java_direct_1bt_tinyb_Adapter_stopDiscoveryImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ std::shared_ptr<direct_bt::HCISession> session = adapter->getOpenSession();
+ if( nullptr == session ) {
+ throw BluetoothException("No adapter session: "+adapter->toString(), E_FILE_LINE);
+ }
+ if( !session->isOpen() ) {
+ throw BluetoothException("No open adapter session: "+adapter->toString(), E_FILE_LINE);
+ }
+ adapter->setDeviceDiscoveryListener(nullptr);
+ adapter->stopDiscovery(*session);
+ return JNI_TRUE;
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return JNI_FALSE;
+}
+
+jint Java_direct_1bt_tinyb_Adapter_discoverAnyDeviceImpl(JNIEnv *env, jobject obj, jint timeoutMS)
+{
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ std::shared_ptr<direct_bt::HCISession> session = adapter->getOpenSession();
+ if( nullptr == session ) {
+ throw BluetoothException("No adapter session: "+adapter->toString(), E_FILE_LINE);
+ }
+ if( !session->isOpen() ) {
+ throw BluetoothException("No open adapter session: "+adapter->toString(), E_FILE_LINE);
+ }
+ return adapter->discoverDevices(*session, -1, EUI48_ANY_DEVICE, timeoutMS, static_cast<uint32_t>(EInfoReport::Element::NAME));
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return 0;
+}
+
+jobject Java_direct_1bt_tinyb_Adapter_getDiscoveredDevicesImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ /**
+ std::function<jobject(JNIEnv*, jclass, jmethodID, HCIDevice*)> ctor_device = [&](JNIEnv *env, jclass clazz, jmethodID clazz_ctor, HCIDevice *elem) {
+ // Device(final long nativeInstance, final Adapter adptr, final String address, final String name)
+ jstring addr = from_string_to_jstring(env, elem->getAddressString());
+ jstring name = from_string_to_jstring(env, elem->getName());
+ jobject object = env->NewObject(clazz, clazz_ctor, (jlong)elem, obj, addr, name);
+ return object;
+ };
+ return convert_vector_to_jobject<HCIDevice>(env, array, "(JLdirect_bt/tinyb/Adapter;Ljava/lang/String;Ljava/lang/String;)V", ctor_device);
+ */
+ std::vector<std::shared_ptr<HCIDevice>> array = adapter->getDiscoveredDevices();
+ return convert_vector_to_jobject(env, array);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return nullptr;
+}
+
+jint Java_direct_1bt_tinyb_Adapter_removeDevicesImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIAdapter *adapter = getInstance<HCIAdapter>(env, obj);
+ return adapter->removeDiscoveredDevices();
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return 0;
+}
+
diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx
new file mode 100644
index 00000000..b2887b55
--- /dev/null
+++ b/java/jni/direct_bt/DBTDevice.cxx
@@ -0,0 +1,78 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "direct_bt_tinyb_Device.h"
+
+#include "JNIMem.hpp"
+#include "helper_base.hpp"
+#include "helper_dbt.hpp"
+
+#include "direct_bt/HCITypes.hpp"
+
+using namespace direct_bt;
+
+void Java_direct_1bt_tinyb_Device_initImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIDevice *device = getInstance<HCIDevice>(env, obj);
+ JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+void Java_direct_1bt_tinyb_Device_deleteImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIDevice *device = getInstance<HCIDevice>(env, obj);
+ delete device;
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+jshort Java_direct_1bt_tinyb_Device_getRSSI(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIDevice *device = getInstance<HCIDevice>(env, obj);
+ return device->getRSSI();
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return 0;
+}
+
+jshort Java_direct_1bt_tinyb_Device_getTxPower(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIDevice *device = getInstance<HCIDevice>(env, obj);
+ return device->getTxPower();
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return 0;
+}
+
+jboolean Java_direct_1bt_tinyb_Device_getConnected(JNIEnv *env, jobject obj)
+{
+ try {
+ HCIDevice *device = getInstance<HCIDevice>(env, obj);
+ (void) device;
+ return JNI_TRUE; // FIXME
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return JNI_FALSE;
+}
diff --git a/java/jni/HCIEvent.cxx b/java/jni/direct_bt/DBTEvent.cxx
index b1bc89c5..e9203d48 100644
--- a/java/jni/HCIEvent.cxx
+++ b/java/jni/direct_bt/DBTEvent.cxx
@@ -23,9 +23,9 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "tinyb_hci_HCIEvent.h"
+#include "direct_bt_tinyb_DBTEvent.h"
-jobject Java_tinyb_hci_HCIEvent_getType(JNIEnv *env, jobject obj)
+jobject Java_direct_1bt_tinyb_DBTEvent_getType(JNIEnv *env, jobject obj)
{
(void)env;
(void)obj;
@@ -33,7 +33,7 @@ jobject Java_tinyb_hci_HCIEvent_getType(JNIEnv *env, jobject obj)
return NULL;
}
-jstring Java_tinyb_hci_HCIEvent_getName(JNIEnv *env, jobject obj)
+jstring Java_direct_1bt_tinyb_DBTEvent_getName(JNIEnv *env, jobject obj)
{
(void)env;
(void)obj;
@@ -41,7 +41,7 @@ jstring Java_tinyb_hci_HCIEvent_getName(JNIEnv *env, jobject obj)
return NULL;
}
-jstring Java_tinyb_hci_HCIEvent_getIdentifier(JNIEnv *env, jobject obj)
+jstring Java_direct_1bt_tinyb_DBTEvent_getIdentifier(JNIEnv *env, jobject obj)
{
(void)env;
(void)obj;
@@ -49,7 +49,7 @@ jstring Java_tinyb_hci_HCIEvent_getIdentifier(JNIEnv *env, jobject obj)
return NULL;
}
-jboolean Java_tinyb_hci_HCIEvent_executeCallback(JNIEnv *env, jobject obj)
+jboolean Java_direct_1bt_tinyb_DBTEvent_executeCallback(JNIEnv *env, jobject obj)
{
(void)env;
(void)obj;
@@ -57,7 +57,7 @@ jboolean Java_tinyb_hci_HCIEvent_executeCallback(JNIEnv *env, jobject obj)
return JNI_FALSE;
}
-jboolean Java_tinyb_hci_HCIEvent_hasCallback(JNIEnv *env, jobject obj)
+jboolean Java_direct_1bt_tinyb_DBTEvent_hasCallback(JNIEnv *env, jobject obj)
{
(void)env;
(void)obj;
@@ -65,9 +65,9 @@ jboolean Java_tinyb_hci_HCIEvent_hasCallback(JNIEnv *env, jobject obj)
return JNI_FALSE;
}
-void Java_tinyb_hci_HCIEvent_init(JNIEnv *env, jobject obj, jobject type, jstring name,
- jstring identifier, jobject parent, jobject callback,
- jobject arg_data)
+void Java_direct_1bt_tinyb_DBTEvent_init(JNIEnv *env, jobject obj, jobject type, jstring name,
+ jstring identifier, jobject parent, jobject callback,
+ jobject arg_data)
{
(void)env;
(void)obj;
@@ -79,7 +79,7 @@ void Java_tinyb_hci_HCIEvent_init(JNIEnv *env, jobject obj, jobject type, jstrin
(void)arg_data;
}
-void Java_tinyb_hci_HCIEvent_delete(JNIEnv *env, jobject obj)
+void Java_direct_1bt_tinyb_DBTEvent_delete(JNIEnv *env, jobject obj)
{
(void)env;
(void)obj;
diff --git a/java/jni/HCIGattCharacteristic.cxx b/java/jni/direct_bt/DBTGattCharacteristic.cxx
index 0a0c4c07..cae33960 100644
--- a/java/jni/HCIGattCharacteristic.cxx
+++ b/java/jni/direct_bt/DBTGattCharacteristic.cxx
@@ -23,12 +23,12 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "direct_bt/HCITypes.hpp"
-
-#include "tinyb_hci_HCIGattCharacteristic.h"
+#include "direct_bt_tinyb_GattCharacteristic.h"
#include "JNIMem.hpp"
#include "helper_base.hpp"
+#include "direct_bt/HCITypes.hpp"
+
using namespace direct_bt;
diff --git a/java/jni/HCIDevice.cxx b/java/jni/direct_bt/DBTGattDescriptor.cxx
index d143b85d..59410d92 100644
--- a/java/jni/HCIDevice.cxx
+++ b/java/jni/direct_bt/DBTGattDescriptor.cxx
@@ -23,12 +23,12 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "direct_bt/HCITypes.hpp"
-
-#include "tinyb_hci_HCIDevice.h"
+#include "direct_bt_tinyb_GattDescriptor.h"
#include "JNIMem.hpp"
#include "helper_base.hpp"
+#include "direct_bt/HCITypes.hpp"
+
using namespace direct_bt;
diff --git a/java/jni/HCIGattService.cxx b/java/jni/direct_bt/DBTGattService.cxx
index 14dfcbe8..6e0fe141 100644
--- a/java/jni/HCIGattService.cxx
+++ b/java/jni/direct_bt/DBTGattService.cxx
@@ -23,12 +23,12 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "direct_bt/HCITypes.hpp"
-
-#include "tinyb_hci_HCIGattService.h"
+#include "direct_bt_tinyb_GattService.h"
#include "JNIMem.hpp"
#include "helper_base.hpp"
+#include "direct_bt/HCITypes.hpp"
+
using namespace direct_bt;
diff --git a/java/jni/direct_bt/DBTManager.cxx b/java/jni/direct_bt/DBTManager.cxx
new file mode 100644
index 00000000..0c01272d
--- /dev/null
+++ b/java/jni/direct_bt/DBTManager.cxx
@@ -0,0 +1,106 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "direct_bt_tinyb_Manager.h"
+
+// #define VERBOSE_ON 1
+#include <dbt_debug.hpp>
+
+#include "JNIMem.hpp"
+#include "helper_base.hpp"
+#include "helper_dbt.hpp"
+
+#include "direct_bt/HCITypes.hpp"
+
+using namespace direct_bt;
+
+void Java_direct_1bt_tinyb_Manager_initImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ MgmtHandler *manager = &MgmtHandler::get(); // special: static singleton
+ setInstance<MgmtHandler>(env, obj, manager);
+ manager->setJavaObject( std::shared_ptr<JavaAnonObj>( new JavaGlobalObj(obj) ) );
+ JavaGlobalObj::check(manager->getJavaObject(), E_FILE_LINE);
+ DBG_PRINT("Java_direct_1bt_tinyb_Manager_init: Manager %s", manager->toString().c_str());
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+void Java_direct_1bt_tinyb_Manager_deleteImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ MgmtHandler *manager = getInstance<MgmtHandler>(env, obj); // special: static singleton
+ manager->setJavaObject(nullptr);
+ // delete manager;
+ (void) manager;
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+static const std::string _adapterClazzCtorArgs("(JLjava/lang/String;Ljava/lang/String;)V");
+
+jobject Java_direct_1bt_tinyb_Manager_getDefaultAdapterImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ MgmtHandler *manager = getInstance<MgmtHandler>(env, obj);
+ DBG_PRINT("Java_direct_1bt_tinyb_Manager_getDefaultAdapterImpl: Manager %s", manager->toString().c_str());
+ int defAdapterIdx = manager->getDefaultAdapterIdx();
+ HCIAdapter * adapter = new HCIAdapter(defAdapterIdx);
+ if( !adapter->isValid() ) {
+ delete adapter;
+ throw BluetoothException("Invalid default adapter "+std::to_string(defAdapterIdx), E_FILE_LINE);
+ }
+ if( !adapter->hasDevId() ) {
+ delete adapter;
+ throw BluetoothException("Invalid default adapter dev-id "+std::to_string(defAdapterIdx), E_FILE_LINE);
+ }
+ std::shared_ptr<direct_bt::HCISession> session = adapter->open();
+ if( nullptr == session ) {
+ delete adapter;
+ throw BluetoothException("Couldn't open default adapter "+std::to_string(defAdapterIdx), E_FILE_LINE);
+ }
+
+ // prepare adapter ctor
+ const jstring addr = from_string_to_jstring(env, adapter->getAddressString());
+ const jstring name = from_string_to_jstring(env, adapter->getName());
+ const jclass clazz = search_class(env, *adapter);
+ if( nullptr == clazz ) {
+ throw InternalError("Adapter class not found: "+HCIAdapter::java_class(), E_FILE_LINE);
+ }
+ const jmethodID clazz_ctor = search_method(env, clazz, "<init>", _adapterClazzCtorArgs.c_str(), false);
+ if( nullptr == clazz_ctor ) {
+ throw InternalError("Adapter ctor not found: "+HCIAdapter::java_class()+".<init>"+_adapterClazzCtorArgs, E_FILE_LINE);
+ }
+ exception_check_raise_and_throw(env, E_FILE_LINE);
+ jobject jAdapter = env->NewObject(clazz, clazz_ctor, (jlong)adapter, addr, name);
+ exception_check_raise_and_throw(env, E_FILE_LINE);
+ JNIGlobalRef::check(jAdapter, E_FILE_LINE);
+ std::shared_ptr<JavaAnonObj> jAdapterRef = adapter->getJavaObject();
+ JavaGlobalObj::check(jAdapterRef, E_FILE_LINE);
+
+ DBG_PRINT("Java_direct_1bt_tinyb_Manager_getDefaultAdapterImpl: New Adapter %s", adapter->toString().c_str());
+ return JavaGlobalObj::GetObject(jAdapterRef);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+ return NULL;
+}
+
diff --git a/java/jni/direct_bt/DBTNativeDownlink.cxx b/java/jni/direct_bt/DBTNativeDownlink.cxx
new file mode 100644
index 00000000..201d0728
--- /dev/null
+++ b/java/jni/direct_bt/DBTNativeDownlink.cxx
@@ -0,0 +1,58 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "direct_bt_tinyb_NativeDownlink.h"
+
+// #define VERBOSE_ON 1
+#include <dbt_debug.hpp>
+
+#include "JNIMem.hpp"
+#include "helper_base.hpp"
+#include "helper_dbt.hpp"
+
+#include "direct_bt/HCITypes.hpp"
+
+using namespace direct_bt;
+
+void Java_direct_1bt_tinyb_NativeDownlink_initNativeJavaObject(JNIEnv *env, jobject obj, jlong nativeInstance)
+{
+ try {
+ JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance);
+ std::shared_ptr<JavaGlobalObj> jobjRef( new JavaGlobalObj(obj) );
+ javaUplink->setJavaObject( jobjRef );
+ JavaGlobalObj::check(javaUplink->getJavaObject(), E_FILE_LINE);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
+void Java_direct_1bt_tinyb_NativeDownlink_clearNativeJavaObject(JNIEnv *env, jobject obj, jlong nativeInstance)
+{
+ (void)obj;
+ try {
+ JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance);
+ DBG_PRINT("Java_direct_1bt_tinyb_NativeDownlink_clearNativeJavaObject %s", javaUplink->toString().c_str());
+ javaUplink->setJavaObject(nullptr);
+ } CATCH_EXCEPTION_AND_RAISE_JAVA(env, e)
+}
+
diff --git a/java/jni/HCIAdapter.cxx b/java/jni/direct_bt/DBTObject.cxx
index afb420fc..74f40e8a 100644
--- a/java/jni/HCIAdapter.cxx
+++ b/java/jni/direct_bt/DBTObject.cxx
@@ -23,12 +23,12 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "direct_bt/HCITypes.hpp"
-
-#include "tinyb_hci_HCIAdapter.h"
+// #include "direct_bt_tinyb_DBTObject.h"
#include "JNIMem.hpp"
#include "helper_base.hpp"
+#include "direct_bt/HCITypes.hpp"
+
using namespace direct_bt;
diff --git a/java/jni/direct_bt/helper_dbt.cxx b/java/jni/direct_bt/helper_dbt.cxx
new file mode 100644
index 00000000..b3431edc
--- /dev/null
+++ b/java/jni/direct_bt/helper_dbt.cxx
@@ -0,0 +1,65 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <jni.h>
+#include <memory>
+#include <stdexcept>
+#include <vector>
+
+#include "helper_dbt.hpp"
+
+using namespace direct_bt;
+
+jclass direct_bt::search_class(JNIEnv *env, JavaUplink &object)
+{
+ return search_class(env, object.get_java_class().c_str());
+}
+
+#if 0
+
+jobject direct_bt::convert_vector_to_jobject(JNIEnv *env, std::vector<std::shared_ptr<JavaUplink>>& array)
+{
+ unsigned int array_size = array.size();
+
+ jmethodID arraylist_add;
+ jobject result = get_new_arraylist(env, array_size, &arraylist_add);
+
+ if (0 == array_size) {
+ return result;
+ }
+
+ for (unsigned int i = 0; i < array_size; ++i) {
+ std::shared_ptr<JavaUplink> elem = array.at(i);
+ std::shared_ptr<JNIGlobalRef> objref = elem->getJavaObject();
+ if ( nullptr == objref ) {
+ throw InternalError("JavaUplink element of array has no valid java-object: "+elem->toString(), E_FILE_LINE);
+ }
+ env->CallBooleanMethod(result, arraylist_add, objref->get());
+ }
+ return result;
+}
+
+#endif
+
diff --git a/java/jni/direct_bt/helper_dbt.hpp b/java/jni/direct_bt/helper_dbt.hpp
new file mode 100644
index 00000000..2f3d265f
--- /dev/null
+++ b/java/jni/direct_bt/helper_dbt.hpp
@@ -0,0 +1,113 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef HELPER_DBT_HPP_
+#define HELPER_DBT_HPP_
+
+#include "JNIMem.hpp"
+#include "helper_base.hpp"
+
+#include "direct_bt/JavaAccess.hpp"
+#include "direct_bt/BasicTypes.hpp"
+
+namespace direct_bt {
+
+ class JavaGlobalObj : public JavaAnonObj {
+ private:
+ JNIGlobalRef javaObjectRef;
+
+ public:
+ static inline void check(const std::shared_ptr<JavaAnonObj> & shref, const char* file, int line) {
+ if( nullptr == shref ) {
+ throw direct_bt::RuntimeException("JavaGlobalObj::check: Null shared-JavaAnonObj", file, line);
+ }
+ const jobject obj = static_cast<const JavaGlobalObj*>(shref.get())->getObject();
+ if( nullptr == obj ) {
+ throw direct_bt::RuntimeException("JavaGlobalObj::check: Null object", file, line);
+ }
+ }
+ JavaGlobalObj(jobject obj) : javaObjectRef(obj) { }
+ ~JavaGlobalObj() override { }
+
+ std::string toString() const override {
+ const uint64_t ref = (uint64_t)(void*)javaObjectRef.getObject();
+ return "JavaGlobalObj["+uint64HexString(ref, true)+"]";
+ }
+
+ JNIGlobalRef & getJavaObject() { return javaObjectRef; }
+
+ /* Provides access to the stored GlobalRef as an jobject. */
+ jobject getObject() const { return javaObjectRef.getObject(); }
+ /* Provides access to the stored GlobalRef as a jclass. */
+ jclass getClass() const { return javaObjectRef.getClass(); }
+
+ /* Provides access to the stored GlobalRef as an jobject. */
+ static jobject GetObject(const std::shared_ptr<JavaAnonObj> & shref) {
+ return static_cast<JavaGlobalObj*>(shref.get())->getObject();
+ }
+
+ /* Provides access to the stored GlobalRef as a jclass. */
+ static jclass GetClass(const std::shared_ptr<JavaAnonObj> & shref) {
+ return static_cast<JavaGlobalObj*>(shref.get())->getClass();
+ }
+ };
+
+
+ jclass search_class(JNIEnv *env, JavaUplink &object);
+
+#if 0
+
+ jobject convert_vector_to_jobject(JNIEnv *env, std::vector<std::shared_ptr<JavaUplink>>& array);
+
+#else
+
+ template <typename T>
+ jobject convert_vector_to_jobject(JNIEnv *env, std::vector<std::shared_ptr<T>>& array)
+ {
+ unsigned int array_size = array.size();
+
+ jmethodID arraylist_add;
+ jobject result = get_new_arraylist(env, array_size, &arraylist_add);
+
+ if (0 == array_size) {
+ return result;
+ }
+
+ for (unsigned int i = 0; i < array_size; ++i) {
+ std::shared_ptr<T> elem = array.at(i);
+ std::shared_ptr<JavaAnonObj> objref = elem->getJavaObject();
+ if ( nullptr == objref ) {
+ throw InternalError("JavaUplink element of array has no valid java-object: "+elem->toString(), E_FILE_LINE);
+ }
+ env->CallBooleanMethod(result, arraylist_add, JavaGlobalObj::GetObject(objref));
+ }
+ return result;
+ }
+
+#endif
+
+} // namespace direct_bt
+
+#endif /* HELPER_DBT_HPP_ */
diff --git a/java/jni/helper_base.cxx b/java/jni/helper_base.cxx
index 2c0c23e6..dd3dcf54 100644
--- a/java/jni/helper_base.cxx
+++ b/java/jni/helper_base.cxx
@@ -31,7 +31,9 @@
#include <stdexcept>
#include <vector>
-#include "helper_tinyb.hpp"
+#include "helper_base.hpp"
+
+#define JAVA_MAIN_PACKAGE "org/tinyb"
jfieldID getInstanceField(JNIEnv *env, jobject obj)
{
@@ -144,6 +146,11 @@ std::string from_jstring_to_string(JNIEnv *env, jstring str)
return string_to_write;
}
+jstring from_string_to_jstring(JNIEnv *env, const std::string & str)
+{
+ return env->NewStringUTF(str.c_str());
+}
+
jobject get_bluetooth_type(JNIEnv *env, const char *field_name)
{
jclass b_type_enum = search_class(env, JAVA_MAIN_PACKAGE "/BluetoothType");
@@ -182,6 +189,10 @@ void raise_java_runtime_exception(JNIEnv *env, std::runtime_error &e)
env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
}
+void raise_java_runtime_exception(JNIEnv *env, direct_bt::RuntimeException &e) {
+ env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
+}
+
void raise_java_oom_exception(JNIEnv *env, std::bad_alloc &e)
{
env->ThrowNew(env->FindClass("java/lang/OutOfMemoryException"), e.what());
@@ -192,4 +203,18 @@ void raise_java_invalid_arg_exception(JNIEnv *env, std::invalid_argument &e)
env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"), e.what());
}
+void raise_java_bluetooth_exception(JNIEnv *env, direct_bt::BluetoothException &e)
+{
+ env->ThrowNew(env->FindClass("org/tinyb/BluetoothException"), e.what());
+}
+void exception_check_raise_and_throw(JNIEnv *env, const char* file, int line)
+{
+ if( env->ExceptionCheck() ) {
+ env->ExceptionDescribe();
+ jthrowable e = env->ExceptionOccurred();
+ env->ExceptionClear();
+ env->Throw(e);
+ throw direct_bt::RuntimeException("Java exception occurred and forwarded.", file, line);
+ }
+}
diff --git a/java/jni/helper_base.hpp b/java/jni/helper_base.hpp
index 153faa9b..4cbda995 100644
--- a/java/jni/helper_base.hpp
+++ b/java/jni/helper_base.hpp
@@ -26,10 +26,15 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#pragma once
+#ifndef HELPER_BASE_HPP_
+#define HELPER_BASE_HPP_
#include <vector>
#include <memory>
+#include <functional>
+#include <jni.h>
+
+#include "BasicTypes.hpp"
jfieldID getInstanceField(JNIEnv *env, jobject obj);
@@ -41,10 +46,20 @@ jfieldID search_field(JNIEnv *env, jclass clazz, const char *field_name,
const char *type, bool is_static);
bool from_jboolean_to_bool(jboolean val);
std::string from_jstring_to_string(JNIEnv *env, jstring str);
+jstring from_string_to_jstring(JNIEnv *env, const std::string & str);
jobject get_bluetooth_type(JNIEnv *env, const char *field_name);
jobject get_new_arraylist(JNIEnv *env, unsigned int size, jmethodID *add);
template <typename T>
+T *castInstance(jlong instance)
+{
+ T *t = reinterpret_cast<T *>(instance);
+ if (t == nullptr)
+ throw std::runtime_error("Trying to cast null object");
+ return t;
+}
+
+template <typename T>
T *getInstance(JNIEnv *env, jobject obj)
{
jlong instance = env->GetLongField(obj, getInstanceField(env, obj));
@@ -111,7 +126,58 @@ jobject convert_vector_to_jobject(JNIEnv *env, std::vector<std::unique_ptr<T>>&
return result;
}
+template <typename T>
+jobject convert_vector_to_jobject(JNIEnv *env, std::vector<std::shared_ptr<T>>& array,
+ const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, T*)> ctor)
+{
+ unsigned int array_size = array.size();
+
+ jmethodID arraylist_add;
+ jobject result = get_new_arraylist(env, array_size, &arraylist_add);
+
+ if (array_size == 0)
+ {
+ return result;
+ }
+
+ jclass clazz = search_class(env, T::java_class().c_str());
+ jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
+
+ for (unsigned int i = 0; i < array_size; ++i)
+ {
+ T *elem = array.at(i).get();
+ jobject object = ctor(env, clazz, clazz_ctor, elem);
+ if (!object)
+ {
+ throw std::runtime_error("cannot create instance of class\n");
+ }
+ env->CallBooleanMethod(result, arraylist_add, object);
+ }
+ return result;
+}
+
void raise_java_exception(JNIEnv *env, std::exception &e);
void raise_java_runtime_exception(JNIEnv *env, std::runtime_error &e);
+void raise_java_runtime_exception(JNIEnv *env, direct_bt::RuntimeException &e);
void raise_java_oom_exception(JNIEnv *env, std::bad_alloc &e);
void raise_java_invalid_arg_exception(JNIEnv *env, std::invalid_argument &e);
+void raise_java_bluetooth_exception(JNIEnv *env, direct_bt::BluetoothException &e);
+
+void exception_check_raise_and_throw(JNIEnv *env, const char* file, int line);
+
+#define CATCH_EXCEPTION_AND_RAISE_JAVA(env, e) \
+ catch (std::bad_alloc &e) { \
+ raise_java_oom_exception(env, e); \
+} catch (direct_bt::BluetoothException &e) { \
+ raise_java_bluetooth_exception(env, e); \
+} catch (direct_bt::RuntimeException &e) { \
+ raise_java_runtime_exception(env, e); \
+} catch (std::runtime_error &e) { \
+ raise_java_runtime_exception(env, e); \
+} catch (std::invalid_argument &e) { \
+ raise_java_invalid_arg_exception(env, e); \
+} catch (std::exception &e) { \
+ raise_java_exception(env, e); \
+}
+
+#endif /* HELPER_BASE_HPP_ */
diff --git a/java/jni/tinyb/CMakeLists.txt b/java/jni/tinyb/CMakeLists.txt
new file mode 100644
index 00000000..a2bfb5a7
--- /dev/null
+++ b/java/jni/tinyb/CMakeLists.txt
@@ -0,0 +1,54 @@
+find_package(JNI REQUIRED)
+
+if (JNI_FOUND)
+ message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
+ message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
+endif (JNI_FOUND)
+
+set (tinyb_LIB_INCLUDE_DIRS
+ ${PROJECT_SOURCE_DIR}/api
+ ${PROJECT_SOURCE_DIR}/api/direct_bt
+ ${PROJECT_SOURCE_DIR}/api/tinyb
+ ${PROJECT_SOURCE_DIR}/include
+ ${PROJECT_SOURCE_DIR}/java/jni
+)
+
+include_directories(
+ ${JNI_INCLUDE_DIRS}
+ ${tinyb_LIB_INCLUDE_DIRS}
+ ${JNI_HEADER_PATH}
+)
+
+set (tinyb_JNI_SRCS
+ ${PROJECT_SOURCE_DIR}/src/direct_bt/BasicTypes.cpp
+ ${PROJECT_SOURCE_DIR}/java/jni/JNIMem.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/helper_base.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/BluetoothFactory.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/BluetoothUtils.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/helper_tinyb.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusAdapter.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusDevice.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusEvent.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusGattCharacteristic.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusGattDescriptor.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusGattService.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusManager.cxx
+ ${PROJECT_SOURCE_DIR}/java/jni/tinyb/DBusObject.cxx
+)
+
+set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
+
+add_library (javatinyb SHARED ${tinyb_JNI_SRCS})
+target_link_libraries(javatinyb ${JNI_LIBRARIES} tinyb)
+
+set_target_properties(
+ javatinyb
+ PROPERTIES
+ SOVERSION ${tinyb_VERSION_MAJOR}
+ VERSION ${tinyb_VERSION_STRING}
+ CXX_STANDARD 11
+ COMPILE_FLAGS "-Wall -Wextra"
+)
+
+install(TARGETS javatinyb LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
diff --git a/java/jni/DBusAdapter.cxx b/java/jni/tinyb/DBusAdapter.cxx
index 9f43c4b8..9f43c4b8 100644
--- a/java/jni/DBusAdapter.cxx
+++ b/java/jni/tinyb/DBusAdapter.cxx
diff --git a/java/jni/DBusDevice.cxx b/java/jni/tinyb/DBusDevice.cxx
index 6a833356..6a833356 100644
--- a/java/jni/DBusDevice.cxx
+++ b/java/jni/tinyb/DBusDevice.cxx
diff --git a/java/jni/DBusEvent.cxx b/java/jni/tinyb/DBusEvent.cxx
index 14b6431c..14b6431c 100644
--- a/java/jni/DBusEvent.cxx
+++ b/java/jni/tinyb/DBusEvent.cxx
diff --git a/java/jni/DBusGattCharacteristic.cxx b/java/jni/tinyb/DBusGattCharacteristic.cxx
index 43ac754f..43ac754f 100644
--- a/java/jni/DBusGattCharacteristic.cxx
+++ b/java/jni/tinyb/DBusGattCharacteristic.cxx
diff --git a/java/jni/DBusGattDescriptor.cxx b/java/jni/tinyb/DBusGattDescriptor.cxx
index 2118205c..2118205c 100644
--- a/java/jni/DBusGattDescriptor.cxx
+++ b/java/jni/tinyb/DBusGattDescriptor.cxx
diff --git a/java/jni/DBusGattService.cxx b/java/jni/tinyb/DBusGattService.cxx
index 0ab089f2..0ab089f2 100644
--- a/java/jni/DBusGattService.cxx
+++ b/java/jni/tinyb/DBusGattService.cxx
diff --git a/java/jni/DBusManager.cxx b/java/jni/tinyb/DBusManager.cxx
index 1680e866..1680e866 100644
--- a/java/jni/DBusManager.cxx
+++ b/java/jni/tinyb/DBusManager.cxx
diff --git a/java/jni/DBusObject.cxx b/java/jni/tinyb/DBusObject.cxx
index 8e3b93a2..8e3b93a2 100644
--- a/java/jni/DBusObject.cxx
+++ b/java/jni/tinyb/DBusObject.cxx
diff --git a/java/jni/helper_tinyb.cxx b/java/jni/tinyb/helper_tinyb.cxx
index 865d55e5..c20b5933 100644
--- a/java/jni/helper_tinyb.cxx
+++ b/java/jni/tinyb/helper_tinyb.cxx
@@ -33,76 +33,78 @@
#include "helper_tinyb.hpp"
-jclass search_class(JNIEnv *env, tinyb::BluetoothObject &object)
+using namespace tinyb;
+
+jclass search_class(JNIEnv *env, BluetoothObject &object)
{
return search_class(env, object.get_java_class().c_str());
}
-tinyb::BluetoothType from_int_to_btype(int type)
+BluetoothType from_int_to_btype(int type)
{
- tinyb::BluetoothType result = tinyb::BluetoothType::NONE;
+ BluetoothType result = BluetoothType::NONE;
switch (type)
{
case 0:
- result = tinyb::BluetoothType::NONE;
+ result = BluetoothType::NONE;
break;
case 1:
- result = tinyb::BluetoothType::ADAPTER;
+ result = BluetoothType::ADAPTER;
break;
case 2:
- result = tinyb::BluetoothType::DEVICE;
+ result = BluetoothType::DEVICE;
break;
case 3:
- result = tinyb::BluetoothType::GATT_SERVICE;
+ result = BluetoothType::GATT_SERVICE;
break;
case 4:
- result = tinyb::BluetoothType::GATT_CHARACTERISTIC;
+ result = BluetoothType::GATT_CHARACTERISTIC;
break;
case 5:
- result = tinyb::BluetoothType::GATT_CHARACTERISTIC;
+ result = BluetoothType::GATT_CHARACTERISTIC;
break;
default:
- result = tinyb::BluetoothType::NONE;
+ result = BluetoothType::NONE;
break;
}
return result;
}
-tinyb::TransportType from_int_to_transport_type(int type)
+TransportType from_int_to_transport_type(int type)
{
- tinyb::TransportType result = tinyb::TransportType::AUTO;
+ TransportType result = TransportType::AUTO;
switch (type)
{
case 0:
- result = tinyb::TransportType::AUTO;
+ result = TransportType::AUTO;
break;
case 1:
- result = tinyb::TransportType::BREDR;
+ result = TransportType::BREDR;
break;
case 2:
- result = tinyb::TransportType::LE;
+ result = TransportType::LE;
break;
default:
- result = tinyb::TransportType::AUTO;
+ result = TransportType::AUTO;
break;
}
return result;
}
-void raise_java_bluetooth_exception(JNIEnv *env, tinyb::BluetoothException &e)
+void raise_java_bluetooth_exception(JNIEnv *env, BluetoothException &e)
{
env->ThrowNew(env->FindClass("org/tinyb/BluetoothException"), e.what());
}
diff --git a/java/jni/helper_tinyb.hpp b/java/jni/tinyb/helper_tinyb.hpp
index f1873a7f..d91051c4 100644
--- a/java/jni/helper_tinyb.hpp
+++ b/java/jni/tinyb/helper_tinyb.hpp
@@ -32,8 +32,12 @@
#include "tinyb/BluetoothObject.hpp"
#include "tinyb/BluetoothException.hpp"
-jclass search_class(JNIEnv *env, tinyb::BluetoothObject &object);
-tinyb::BluetoothType from_int_to_btype(int type);
-tinyb::TransportType from_int_to_transport_type(int type);
+namespace tinyb {
-void raise_java_bluetooth_exception(JNIEnv *env, tinyb::BluetoothException &e);
+ jclass search_class(JNIEnv *env, BluetoothObject &object);
+ BluetoothType from_int_to_btype(int type);
+ TransportType from_int_to_transport_type(int type);
+
+ void raise_java_bluetooth_exception(JNIEnv *env, BluetoothException &e);
+
+} // namespace tinyb
diff --git a/java/org/tinyb/BluetoothAdapter.java b/java/org/tinyb/BluetoothAdapter.java
index 95d2e6d0..2b55cf75 100644
--- a/java/org/tinyb/BluetoothAdapter.java
+++ b/java/org/tinyb/BluetoothAdapter.java
@@ -242,6 +242,12 @@ public interface BluetoothAdapter extends BluetoothObject
public boolean getDiscovering();
/**
+ * Sets the {@link BluetoothDeviceDiscoveryListener} for the respective device discovery events.
+ * @param listener A {@link BluetoothDeviceDiscoveryListener} instance, or {@code null} to disable notifications.
+ */
+ public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener listener);
+
+ /**
* Enables notifications for the discovering property and calls run function of the
* BluetoothNotification object.
* @param callback A BluetoothNotification<Boolean> object. Its run function will be called
diff --git a/java/org/tinyb/BluetoothDeviceDiscoveryListener.java b/java/org/tinyb/BluetoothDeviceDiscoveryListener.java
new file mode 100644
index 00000000..737f47b9
--- /dev/null
+++ b/java/org/tinyb/BluetoothDeviceDiscoveryListener.java
@@ -0,0 +1,42 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.tinyb;
+
+/**
+ * {@link BluetoothDevice} listener for the respective {@link BluetoothDevice} discovery events: Added, updated and removed.
+ * <p>
+ * A listener instance may be attached to a {@link BluetoothAdapter} via
+ * {@link BluetoothAdapter#setDeviceDiscoveryListener(BluetoothDeviceDiscoveryListener)}.
+ * </p>
+ */
+public interface BluetoothDeviceDiscoveryListener {
+ /** A {@link BluetoothDevice} has been newly discovered. */
+ public void deviceAdded(final BluetoothAdapter adapter, final BluetoothDevice device);
+ /** An already discovered {@link BluetoothDevice} has been updated. */
+ public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device);
+ /** An already discovered {@link BluetoothDevice} has been removed or lost. */
+ public void deviceRemoved(final BluetoothAdapter adapter, final BluetoothDevice device);
+};
diff --git a/java/org/tinyb/BluetoothFactory.java b/java/org/tinyb/BluetoothFactory.java
index 8f01db15..38306a16 100644
--- a/java/org/tinyb/BluetoothFactory.java
+++ b/java/org/tinyb/BluetoothFactory.java
@@ -39,12 +39,12 @@ public class BluetoothFactory {
/**
* Name of the native implementation native library basename: {@value}
*/
- public static final String ImplNativeLibBasename = "tinyb";
+ public static final String ImplNativeLibBasename = "direct_bt"; // "tinyb";
/**
* Name of the Jave native library basename: {@value}
*/
- public static final String JavaNativeLibBasename = "javatinyb";
+ public static final String JavaNativeLibBasename = "javadirect_bt"; // "javatinyb";
/**
* Manifest's {@link Attributes.Name#SPECIFICATION_VERSION} or {@code null} if not available.
@@ -138,12 +138,12 @@ public class BluetoothFactory {
public static final String DBusFactoryImplClassName = "tinyb.dbus.DBusManager";
/**
- * Fully qualified factory class name for native HCI implementation: {@value}
+ * Fully qualified factory class name for direct_bt implementation: {@value}
* <p>
* This value is exposed for convenience, user implementations are welcome.
* </p>
*/
- public static final String HCIFactoryImplClassName = "tinyb.hci.HCIManager";
+ public static final String DirectBTFactoryImplClassName = "direct_bt.tinyb.Manager";
/**
* Returns an initialized BluetoothManager instance using the given {@code factoryImplClass}.
@@ -187,7 +187,7 @@ public class BluetoothFactory {
* @throws InvocationTargetException
* @throws ClassNotFoundException
* @see {@link #DBusFactoryImplClassName}
- * @see {@link #HCIFactoryImplClassName}
+ * @see {@link #DirectBTFactoryImplClassName}
*/
public static synchronized BluetoothManager getBluetoothManager(final String factoryImplClassName)
throws BluetoothException, NoSuchMethodException, SecurityException,
diff --git a/java/org/tinyb/BluetoothManager.java b/java/org/tinyb/BluetoothManager.java
index ec1de2d7..b7bec3cb 100644
--- a/java/org/tinyb/BluetoothManager.java
+++ b/java/org/tinyb/BluetoothManager.java
@@ -181,4 +181,13 @@ public interface BluetoothManager
* @return TRUE if discovery is running
*/
public boolean getDiscovering() throws BluetoothException;
+
+ /**
+ * Release the native memory associated with this object and all related Bluetooth resources.
+ * The object should not be used following a call to close
+ * <p>
+ * Shutdown method is intended to allow a clean Bluetooth state at program exist.
+ * </p>
+ */
+ public void shutdown();
}
diff --git a/java/jni/HCIGattDescriptor.cxx b/java/org/tinyb/BluetoothUtils.java
index cefc6b4d..e7a0276b 100644
--- a/java/jni/HCIGattDescriptor.cxx
+++ b/java/org/tinyb/BluetoothUtils.java
@@ -1,4 +1,4 @@
-/*
+/**
* Author: Sven Gothel <[email protected]>
* Copyright (c) 2020 Gothel Software e.K.
* Copyright (c) 2020 ZAFENA AB
@@ -22,13 +22,13 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+package org.tinyb;
-#include "direct_bt/HCITypes.hpp"
+public class BluetoothUtils {
-#include "tinyb_hci_HCIGattDescriptor.h"
-
-#include "JNIMem.hpp"
-#include "helper_base.hpp"
-
-using namespace direct_bt;
+ /**
+ * Returns current monotonic time in milliseconds.
+ */
+ public static native long getCurrentMilliseconds();
+}
diff --git a/java/tinyb/dbus/DBusAdapter.java b/java/tinyb/dbus/DBusAdapter.java
index 695677fe..973d3e8d 100644
--- a/java/tinyb/dbus/DBusAdapter.java
+++ b/java/tinyb/dbus/DBusAdapter.java
@@ -35,6 +35,7 @@ import java.util.UUID;
import org.tinyb.BluetoothAdapter;
import org.tinyb.BluetoothDevice;
+import org.tinyb.BluetoothDeviceDiscoveryListener;
import org.tinyb.BluetoothException;
import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothNotification;
@@ -148,6 +149,11 @@ public class DBusAdapter extends DBusObject implements BluetoothAdapter
public native boolean getDiscovering();
@Override
+ public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener l) {
+ throw new UnsupportedOperationException(); // FIXME
+ }
+
+ @Override
public native void enableDiscoveringNotifications(BluetoothNotification<Boolean> callback);
@Override
diff --git a/java/tinyb/dbus/DBusManager.java b/java/tinyb/dbus/DBusManager.java
index 2b5efe65..bfcd5e4b 100644
--- a/java/tinyb/dbus/DBusManager.java
+++ b/java/tinyb/dbus/DBusManager.java
@@ -134,4 +134,9 @@ public class DBusManager implements BluetoothManager
{
delete();
}
+
+ @Override
+ public void shutdown() {
+ delete();
+ }
}
diff --git a/java/tinyb/hci/HCIAdapter.java b/java/tinyb/hci/HCIAdapter.java
deleted file mode 100644
index 71c9d818..00000000
--- a/java/tinyb/hci/HCIAdapter.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Author: Sven Gothel <[email protected]>
- * Copyright (c) 2020 Gothel Software e.K.
- * Copyright (c) 2020 ZAFENA AB
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-package tinyb.hci;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
-import org.tinyb.BluetoothAdapter;
-import org.tinyb.BluetoothDevice;
-import org.tinyb.BluetoothException;
-import org.tinyb.BluetoothManager;
-import org.tinyb.BluetoothNotification;
-import org.tinyb.BluetoothType;
-import org.tinyb.TransportType;
-
-public class HCIAdapter extends HCIObject implements BluetoothAdapter
-{
- private final String address;
- private final String name;
-
- /* pp */ HCIAdapter(final String address, final String name)
- {
- super(compHash(address, name));
- this.address = address;
- this.name = name;
- }
-
- @Override
- public boolean equals(final Object obj)
- {
- if (obj == null || !(obj instanceof HCIDevice)) {
- return false;
- }
- final HCIAdapter other = (HCIAdapter)obj;
- return address.equals(other.address) && name.equals(other.name);
- }
-
- @Override
- public String getAddress() { return address; }
-
- @Override
- public String getName() { return name; }
-
- public String getInterfaceName() {
- throw new UnsupportedOperationException(); // FIXME
- }
-
- @Override
- public native BluetoothType getBluetoothType();
-
- @Override
- public native BluetoothAdapter clone();
-
- static BluetoothType class_type() { return BluetoothType.ADAPTER; }
-
- @Override
- public BluetoothDevice find(final String name, final String address, final long timeoutMS) {
- final BluetoothManager manager = HCIManager.getBluetoothManager();
- return (BluetoothDevice) manager.find(BluetoothType.DEVICE, name, address, this, timeoutMS);
- }
-
- @Override
- public BluetoothDevice find(final String name, final String address) {
- return find(name, address, 0);
- }
-
- /* D-Bus method calls: */
-
- @Override
- public native boolean startDiscovery() throws BluetoothException;
-
- @Override
- public native boolean stopDiscovery() throws BluetoothException;
-
- @Override
- public native List<BluetoothDevice> getDevices();
-
- @Override
- public native int removeDevices() throws BluetoothException;
-
- /* D-Bus property accessors: */
-
- @Override
- public native String getAlias();
-
- @Override
- public native void setAlias(String value);
-
- @Override
- public native long getBluetoothClass();
-
- @Override
- public native boolean getPowered();
-
- @Override
- public native void enablePoweredNotifications(BluetoothNotification<Boolean> callback);
-
- @Override
- public native void disablePoweredNotifications();
-
- @Override
- public native void setPowered(boolean value);
-
- @Override
- public native boolean getDiscoverable();
-
- @Override
- public native void enableDiscoverableNotifications(BluetoothNotification<Boolean> callback);
-
- @Override
- public native void disableDiscoverableNotifications();
-
- @Override
- public native void setDiscoverable(boolean value);
-
- @Override
- public native long getDiscoverableTimeout();
-
- @Override
- public native void setDiscoverableTimout(long value);
-
- @Override
- public native BluetoothDevice connectDevice(String address, String addressType);
-
- @Override
- public native boolean getPairable();
-
- @Override
- public native void enablePairableNotifications(BluetoothNotification<Boolean> callback);
-
- @Override
- public native void disablePairableNotifications();
-
- @Override
- public native void setPairable(boolean value);
-
- @Override
- public native long getPairableTimeout();
-
- @Override
- public native void setPairableTimeout(long value);
-
- @Override
- public native boolean getDiscovering();
-
- @Override
- public native void enableDiscoveringNotifications(BluetoothNotification<Boolean> callback);
-
- @Override
- public native void disableDiscoveringNotifications();
-
- @Override
- public native String[] getUUIDs();
-
- @Override
- public native String getModalias();
-
- @Override
- public void setDiscoveryFilter(final List<UUID> uuids, final int rssi, final int pathloss, final TransportType transportType) {
- final List<String> uuidsFmt = new ArrayList<>(uuids.size());
- for (final UUID uuid : uuids) {
- uuidsFmt.add(uuid.toString());
- }
- setDiscoveryFilter(uuidsFmt, rssi, pathloss, transportType.ordinal());
- }
-
- public void setRssiDiscoveryFilter(final int rssi) {
- setDiscoveryFilter(Collections.EMPTY_LIST, rssi, 0, TransportType.AUTO);
- }
-
- private native void delete();
-
- private native void setDiscoveryFilter(List<String> uuids, int rssi, int pathloss, int transportType);
-}