From e274309d9293777aaaecebccaa29a339a05bd4f9 Mon Sep 17 00:00:00 2001 From: Emanoil Kotsev Date: Mon, 12 Nov 2018 21:18:37 +0100 Subject: Based on KDE3 bluez4 version a TDE bluez5 version was created Signed-off-by: Emanoil Kotsev --- src/libtdebluez/CMakeLists.txt | 96 +++++ src/libtdebluez/README | 29 ++ src/libtdebluez/adapterImpl.cpp | 144 +++++++ src/libtdebluez/adapterImpl.h | 59 +++ src/libtdebluez/btuuids.h | 148 ++++++++ src/libtdebluez/deviceImpl.cpp | 49 +++ src/libtdebluez/deviceImpl.h | 62 +++ src/libtdebluez/devicemimeconverter.cpp | 147 ++++++++ src/libtdebluez/devicemimeconverter.h | 53 +++ src/libtdebluez/interfaces/CMakeLists.txt | 135 +++++++ src/libtdebluez/objectmanagerImpl.cpp | 607 ++++++++++++++++++++++++++++++ src/libtdebluez/objectmanagerImpl.h | 177 +++++++++ 12 files changed, 1706 insertions(+) create mode 100644 src/libtdebluez/CMakeLists.txt create mode 100644 src/libtdebluez/README create mode 100644 src/libtdebluez/adapterImpl.cpp create mode 100644 src/libtdebluez/adapterImpl.h create mode 100644 src/libtdebluez/btuuids.h create mode 100644 src/libtdebluez/deviceImpl.cpp create mode 100644 src/libtdebluez/deviceImpl.h create mode 100644 src/libtdebluez/devicemimeconverter.cpp create mode 100644 src/libtdebluez/devicemimeconverter.h create mode 100644 src/libtdebluez/interfaces/CMakeLists.txt create mode 100644 src/libtdebluez/objectmanagerImpl.cpp create mode 100644 src/libtdebluez/objectmanagerImpl.h (limited to 'src/libtdebluez') diff --git a/src/libtdebluez/CMakeLists.txt b/src/libtdebluez/CMakeLists.txt new file mode 100644 index 0000000..bb80327 --- /dev/null +++ b/src/libtdebluez/CMakeLists.txt @@ -0,0 +1,96 @@ +################################################# +# +# (C) 2018 Emanoil Kotsev +# deloptes (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +project( libtdebluez ) +set(LIBRARY_VERSION 0.0.1) + +# include( ConfigureChecks.cmake ) +foreach( f ${TQT_LIBRARIES} ) + if( ${f} STREQUAL "tqt-mt" ) + set(TQUI_LIBRARIES "tqui" CACHE TYPE STRING FORCE) + endif() + if( ${f} STREQUAL "qt-mt" ) + set(TQUI_LIBRARIES "qui" CACHE TYPE STRING FORCE) + endif() +endforeach() + +# import required +#tde_import( lib... ) + +add_subdirectory( interfaces ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${DBUS_INCLUDE_DIRS} + ${DBUS_TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + +##### headers ################################### +# implementations +install( + FILES adapterImpl.h + btuuids.h + deviceImpl.h + devicemimeconverter.h + objectmanagerImpl.h + DESTINATION ${INCLUDE_INSTALL_DIR}/tdebluez ) + +##### other data ################################ +# install( FILES xxxxxxxx.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) + +##### tdebluetoothwidgets (module) #################### +# +# add_custom_command( OUTPUT tdebluetoothwidgets.cpp +# COMMAND +# ${KDE3_MAKETDEWIDGETS_EXECUTABLE} +# -o tdebluetoothwidgets.cpp +# ${CMAKE_CURRENT_SOURCE_DIR}/tdebluez.widgets +# DEPENDS +# ${CMAKE_CURRENT_SOURCE_DIR}/tdebluez.widgets ) +# +# set_source_files_properties( tdebluetoothwidgets.cpp PROPERTIES COMPILE_FLAGS "-DQT_PLUGIN" ) +# +# tde_add_kpart( tdebluetoothwidgets +# SOURCES tdebluetoothwidgets.cpp +# LINK tdebluez-shared +# DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/designer +# ) + +set( target tdebluez ) + +set( ${target}_SRCS + objectmanagerImpl.cpp + adapterImpl.cpp + deviceImpl.cpp + devicemimeconverter.cpp +# agent/introspectableinterface.cpp agent/org_trinitydesktop_tdeblueznode.cpp + ) + +##### tdebluez (shared) ########################### +# set( KDE3_DCOPIDL_EXECUTABLE ${KDE3_DCOPIDLNG_EXECUTABLE} ) +tde_add_library( ${target} SHARED AUTOMOC + SOURCES ${${target}_SRCS} + VERSION ${LIBRARY_VERSION} + DEPENDS bluezinterfaces-static + LINK ${DBUS_TQT_LIBRARIES} tdeparts-shared bluezinterfaces-static ${TQUI_LIBRARIES} + DESTINATION ${LIB_INSTALL_DIR} + ) + +##### install import cmake modules ############### +tde_install_export( ) diff --git a/src/libtdebluez/README b/src/libtdebluez/README new file mode 100644 index 0000000..fa8b639 --- /dev/null +++ b/src/libtdebluez/README @@ -0,0 +1,29 @@ +interfaces + source interfaces for autogenerating with dbusxml2qt3 +libtdebluez/ + Implementations and other files part of the library + +libtdebluez/ + +libtdebluez/interfaces + interfaces autogenerated with dbusxml2qt3 + - autogenerated proxy to objectmanager + - adapter + adapter1 proxy + gattmanager1 proxy + media1 proxy + neworkserver1 proxy + - obexagent + autogenerated obex agent - interface and proxy + - properties + autogenerated dbus properties proxy + - device + autogenerated device1 proxy + autogenerated mediacontrol1 proxy + - agent + autogenerated agent1 interface and proxy + autogenerated introspectable interface + autogenerated trinity desktop tdebluez node interface + - manager + autogenerated proxies to managers + \ No newline at end of file diff --git a/src/libtdebluez/adapterImpl.cpp b/src/libtdebluez/adapterImpl.cpp new file mode 100644 index 0000000..703f06f --- /dev/null +++ b/src/libtdebluez/adapterImpl.cpp @@ -0,0 +1,144 @@ +/* + * + * Adapter Implementation of bluez5 for libtdebluez + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#include "adapterImpl.h" + +namespace TDEBluetooth +{ + +AdapterImpl::AdapterImpl(const TQString& service, const TQString& path, TQObject* parent, const char* name) : + Adapter1Proxy(service, path, parent, name) /*,properties(service,path,parent,name)*/ +{ +} + +AdapterImpl::~AdapterImpl() +{ +} + +void AdapterImpl::powerOn(bool state) +{ + // https://www.kernel.org/doc/Documentation/rfkill.txt + // http://jwhsmith.net/2015/02/manipulating-rfkill-using-devices-programmatically/ + // https://cpp.hotexamples.com/examples/-/-/rfkill_alloc/cpp-rfkill_alloc-function-examples.html + // https://github.com/systemd/systemd/blob/main/src/rfkill/rfkill.c + + TQString device = getPath(); + device = device.replace(TQRegExp("^/.*/"), ""); + int hcidx = -1; + TQDir d("/sys/class/rfkill"); + d.setFilter(TQDir::Dirs); + for (int i = 0; i < d.count(); i++) + { + // expected is rfkill + TQFile f("/sys/class/rfkill/" + d[i] + "/name"); + TQString content; + if (f.exists() && f.open(IO_ReadOnly)) + { + TQTextStream stream(&f); + content = stream.readLine(); + f.close(); + } + else + { + continue; + } + if (content.startsWith(device)) + { + TQFile f("/sys/class/rfkill/" + d[i] + "/index"); + if (f.exists() && f.open(IO_ReadOnly)) + { + TQTextStream stream(&f); + hcidx = stream.readLine().toUInt(); + f.close(); + } + break; + } + } + + if (hcidx < 0) + { + // error handling + tqDebug("Index for the device %s not found", device.local8Bit().data()); + return; + } + + struct rfkill_event event = { 0 }; + + TQFile file("/dev/rfkill"); + if (!file.open(IO_ReadWrite)) + { + tqDebug("Failed to open %s", file.name().utf8().data()); + return; + } + + event.idx = hcidx; + event.op = RFKILL_OP_CHANGE; + if (state) + event.soft = 0; + else + event.soft = 1; + + tqDebug("Bluetooth device %s switches: idx(%i), soft(%d).", device.local8Bit().data(), event.idx, event.soft); + + if (write(file.handle(), &event, sizeof(event)) < 0) + tqDebug("Failed to write to %s", file.name().utf8().data()); + file.close(); +} + +TQString AdapterImpl::getPath() +{ + return TQString(m_baseProxy->path()); +} + +void AdapterImpl::slotSetAlias(const TQString& alias) +{ + TQT_DBusError error; + setAlias(alias, error); + if (error.isValid()) + tqDebug("AdapterImpl::slotSetAlias(%s) failed: %s", alias.utf8().data(), error.message().utf8().data()); +} + +void AdapterImpl::slotSetTimeout(int timeout) +{ + TQT_DBusError error; + setDiscoverableTimeout(timeout, error); + if (error.isValid()) + tqDebug("AdapterImpl::slotSetTimeout(%i) failed: %s", timeout, error.message().utf8().data()); +} + +} // namespace TDEBluetooth + +#include "adapterImpl.moc" +// End of File diff --git a/src/libtdebluez/adapterImpl.h b/src/libtdebluez/adapterImpl.h new file mode 100644 index 0000000..e192a17 --- /dev/null +++ b/src/libtdebluez/adapterImpl.h @@ -0,0 +1,59 @@ +/* + * + * Adapter Implementation of bluez5 for libtdebluez + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#if !defined(ADAPTERIMPL_H_INCLUDED) +#define ADAPTERIMPL_H_INCLUDED + +#include "interfaces/adapter1Proxy.h" + +using namespace org::bluez; + +namespace TDEBluetooth +{ + +class AdapterImpl: public Adapter1Proxy +{ + Q_OBJECT + +public: + AdapterImpl(const TQString& service, const TQString& path, TQObject* parent = 0, const char* name = 0); + + virtual ~AdapterImpl(); + void powerOn(bool state); + TQString getPath(); + +public slots: + void slotSetAlias(const TQString& alias); + void slotSetTimeout(int timeout); + +}; +// class AdapterImpl + +}; +// namespace TDEBluetooth + +#endif //ADAPTERIMPL_H_INCLUDED + +// End of File diff --git a/src/libtdebluez/btuuids.h b/src/libtdebluez/btuuids.h new file mode 100644 index 0000000..597f037 --- /dev/null +++ b/src/libtdebluez/btuuids.h @@ -0,0 +1,148 @@ +/* + * + * List of BT UUIDs and resolver for libtdebluez + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/* + * This was taken from bluez/lib/uuid.h 2018-07-22 + * + */ + + +#include +#include + +#ifndef BTUUIDS_H_ +#define BTUUIDS_H_ + +static const std::map my_map = +{ + { "00001203-0000-1000-8000-00805f9b34fb", "Generic Audio" }, + { "00001108-0000-1000-8000-00805f9b34fb", "Headset" }, + { "00001112-0000-1000-8000-00805f9b34fb", "Headset AG" }, + + { "0000111e-0000-1000-8000-00805f9b34fb", "Handsfree" }, + { "0000111f-0000-1000-8000-00805f9b34fb", "Handsfree AG" }, + + { "0000110d-0000-1000-8000-00805f9b34fb", "Advanced Audio" }, + + { "0000110a-0000-1000-8000-00805f9b34fb", "A2DP Source" }, //Advanced Audio Distribution Profile + { "0000110b-0000-1000-8000-00805f9b34fb", "A2DP Sink" }, + + { "0000110e-0000-1000-8000-00805f9b34fb", "A/V Remote Ctrl" }, //Audio/Video Remote Control Profile + { "0000110c-0000-1000-8000-00805f9b34fb", "A/V Remote Ctrl Tgt" }, + + { "00001115-0000-1000-8000-00805f9b34fb", "PANU" }, + { "00001116-0000-1000-8000-00805f9b34fb", "NAP" }, + { "00001117-0000-1000-8000-00805f9b34fb", "GN" }, + { "0000000f-0000-1000-8000-00805f9b34fb", "BNEP Service" }, //Bluetooth Network Encapsulation Protocol + + { "00002a50-0000-1000-8000-00805f9b34fb", "PNPID" }, + { "0000180a-0000-1000-8000-00805f9b34fb", "Device Information" }, + + { "00001801-0000-1000-8000-00805f9b34fb", "GATT" }, //Generic Access Profile (Generic Attributes) + { "00001802-0000-1000-8000-00805f9b34fb", "Immediate Alert" }, + { "00001803-0000-1000-8000-00805f9b34fb", "Link Loss" }, + { "00001804-0000-1000-8000-00805f9b34fb", "TX Power" }, + + { "0000112d-0000-1000-8000-00805f9b34fb", "SAP" }, + + { "0000180d-0000-1000-8000-00805f9b34fb", "Heart Rate" }, + { "00002a37-0000-1000-8000-00805f9b34fb", "Heart Rate Measurement" }, + { "00002a38-0000-1000-8000-00805f9b34fb", "Body Sensor Location" }, + { "00002a39-0000-1000-8000-00805f9b34fb", "Heart Rate Control Point" }, + + { "00001809-0000-1000-8000-00805f9b34fb", "Health Thermometer" }, + { "00002a1c-0000-1000-8000-00805f9b34fb", "Temp Measurement" }, + { "00002a1d-0000-1000-8000-00805f9b34fb", "Temp Type" }, + { "00002a1e-0000-1000-8000-00805f9b34fb", "Immediate Temp" }, + { "00002a21-0000-1000-8000-00805f9b34fb", "Measurement Interval" }, + + { "00001816-0000-1000-8000-00805f9b34fb", "Cycling SC" }, + { "00002a5b-0000-1000-8000-00805f9b34fb", "CSC Measurement" }, + { "00002a5c-0000-1000-8000-00805f9b34fb", "CSC Feature" }, + { "00002a5d-0000-1000-8000-00805f9b34fb", "Sensor Location" }, + { "00002a55-0000-1000-8000-00805f9b34fb", "SC Control Point" }, + + { "00000003-0000-1000-8000-00805f9b34fb", "RFCOMM" }, + + { "00001400-0000-1000-8000-00805f9b34fb", "HDP" }, + { "00001401-0000-1000-8000-00805f9b34fb", "HDP Source" }, + { "00001402-0000-1000-8000-00805f9b34fb", "HDP Sink" }, + + { "00001124-0000-1000-8000-00805f9b34fb", "HID" }, + + { "00001103-0000-1000-8000-00805f9b34fb", "DUN Gateway" }, //Dial-up Networking Profile + + { "00001800-0000-1000-8000-00805f9b34fb", "GAP" }, //Generic Access Profile + { "00001200-0000-1000-8000-00805f9b34fb", "PNP" }, + + { "00001101-0000-1000-8000-00805f9b34fb", "SPP" }, //Serial Port Profile + + { "00001104-0000-1000-8000-00805f9b34fb", "OBEX Sync" }, + { "00001105-0000-1000-8000-00805f9b34fb", "OBEX OPP" }, + { "00001106-0000-1000-8000-00805f9b34fb", "OBEX FTP" }, + { "f9ec7bc4-953c-11d2-984e-525400dc9e09", "OBEX DIR" }, + { "0000112e-0000-1000-8000-00805f9b34fb", "OBEX PCE" }, + { "0000112f-0000-1000-8000-00805f9b34fb", "OBEX PSE" }, + { "00001130-0000-1000-8000-00805f9b34fb", "OBEX PBAP" }, + { "00001132-0000-1000-8000-00805f9b34fb", "OBEX Msg Access Srv" }, + { "00001133-0000-1000-8000-00805f9b34fb", "OBEX Msg Notif. Srv" }, + { "00001134-0000-1000-8000-00805f9b34fb", "OBEX MAP" }, + // taken from + // https://www.vistax64.com/threads/bluetooth-peripheral-device-cannot-be-found.62944/ + // https://together.jolla.com/question/64565/accessing-bluetooth-profiles/ + // http://www.sensi.org/~ak/tmp/n95.txt + { "00005005-0000-1000-8000-0002ee000001", "Nokia PC Suite" }, + { "00005601-0000-1000-8000-0002ee000001", "Nokia SyncML Server" }, + { "00000001-0000-1000-8000-0002ee000001", "SyncML Server" }, + { "00000002-0000-1000-8000-0002ee000002", "OBEX Syncevolution" }, + { "00000004-0000-1000-8000-0002ee000002", "SyncML DM Client" } + +}; + +/*! + * This function resolves UUID to human readable service name. + * \return string service name + * \retval the service name + */ + +static const TQString resolveUUID(const TQString &uuid) +{ + + TQString name; + + for (auto i = my_map.begin(); i != my_map.end(); ++i) + { + if (i->first == uuid.latin1()) + { + name = TQString(i->second.c_str()); + break; + } + } + // name = i18n("Unknown"); + return (!name.isEmpty()) ? name : uuid; +} + +#endif // BTUUIDS_H_ diff --git a/src/libtdebluez/deviceImpl.cpp b/src/libtdebluez/deviceImpl.cpp new file mode 100644 index 0000000..7b8a971 --- /dev/null +++ b/src/libtdebluez/deviceImpl.cpp @@ -0,0 +1,49 @@ +/* + * + * Device Implementation of bluez5 for libtdebluez + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "deviceImpl.h" + +namespace TDEBluetooth +{ + +DeviceImpl::DeviceImpl(const TQString& service, const TQString& path, TQObject* parent, const char* name) : org::bluez::Device1Proxy(service, path, parent, name) +{ + m_path = path; +} + +DeviceImpl::~DeviceImpl() +{ +} + +const TQString DeviceImpl::getPath() +{ + return m_path; +} + +}; +// namespace TDEBluetooth + +#include "deviceImpl.moc" +// End of File diff --git a/src/libtdebluez/deviceImpl.h b/src/libtdebluez/deviceImpl.h new file mode 100644 index 0000000..45b355b --- /dev/null +++ b/src/libtdebluez/deviceImpl.h @@ -0,0 +1,62 @@ +/* + * + * Device Implementation of bluez5 for libtdebluez + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#if !defined(DEVICEIMPL_H_INCLUDED) +#define DEVICEIMPL_H_INCLUDED + +// QT - Header +#include + +// debug +#include + +#include "interfaces/device1Proxy.h" +#include "interfaces/propertiesProxy.h" + +namespace TDEBluetooth +{ + +class DeviceImpl: public org::bluez::Device1Proxy +{ + Q_OBJECT + +public: + DeviceImpl(const TQString& service, const TQString& path, TQObject* parent = 0, const char* name = 0); + + virtual ~DeviceImpl(); + const TQString getPath(); + +private: + TQString m_path; + +}; +// class DeviceImpl + +}; +// namespace TDEBluetooth + +#endif //DEVICEIMPL_H_INCLUDED + +// End of File diff --git a/src/libtdebluez/devicemimeconverter.cpp b/src/libtdebluez/devicemimeconverter.cpp new file mode 100644 index 0000000..b14669e --- /dev/null +++ b/src/libtdebluez/devicemimeconverter.cpp @@ -0,0 +1,147 @@ +/* + * + * Device Mime Converter for libtdebluez + * + * Copyright (C) 2003 by Fred Schaettgen + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include "devicemimeconverter.h" + +namespace TDEBluetooth +{ + +DeviceMimeConverter::DeviceMimeConverter() +{ + getIconName("bluetooth/unknown-device-class"); + getIconName("bluetooth/misc-device-class"); + getIconName("bluetooth/computer-device-class"); + getIconName("bluetooth/phone-device-class"); + getIconName("bluetooth/lan-device-class"); + getIconName("bluetooth/av-device-class"); + getIconName("bluetooth/peripheral-device-class"); + getIconName("bluetooth/mouse-device-class"); + getIconName("bluetooth/keyboard-device-class"); + getIconName("bluetooth/imaging-device-class"); +} + +void DeviceMimeConverter::getIconName(TQString mime) +{ + TQString iconName = KMimeType::mimeType(mime)->icon(TQString::null, false); + mimeTypeToIconMap[mime] = iconName; +} + +DeviceMimeConverter* DeviceMimeConverter::getInstance() +{ + static DeviceMimeConverter instance; + return &instance; +} + +TQString DeviceMimeConverter::classToIconName(int n) +{ + return DeviceMimeConverter::mimeTypeToIcon(DeviceMimeConverter::classToMimeType(n)); +} + +/* + * device classes + * + AUDIO_VIDEO (Value: 0x00000400) + COMPUTER (Value: 0x00000100) + HEALTH (Value: 0x00000900) + IMAGING (Value: 0x00000600) + MISC (Value: 0x00000000) + NETWORKING (Value: 0x00000300) + PERIPHERAL (Value: 0x00000500) + PHONE (Value: 0x00000200) + TOY (Value: 0x00000800) + UNCATEGORIZED (Value: 0x00001f00) + WEARABLE (Value: 0x00000700) +*/ + +TQString DeviceMimeConverter::classToMimeType(int n) +{ + TQString mimeType; + int major = ((n & 0x001F00) >> 8); + int minor = ((n >> 2) & 0x30); + switch (major) + { + case 0x00: + mimeType = "bluetooth/misc-device-class"; + break; + case 0x01: + mimeType = "bluetooth/computer-device-class"; + break; + case 0x02: + mimeType = "bluetooth/phone-device-class"; + break; + case 0x03: + mimeType = "bluetooth/lan-device-class"; + break; + case 0x04: + mimeType = "bluetooth/av-device-class"; + break; + case 0x05: + switch (minor) + { + case 0x10: + mimeType = "bluetooth/keyboard-device-class"; + break; + case 0x20: + mimeType = "bluetooth/mouse-device-class"; + break; + default: + mimeType = "bluetooth/peripheral-device-class"; + } + break; + case 0x06: + mimeType = "bluetooth/imaging-device-class"; + break; + case 0x07: + mimeType = "bluetooth/wearable-device-class"; + break; + case 0x08: + mimeType = "bluetooth/toy-device-class"; + break; + case 0x09: + mimeType = "bluetooth/health-device-class"; + break; + default: + mimeType = "bluetooth/unknown-device-class"; + } + return mimeType; +} + +TQString DeviceMimeConverter::mimeTypeToIcon(TQString mime) +{ + DeviceMimeConverter* c = DeviceMimeConverter::getInstance(); + if (c->mimeTypeToIconMap.find(mime) != c->mimeTypeToIconMap.end()) + { + return c->mimeTypeToIconMap[mime]; + } + else + { + return c->mimeTypeToIconMap["bluetooth/unknown-device-class"]; + } +} + +} // TDEBluetooth diff --git a/src/libtdebluez/devicemimeconverter.h b/src/libtdebluez/devicemimeconverter.h new file mode 100644 index 0000000..63a1d9f --- /dev/null +++ b/src/libtdebluez/devicemimeconverter.h @@ -0,0 +1,53 @@ +/* + * + * Device Mime Converter for libtdebluez + * + * Copyright (C) 2003 by Fred Schaettgen + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef DEVICEMIMECONVERTER_H +#define DEVICEMIMECONVERTER_H + +#include + +namespace TDEBluetooth +{ +/** + @author Fred Schaettgen + */ +class DeviceMimeConverter +{ +public: + static TQString classToMimeType(int deviceClass); + static TQString mimeTypeToIcon(TQString mimeType); + static TQString classToIconName(int deviceClass); +protected: + DeviceMimeConverter(); + static DeviceMimeConverter *getInstance(); +private: + std::map mimeTypeToIconMap; + void getIconName(TQString mimetype); +}; + +} // TDEBluetooth + +#endif diff --git a/src/libtdebluez/interfaces/CMakeLists.txt b/src/libtdebluez/interfaces/CMakeLists.txt new file mode 100644 index 0000000..2f44a83 --- /dev/null +++ b/src/libtdebluez/interfaces/CMakeLists.txt @@ -0,0 +1,135 @@ +################################################# +# +# (C) 2020 Emanoil Kotsev +# deloptes (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TQT_INCLUDE_DIRS} + ${DBUS_TQT_INCLUDE_DIRS} +) + +set( INTROSPECTIONPATH ${CMAKE_SOURCE_DIR}/src/interfaces ) +set( DBUSXML2QT3_EXECUTABLE dbusxml2qt3 ) + +set( ObjectManager_HDRS objectmanagerInterface.h objectmanagerProxy.h introspectableInterface.h ) +set( ObjectManager_SRCS objectmanagerInterface.cpp objectmanagerProxy.cpp introspectableInterface.cpp) + +set( AgentManager_HDRS agentmanager1Interface.h agentmanager1Proxy.h healthmanager1Interface.h healthmanager1Proxy.h profilemanager1Interface.h profilemanager1Proxy.h ) +set( AgentManager_SRCS agentmanager1Interface.cpp agentmanager1Proxy.cpp healthmanager1Interface.cpp healthmanager1Proxy.cpp profilemanager1Interface.cpp profilemanager1Proxy.cpp ) + +set( Agent_HDRS agent1Interface.h agent1Proxy.h dbusbaseNode.h tdebluezNode.h ) +set( Agent_SRCS agent1Interface.cpp agent1Proxy.cpp dbusbaseNode.cpp tdebluezNode.cpp ) + +set( Adapter_HDRS adapter1Interface.h adapter1Proxy.h gattmanager1Interface.h gattmanager1Proxy.h media1Interface.h media1Proxy.h networkserver1Interface.h networkserver1Proxy.h propertiesInterface.h propertiesProxy.h) +set( Adapter_SRCS adapter1Interface.cpp adapter1Proxy.cpp gattmanager1Interface.cpp gattmanager1Proxy.cpp media1Interface.cpp media1Proxy.cpp networkserver1Interface.cpp networkserver1Proxy.cpp propertiesInterface.cpp propertiesProxy.cpp ) + +set( Device_HDRS device1Interface.h device1Proxy.h mediacontrol1Interface.h mediacontrol1Proxy.h) +set( Device_SRCS device1Interface.cpp device1Proxy.cpp mediacontrol1Interface.cpp mediacontrol1Proxy.cpp ) + +function( make_moc fileinput ) + add_custom_command( OUTPUT ${fileinput}.moc + COMMAND ${TMOC_EXECUTABLE} ${fileinput}.h -o ${fileinput}.moc + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${fileinput}.h + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + set_property( SOURCE ${CMAKE_CURRENT_BINARY_DIR}/${fileinput}.cpp APPEND + PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${fileinput}.moc ) +endfunction( ) + +#function( install_header fileinput target ) +# install( +# FILES ${CMAKE_CURRENT_BUILD_DIR}/${fileinput} +# DESTINATION ${target} +# ) +#endfunction( ) + + +##### ObjectManager ######################### +add_custom_command( + OUTPUT ${ObjectManager_HDRS} ${ObjectManager_SRCS} + COMMAND ${DBUSXML2QT3_EXECUTABLE} ${INTROSPECTIONPATH}/org.freedesktop.DBus.ObjectManager.xml 2>/dev/null + DEPENDS ${INTROSPECTIONPATH}/org.freedesktop.DBus.ObjectManager.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +make_moc ( objectmanagerProxy ) + +##### AgentManager ######################### +add_custom_command( + OUTPUT ${AgentManager_HDRS} ${AgentManager_SRCS} + COMMAND ${DBUSXML2QT3_EXECUTABLE} ${INTROSPECTIONPATH}/org.bluez.manager.xml 2>/dev/null + DEPENDS ${INTROSPECTIONPATH}/org.bluez.manager.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +make_moc ( agentmanager1Proxy ) +make_moc ( healthmanager1Proxy ) +make_moc ( profilemanager1Proxy ) + +##### Agent ######################### +add_custom_command( + OUTPUT ${Agent_HDRS} ${Agent_SRCS} + COMMAND ${DBUSXML2QT3_EXECUTABLE} ${INTROSPECTIONPATH}/org.tdebluez.agent.xml 2>/dev/null + DEPENDS ${INTROSPECTIONPATH}/org.tdebluez.agent.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +make_moc ( agent1Proxy ) + +##### Adapter ######################### +add_custom_command( + OUTPUT ${Adapter_HDRS} ${Adapter_SRCS} + COMMAND ${DBUSXML2QT3_EXECUTABLE} ${INTROSPECTIONPATH}/org.bluez.adapter.xml 2>/dev/null + DEPENDS ${INTROSPECTIONPATH}/org.bluez.adapter.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +make_moc ( adapter1Proxy ) +make_moc ( gattmanager1Proxy ) +make_moc ( networkserver1Proxy ) +make_moc ( propertiesProxy ) + +##### Device ######################### +add_custom_command( + OUTPUT ${Device_HDRS} ${Device_SRCS} + COMMAND ${DBUSXML2QT3_EXECUTABLE} ${INTROSPECTIONPATH}/org.bluez.device.xml 2>/dev/null + DEPENDS ${INTROSPECTIONPATH}/org.bluez.device.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +make_moc ( device1Proxy ) +make_moc ( propertiesProxy ) +make_moc ( mediacontrol1Proxy ) +make_moc ( media1Proxy ) + +tde_add_library( bluezinterfaces STATIC_PIC AUTOMOC + SOURCES ${ObjectManager_SRCS} ${AgentManager_SRCS} ${Agent_SRCS} ${Adapter_SRCS} ${Device_SRCS} + LINK ${DBUS_TQT_LIBRARIES} +) + +##### install headers ################################### + + +#file( GLOB _bin_dirs RELATIVE ${CMAKE_CURRENT_BINARY_DIR} +#      ${CMAKE_CURRENT_BINARY_DIR}/* ) +#unset( _exclude_dirs ) +#foreach( _dir IN LISTS _bin_dirs ) +#  if(IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_dir} ) +#    list( APPEND _exclude_dirs PATTERN ${_dir} EXCLUDE ) +#  endif() +#endforeach() +# +#install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +# DESTINATION ${INCLUDE_INSTALL_DIR}/tdeobex +# USE_SOURCE_PERMISSIONS +# FILES_MATCHING PATTERN PATTERN "*.h" +# ${_exclude_dirs} +#) + +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DESTINATION ${INCLUDE_INSTALL_DIR}/tdebluez + USE_SOURCE_PERMISSIONS + FILES_MATCHING PATTERN PATTERN "*.h" + PATTERN "CMakeFiles" EXCLUDE) diff --git a/src/libtdebluez/objectmanagerImpl.cpp b/src/libtdebluez/objectmanagerImpl.cpp new file mode 100644 index 0000000..789e221 --- /dev/null +++ b/src/libtdebluez/objectmanagerImpl.cpp @@ -0,0 +1,607 @@ +/* + * + * Object Manager implementation of bluez5 + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "objectmanagerImpl.h" +#include "btuuids.h" + +namespace TDEBluetooth +{ + +ObjectManagerImpl::ObjectManagerImpl(const TQString& service, const TQString& path, TQObject* parent, const char* name) : + ObjectManagerProxy(service, path, parent, name) +{ + agentManager = 0; + profileManager = 0; + healthManager = 0; + agentRegisteredStatus = false; + agentIsDefaultAgent = false; + // init connection to dbus + initDBUS(); +} + +ObjectManagerImpl::~ObjectManagerImpl() +{ + // close D-Bus connection + close(); + + if(agentManager) + delete agentManager; + if(profileManager) + delete profileManager; + if(healthManager) + delete healthManager; +} + +/*! + * This function try a reconnect to D-Bus. + * \return boolean with the result of the operation + * \retval true if successful reconnected to D-Bus + * \retval false if unsuccessful + */ +bool ObjectManagerImpl::reconnect() +{ + // close D-Bus connection + close(); + // init D-Bus conntection + return (initDBUS()); +} + +/*! + * This function return information about connection status to the DBUS daemon. + * \return boolean with the state of the connection to D-Bus + * \retval true if connected + * \retval false if disconnected + */ +bool ObjectManagerImpl::isConnectedToDBUS() +{ + return dBusConn.isConnected(); +} + +/*! + * This function returns pointer to connection of the DBUS. + * \return TQT_DBusConnection* of the connection to D-Bus + * \retval TQT_DBusConnection* + */ +TQT_DBusConnection* ObjectManagerImpl::getConnection() +{ + return &dBusConn; +} + +/*! + * This function close the connection to manager over the D-Bus daemon. + * \return boolean with the result of the operation + * \retval true if successful closed the connection + * \retval false if any problems + */ +bool ObjectManagerImpl::close() +{ + disconnect(this, SIGNAL(InterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >&)), + this, SLOT(slotInterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >& ))); + disconnect(this, SIGNAL(InterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& )), + this, SLOT(slotInterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& ))); + + for (PropertiesMap::iterator it = adapters.begin(); it != adapters.end(); + ++it) + { + org::freedesktop::DBus::PropertiesProxy *p; + p = it.data(); + if (p != NULL) + delete p; + } + for (PropertiesMap::iterator it = devices.begin(); it != devices.end(); + ++it) + { + org::freedesktop::DBus::PropertiesProxy *p; + p = it.data(); + if (p != NULL) + delete p; + } + adapters.clear(); + devices.clear(); + + dBusConn.closeConnection(DBUS_CONN_NAME); + return true; +} + +/*! + * This function initializes the connection to the D-Bus daemon. + * \return pointer to AgentManager1Proxy + */ +AgentManager1Proxy * ObjectManagerImpl::getAgentManager() +{ + return agentManager; +} + +/*! + * This function initializes the connection to the D-Bus daemon. + * \return pointer to ProfileManager1Proxy + */ +ProfileManager1Proxy * ObjectManagerImpl::getProfileManager() +{ + return profileManager; +} + +/*! + * This function initializes the connection to the D-Bus daemon. + * \return pointer to HealthManager1Proxy + */ +HealthManager1Proxy * ObjectManagerImpl::getHealthManager() +{ + return healthManager; +} + +/*! + * This function returns a list of objectpaths + * \return TQValueList + * \retval TQValueList + */ +ObjectManagerImpl::AdapterList ObjectManagerImpl::getAdapters() +{ + return adapters.keys(); +} + +/*! + * This function returns a list of objectpaths + * \return TQValueList + * \retval TQValueList + */ +ObjectManagerImpl::DeviceList ObjectManagerImpl::getDevices() +{ + return devices.keys(); +} + +ObjectManagerImpl::ConnectionList ObjectManagerImpl::listConnections(const TQString &adapter) +{ + ConnectionList list; + return list; +} + +bool ObjectManagerImpl::registerAgent() +{ + if (!agentRegisteredStatus) + { + TQT_DBusError error; + agentManager->RegisterAgent( + TQT_DBusObjectPath(TQCString(DBUS_AUTH_SERVICE_PATH)), DEVICE_PIN_CAPABILITY, error); + if (error.isValid()) + { + tqDebug("Could not register agent: %s", error.message().local8Bit().data()); + return false; + } + agentRegisteredStatus = true; + } + return true; +} + +bool ObjectManagerImpl::unregisterAgent() +{ + kdDebug() << k_funcinfo << endl; + if (agentRegisteredStatus) + { + TQT_DBusError error; + getAgentManager()->UnregisterAgent( + TQT_DBusObjectPath(TQCString(DBUS_AUTH_SERVICE_PATH)), error); + if (error.isValid()) + { + tqDebug("Could not unregister agent"); + return false; + } + agentRegisteredStatus = false; + agentIsDefaultAgent = false; + } + return true; +} + +bool ObjectManagerImpl::requestDefaultAgent() +{ + TQT_DBusError error; + agentManager->RequestDefaultAgent( + TQT_DBusObjectPath(TQCString(DBUS_AUTH_SERVICE_PATH)), error); + if (error.isValid()) + { + tqDebug("Could not request default agent: %s", error.message().local8Bit().data()); + return false; + } + agentIsDefaultAgent = true; + return true; +} + +bool ObjectManagerImpl::isAgentRegistered() +{ + return agentRegisteredStatus; +} + +bool ObjectManagerImpl::isAgentDefaultAgent() +{ + return agentIsDefaultAgent; +} + +/*! + * This function initializes the connection to the D-Bus daemon. + * \return boolean with the result of the operation + * \retval true if successful initialized D-Bus connection + * \retval false if unsuccessful + */ +bool ObjectManagerImpl::initDBUS() +{ + dBusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus, DBUS_CONN_NAME); + if (!dBusConn.isConnected()) + { + tqDebug("Failed to open connection to system message bus: %s", dBusConn.lastError().message().local8Bit().data()); + TQTimer::singleShot(4000, this, TQT_SLOT(reconnect())); + return false; + } + setConnection(dBusConn); + + TQT_DBusDataMap objects; + TQT_DBusError error; + if (!GetManagedObjects(objects, error)) + { + tqDebug("GetManagedObjects(objects,error) FAILED:\n%s\n", error.message().latin1()); + return false; + } + + TQT_DBusDataMap::const_iterator it = objects.begin(); + for (it; it != objects.end(); ++it) + { + bool ok = false; + slotInterfacesAdded(it.key(), it.data().toStringKeyMap(&ok)); + if (!ok) + tqWarning("Failed to convert dbus data to string map: %s", it.key().latin1()); + } + + connect(this, SIGNAL(InterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >&)), + this, SLOT(slotInterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >& ))); + connect(this, SIGNAL(InterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& )), + this, SLOT(slotInterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& ))); + + return true; +} + +void ObjectManagerImpl::adapterPropertiesChanged(TQString path, const TQMap< + TQString, TQT_DBusVariant>& changed_properties) +{ + TQMap::const_iterator it; + for (it = changed_properties.begin(); it != changed_properties.end(); ++it) + { + bool ok = false; + if (it.key() == "Powered") + emit adapterPowerOnChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "Class") + emit adapterClassChanged(path, it.data().value.toUInt32(&ok)); + else if (it.key() == "Name") + emit adapterNameChanged(path, it.data().value.toString(&ok)); + else if (it.key() == "Alias") + emit adapterAliasChanged(path, it.data().value.toString(&ok)); + else if (it.key() == "DiscoverableTimeout") + emit adapterDiscoverableTimeoutChanged(path, it.data().value.toUInt32(&ok)); + else if (it.key() == "Discoverable") + emit adapterDiscoverableChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "Discovering") + emit adapterDiscoveringChanged(path, it.data().value.toBool(&ok)); + else + continue; + if (!ok) + tqDebug("ObjectManagerImpl::adapterPropertiesChanged conversion failed"); + } +} + +void ObjectManagerImpl::devicePropertiesChanged(TQString path, const TQMap& changed_properties) +{ + // https://github.com/r10r/bluez/blob/master/doc/device-api.txt + TQMap::const_iterator it; + for (it = changed_properties.begin(); it != changed_properties.end(); ++it) + { + bool ok = false; + if (it.key() == "Address") + emit deviceAddressChanged(path, it.data().value.toString(&ok)); + else if (it.key() == "Class") + emit deviceClassChanged(path, it.data().value.toUInt32(&ok)); + else if (it.key() == "Name") + emit deviceNameChanged(path, it.data().value.toString(&ok)); + else if (it.key() == "Alias") + emit deviceAliasChanged(path, it.data().value.toString(&ok)); +// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml + else if (it.key() == "Appearance") + emit deviceAppearanceChanged(path, it.data().value.toUInt16(&ok)); + else if (it.key() == "Icon") + emit deviceIconChanged(path, it.data().value.toString(&ok)); + else if (it.key() == "Paired") + emit devicePairedChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "Trusted") + emit deviceTrustedChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "Blocked") + emit deviceBlockedChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "LegacyPairing") + emit deviceLegacyPairingChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "RSSI") + emit deviceRSSIChanged(path, it.data().value.toInt16(&ok)); //INT16 + else if (it.key() == "Connected") + emit deviceConnectedChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "UUIDs") + { + TQT_DBusDataList vl = TQT_DBusDataList(it.data().value.toTQValueList(&ok)); + emit deviceUUIDsChanged(path, vl.toStringList(&ok)); + } + else if (it.key() == "Adapter") + emit deviceAdapterChanged(path, it.data().value.toObjectPath(&ok)); + else if (it.key() == "ManufacturerData") + emit deviceManufacturerDataChanged(path, it.data().value.toUInt16KeyMap(&ok)); //a{qv} + else if (it.key() == "ServiceData") + emit deviceServiceDataChanged(path, it.data().value.toStringKeyMap(&ok)); //a{sv} + else if (it.key() == "TxPower") + emit deviceTxPowerChanged(path, it.data().value.toInt16(&ok)); //INT16 + else if (it.key() == "ServicesResolved") + emit deviceServicesResolvedChanged(path, it.data().value.toBool(&ok)); + else + continue; + if (!ok) + tqDebug("ObjectManagerImpl::devicePropertiesChanged conversion failed"); + } + +} + +void ObjectManagerImpl::mediaControlPropertiesChanged(TQString path, const TQMap& changed_properties) +{ + TQMap::const_iterator it; + for (it = changed_properties.begin(); it != changed_properties.end(); ++it) + { + bool ok = false; + if (it.key() == "Connected") + emit mediaControlConnectedChanged(path, it.data().value.toBool(&ok)); + else if (it.key() == "Player") + emit mediaControlPlayerChanged(path, it.data().value.toObjectPath(&ok)); + else + continue; + if (!ok) + tqDebug("ObjectManagerImpl::mediaControlPropertiesChanged conversion failed"); + } +} + +void ObjectManagerImpl::slotInterfacesAdded(const TQT_DBusObjectPath& object, const TQT_DBusDataMap& interfaces) +{ + TQT_DBusDataMap::const_iterator it1 = interfaces.begin(); + for (it1; it1 != interfaces.end(); it1++) + { + TQString interface = it1.key(); + if (interface == "org.bluez.AgentManager1") + { + agentManager = new AgentManager1Proxy("org.bluez", object/*, this, "AgentManager1"*/); + if (agentManager) + agentManager->setConnection(dBusConn); + } + else if (interface == "org.bluez.ProfileManager1") + { + profileManager = new ProfileManager1Proxy("org.bluez", object/*, this, "ProfileManager1"*/); + if (profileManager) + profileManager->setConnection(dBusConn); + } + else if (interface == "org.bluez.HealthManager1") + { + healthManager = new HealthManager1Proxy("org.bluez", object/*, this, "HealthManager1"*/); + if (healthManager) + healthManager->setConnection(dBusConn); + } + else if (interface == "org.bluez.Adapter1") + { + org::freedesktop::DBus::PropertiesProxy *properties; + properties = new org::freedesktop::DBus::PropertiesProxy("org.bluez", object); + properties->setConnection(dBusConn); + connect(properties, SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& ))); + adapters.insert(TQString(object), properties); + //notify others + emit adapterAdded(TQString(object)); + } + else if (interface == "org.bluez.GattManager1") + { + kdDebug() << "Interface not implemented: org.bluez.GattManager1" << endl; + // TODO: Implement GattManager1 + } + else if (interface == "org.bluez.Media1") + { + kdDebug() << "Interface not implemented: org.bluez.Media1" << endl; + // TODO: Implement Media1 + } + else if (interface == "org.bluez.NetworkServer1") + { + kdDebug() << "Interface not implemented: org.bluez.NetworkServer1" << endl; + // TODO: Implement NetworkServer1 + } + else if (interface == "org.bluez.Device1") + { + org::freedesktop::DBus::PropertiesProxy *properties; + properties = new org::freedesktop::DBus::PropertiesProxy("org.bluez", object); + properties->setConnection(dBusConn); + connect(properties, SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& ))); + devices.insert(TQString(object), properties); + //notify others + emit deviceAdded(TQString(object)); + } + else if (interface == "org.bluez.MediaControl1") + { + kdDebug() << "Interface not implemented: org.bluez.MediaControl1" << endl; + kdDebug() << "as the media control is triggered via properties changed." << endl; + } + else if (interface == "org.bluez.MediaTransport1") + { + kdDebug() << "Interface not implemented: org.bluez.MediaTransport1" << endl; + // TODO: Implement MediaTransport1 + } + else if (interface == "org.freedesktop.DBus.Introspectable") + { + // do nothing + } + else if (interface == "org.freedesktop.DBus.Properties") + { + // do nothing + } + else + { + tqWarning("Interface not implemented: %s", interface.local8Bit().data()); + } + } +} + +void ObjectManagerImpl::slotInterfacesRemoved(const TQT_DBusObjectPath& object, const TQStringList& interfaces) +{ + // TODO: remove interface + for (TQValueListConstIterator it = interfaces.begin(); + it != interfaces.end(); ++it) + { + if ((*it) == "org.bluez.AgentManager1") + { + kdDebug() << "Remove org.bluez.AgentManager1" << endl; + // TODO: remove AgentManager1 + } + else if ((*it) == "org.bluez.ProfileManager1") + { + kdDebug() << "Interface not implemented: org.bluez.ProfileManager1" << endl; + // TODO: remove ProfileManager1 + } + else if ((*it) == "org.bluez.HealthManager1") + { + kdDebug() << "Interface not implemented: org.bluez.HealthManager1" << endl; + // TODO: remove HealthManager1 + } + else if ((*it) == "org.bluez.Adapter1") + { + kdDebug() << "Remove org.bluez.Adapter1" << endl; + disconnect(adapters[object], SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& ))); + adapters.remove(object); + emit adapterRemoved(TQString(object)); + } + else if ((*it) == "org.bluez.GattManager1") + { + kdDebug() << "Interface not implemented: org.bluez.GattManager1" << endl; + // TODO: Implement GattManager1 + } + else if ((*it) == "org.bluez.Media1") + { + kdDebug() << "Interface not implemented: org.bluez.Media1" << endl; + // TODO: Implement Media1 + } + else if ((*it) == "org.bluez.NetworkServer1") + { + kdDebug() << "Interface not implemented: org.bluez.NetworkServer1" << endl; + // TODO: Implement NetworkServer1 + } + else if ((*it) == "org.bluez.Device1") + { + kdDebug() << "Remove org.bluez.Device1" << endl; + disconnect(devices[object], SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& ))); + devices.remove(object); + emit deviceRemoved(TQString(object)); + } + else if ((*it) == "org.bluez.MediaControl1") + { + kdDebug() << "Interface not implemented: org.bluez.MediaControl1" << endl; + kdDebug() << "as the media control is triggered via properties changed." << endl; + // emit mediaControlRemoved(TQString ( object.data() )); + } + else if ((*it) == "org.freedesktop.DBus.Introspectable") + { + // do nothing + } + else if ((*it) == "org.freedesktop.DBus.Properties") + { + // do nothing + } + else + { + tqWarning("Interface not implemented: %s", (*it).local8Bit().data()); + } + } +} + +void ObjectManagerImpl::slotPropertiesChanged(const TQString& interface, const TQMap& changed_properties, const TQStringList& invalidated_properties) +{ + // who send the signal ? + const TQObject * o = TQObject::sender(); + org::freedesktop::DBus::PropertiesProxy *obj; + obj = const_cast(reinterpret_cast(o)); + TQString path; + + if (interface == "org.bluez.Adapter1") + { + for (PropertiesMap::Iterator it = adapters.begin(); + it != adapters.end(); ++it) + { + if (obj == it.data()) + path = it.key(); + } + if (!path.isEmpty()) + adapterPropertiesChanged(path, changed_properties); + } + else if (interface == "org.bluez.Device1") + { + for (PropertiesMap::Iterator it = devices.begin(); it != devices.end(); + ++it) + { + if (obj == it.data()) + path = it.key(); + } + if (!path.isEmpty()) + devicePropertiesChanged(path, changed_properties); + } + else if (interface == "org.bluez.MediaControl1") + { + for (PropertiesMap::Iterator it = devices.begin(); it != devices.end(); + ++it) + { + if (obj == it.data()) + path = it.key(); + } + if (!path.isEmpty()) + mediaControlPropertiesChanged(path, changed_properties); + } + +// TQStringList::const_iterator it1; +// for ( it1 = invalidated_properties.begin(); it1 != invalidated_properties.end(); ++it1 ) +// { +// kdDebug() << "Invalidated Key: " << (*it1) << endl; +//// if ( it.key() == "Powered" ) +//// emit powerOnChanged(TQT_DBusData::fromVariant ( it.data() ).toBool()); +//// if ( it.key() == "DiscoverableTimeout" ) +//// emit discoverableTimeoutChanged(TQT_DBusData::fromVariant ( it.data() ).toUInt32()); +//// if ( it.key() == "Discoverable" ) +//// emit discoverableTimeoutChanged(TQT_DBusData::fromVariant ( it.data() ).toBool()); +// } + +} + +}; // namespace TDEBluetooth + +#include "objectmanagerImpl.moc" +// End of File + diff --git a/src/libtdebluez/objectmanagerImpl.h b/src/libtdebluez/objectmanagerImpl.h new file mode 100644 index 0000000..f8f9c2f --- /dev/null +++ b/src/libtdebluez/objectmanagerImpl.h @@ -0,0 +1,177 @@ +/* + * + * Object Manager implementation of bluez5 + * + * Copyright (C) 2018 Emanoil Kotsev + * + * + * This file is part of libtdebluez. + * + * libtdebluez is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libtdebluez is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kbluetooth; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef OBJECTMANAGERIMPL_H_INCLUDED +#define OBJECTMANAGERIMPL_H_INCLUDED + +#include +#include + +#include "interfaces/objectmanagerProxy.h" +#include "interfaces/agentmanager1Proxy.h" +#include "interfaces/profilemanager1Proxy.h" +#include "interfaces/healthmanager1Proxy.h" +#include "interfaces/propertiesProxy.h" + +#include "adapterImpl.h" +#include "deviceImpl.h" + +//using namespace org::bluez; + +#define DBUS_CONN_NAME "TDEBluez" + +#define DBUS_AUTH_SERVICE_PATH "/org/trinitydesktop/tdebluez" +#define DEVICE_PIN_CAPABILITY "KeyboardDisplay" + +namespace TDEBluetooth +{ + +class ObjectManagerImpl : public org::freedesktop::DBus::ObjectManagerProxy +{ + Q_OBJECT + +public: + ObjectManagerImpl(const TQString& service, const TQString& path, TQObject* parent = 0, const char* name = 0); + + virtual ~ObjectManagerImpl(); + typedef TQMap PropertiesMap; + typedef TQValueList AdapterList; + typedef TQValueList DeviceList; + typedef TQValueList ConnectionList; + // typedef TQValueList ServiceList; + + // --- helper to get private members of the class --- // + //! to get information if TDEBluez is connected to D-Bus + bool isConnectedToDBUS(); + //! pointer to the D-Bus connection + TQT_DBusConnection* getConnection(); + //! to close the connection to D-Bus + bool close(); + + // + AgentManager1Proxy* getAgentManager(); + ProfileManager1Proxy* getProfileManager(); + HealthManager1Proxy* getHealthManager(); + AdapterList getAdapters(); + DeviceList getDevices(); + // ServiceList getServices(); + ConnectionList listConnections(const TQString&); + + + //! to register the agent to D-Bus + bool registerAgent(); //TQT_DBusError& + //! to unregister the agent to D-Bus + bool unregisterAgent(); //TQT_DBusError& + //! to register the agent to D-Bus + bool requestDefaultAgent(); //TQT_DBusError& + + bool isAgentRegistered(); + + bool isAgentDefaultAgent(); + +private: + bool initDBUS(); + void adapterPropertiesChanged(TQString path, const TQMap& changed_properties); + void devicePropertiesChanged(TQString path, const TQMap& changed_properties); + void mediaControlPropertiesChanged(TQString path, const TQMap& changed_properties); + +private: + //! TQt connection to D-Bus + TQT_DBusConnection dBusConn; + AgentManager1Proxy* agentManager; + ProfileManager1Proxy* profileManager; + HealthManager1Proxy* healthManager; + PropertiesMap adapters; + PropertiesMap devices; + bool agentRegisteredStatus; + bool agentIsDefaultAgent; + +signals: + // from ObjectManager + void adapterAdded(const TQString&); + void adapterRemoved(const TQString&); + + void deviceAdded(const TQString&); + void deviceRemoved(const TQString&); + + void mediaControlAdded(const TQString&); + void mediaControlRemoved(const TQString&); + + // from Adapter1 + void adapterNameChanged(const TQString&, const TQString&); + // void adapterModeChanged(const TQString&, const TQString&); + void adapterAliasChanged(const TQString&, const TQString&); + void adapterPowerOnChanged(const TQString&, bool state); + void adapterClassChanged(const TQString&, TQ_UINT32 classvalue); + void adapterDiscoverableTimeoutChanged(const TQString&, TQ_UINT32 timeout); + // TODO: this should be same as modeChanged + void adapterDiscoverableChanged(const TQString&, bool state); + void adapterDiscoveringChanged(const TQString&, bool state); + + // from Device1 + void deviceAddressChanged(const TQString&, const TQString&); + void deviceClassChanged(const TQString&, TQ_UINT32); + void deviceNameChanged(const TQString&, const TQString&); + void deviceAliasChanged(const TQString&, const TQString&); + // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml + void deviceAppearanceChanged(const TQString&, TQ_UINT32); + void deviceIconChanged(const TQString&, const TQString&); + void devicePairedChanged(const TQString&, bool); + void deviceTrustedChanged(const TQString&, bool); + void deviceBlockedChanged(const TQString&, bool); + void deviceLegacyPairingChanged(const TQString&, bool); + void deviceRSSIChanged(const TQString&, TQ_INT16); + void deviceConnectedChanged(const TQString&, bool); + void deviceUUIDsChanged(const TQString&, TQStringList); + void deviceAdapterChanged(const TQString&, const TQT_DBusObjectPath&); + void deviceManufacturerDataChanged(const TQString&, TQT_DBusDataMap); + void deviceServiceDataChanged(const TQString&, TQT_DBusDataMap); + void deviceTxPowerChanged(const TQString&, TQ_INT16); + void deviceServicesResolvedChanged(const TQString&, bool); + + // from MediaControl1 + void mediaControlConnectedChanged(const TQString&, bool state); + void mediaControlPlayerChanged(const TQString&, const TQT_DBusObjectPath&); + +private slots: + bool reconnect(); + + // inherited from ObjectManager + void slotInterfacesAdded(const TQT_DBusObjectPath& object, const TQT_DBusDataMap< TQString >& interfaces); + void slotInterfacesRemoved(const TQT_DBusObjectPath& object, const TQStringList& interfaces); + + /** + * parse properties changed on any interface + * emit signal for the interface and property + */ + void slotPropertiesChanged(const TQString& interface, const TQMap< TQString, TQT_DBusVariant >& changed_properties, const TQStringList& invalidated_properties); + +}; // class ObjectManagerImpl + +}; // namespace TDEBluetooth + +#endif //OBJECTMANAGERIMPL_H_INCLUDED + +// End of File -- cgit v1.2.1