tdebluez
objectmanagerImpl.cpp
Go to the documentation of this file.
1 /*
2  *
3  * Object Manager implementation of bluez5
4  *
5  * Copyright (C) 2018 Emanoil Kotsev <deloptes@gmail.com>
6  *
7  *
8  * This file is part of libtdebluez.
9  *
10  * libtdebluez is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * libtdebluez is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with kbluetooth; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 #include <tqstringlist.h>
27 
28 #include <tqdbusmessage.h>
29 #include <tqdbusobjectpath.h>
30 #include <tqdbusdatamap.h>
31 #include <tqdbusdata.h>
32 #include <tqdbusdatalist.h>
33 #include <tqdbusvariant.h>
34 
35 #include "objectmanagerImpl.h"
36 #include "btuuids.h"
37 
38 namespace TDEBluetooth
39 {
40 
41 ObjectManagerImpl::ObjectManagerImpl(const TQString& service, const TQString& path, TQObject* parent, const char* name) :
42  ObjectManagerProxy(service, path, parent, name)
43 {
44  agentManager = 0;
45  profileManager = 0;
46  healthManager = 0;
47  agentRegisteredStatus = false;
48  agentIsDefaultAgent = false;
49  // init connection to dbus
50  initDBUS();
51 }
52 
54 {
55  // close D-Bus connection
56  close();
57 
58  if(agentManager)
59  delete agentManager;
60  if(profileManager)
61  delete profileManager;
62  if(healthManager)
63  delete healthManager;
64 }
65 
73 {
74  // close D-Bus connection
75  close();
76  // init D-Bus conntection
77  return (initDBUS());
78 }
79 
87 {
88  return dBusConn.isConnected();
89 }
90 
96 TQT_DBusConnection* ObjectManagerImpl::getConnection()
97 {
98  return &dBusConn;
99 }
100 
108 {
109  disconnect(this, TQ_SIGNAL(InterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >&)),
110  this, TQ_SLOT(slotInterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >& )));
111  disconnect(this, TQ_SIGNAL(InterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& )),
112  this, TQ_SLOT(slotInterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& )));
113 
114  for (PropertiesMap::iterator it = adapters.begin(); it != adapters.end();
115  ++it)
116  {
118  p = it.data();
119  if (p != NULL)
120  delete p;
121  }
122  for (PropertiesMap::iterator it = devices.begin(); it != devices.end();
123  ++it)
124  {
126  p = it.data();
127  if (p != NULL)
128  delete p;
129  }
130  adapters.clear();
131  devices.clear();
132 
133  dBusConn.closeConnection(DBUS_CONN_NAME);
134  return true;
135 }
136 
142 {
143  return agentManager;
144 }
145 
151 {
152  return profileManager;
153 }
154 
160 {
161  return healthManager;
162 }
163 
170 {
171  return adapters.keys();
172 }
173 
180 {
181  return devices.keys();
182 }
183 
185 {
186  ConnectionList list;
187  return list;
188 }
189 
191 {
193  {
194  TQT_DBusError dbuserror;
196  TQT_DBusObjectPath(TQCString(DBUS_AUTH_SERVICE_PATH)), DEVICE_PIN_CAPABILITY, dbuserror);
197  if (dbuserror.isValid())
198  {
199  tqDebug(i18n("Could not register agent: %1").arg(dbuserror.message()));
200  return false;
201  }
202  agentRegisteredStatus = true;
203  }
204  return true;
205 }
206 
208 {
209  kdDebug() << k_funcinfo << endl;
211  {
212  TQT_DBusError dbuserror;
214  TQT_DBusObjectPath(TQCString(DBUS_AUTH_SERVICE_PATH)), dbuserror);
215  if (dbuserror.isValid())
216  {
217  tqDebug(i18n("Could not unregister agent"));
218  return false;
219  }
220  agentRegisteredStatus = false;
221  agentIsDefaultAgent = false;
222  }
223  return true;
224 }
225 
227 {
228  TQT_DBusError dbuserror;
230  TQT_DBusObjectPath(TQCString(DBUS_AUTH_SERVICE_PATH)), dbuserror);
231  if (dbuserror.isValid())
232  {
233  tqDebug(i18n("Could not request default agent: %1").arg(dbuserror.message()));
234  return false;
235  }
236  agentIsDefaultAgent = true;
237  return true;
238 }
239 
241 {
242  return agentRegisteredStatus;
243 }
244 
246 {
247  return agentIsDefaultAgent;
248 }
249 
257 {
258  dBusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus, DBUS_CONN_NAME);
259  if (!dBusConn.isConnected())
260  {
261  tqDebug(i18n("Failed to open connection to system message bus: %1").arg(dBusConn.lastError().message()));
262  TQTimer::singleShot(4000, this, TQ_SLOT(reconnect()));
263  return false;
264  }
266 
268  TQT_DBusError dbuserror;
269  if (!GetManagedObjects(objects, dbuserror))
270  {
271  tqDebug(i18n("GetManagedObjects(objects,error) failed: %1").arg(dbuserror.message()));
272  return false;
273  }
274 
276  for (it; it != objects.end(); ++it)
277  {
278  bool ok = false;
279  slotInterfacesAdded(it.key(), it.data().toStringKeyMap(&ok));
280  if (!ok)
281  tqWarning(i18n("Failed to convert dbus data to string map: %1").arg(it.key()));
282  }
283 
284  connect(this, TQ_SIGNAL(InterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >&)),
285  this, TQ_SLOT(slotInterfacesAdded(const TQT_DBusObjectPath&, const TQT_DBusDataMap< TQString >& )));
286  connect(this, TQ_SIGNAL(InterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& )),
287  this, TQ_SLOT(slotInterfacesRemoved(const TQT_DBusObjectPath& , const TQStringList& )));
288 
289  return true;
290 }
291 
293  TQString, TQT_DBusVariant>& changed_properties)
294 {
296  for (it = changed_properties.begin(); it != changed_properties.end(); ++it)
297  {
298  bool ok = false;
299  if (it.key() == "Powered")
300  emit adapterPowerOnChanged(path, it.data().value.toBool(&ok));
301  else if (it.key() == "Class")
302  emit adapterClassChanged(path, it.data().value.toUInt32(&ok));
303  else if (it.key() == "Name")
304  emit adapterNameChanged(path, it.data().value.toString(&ok));
305  else if (it.key() == "Alias")
306  emit adapterAliasChanged(path, it.data().value.toString(&ok));
307  else if (it.key() == "DiscoverableTimeout")
308  emit adapterDiscoverableTimeoutChanged(path, it.data().value.toUInt32(&ok));
309  else if (it.key() == "Discoverable")
310  emit adapterDiscoverableChanged(path, it.data().value.toBool(&ok));
311  else if (it.key() == "Discovering")
312  emit adapterDiscoveringChanged(path, it.data().value.toBool(&ok));
313  else
314  continue;
315  if (!ok)
316  tqDebug(i18n("ObjectManagerImpl::adapterPropertiesChanged conversion failed"));
317  }
318 }
319 
321 {
322  // https://github.com/r10r/bluez/blob/master/doc/device-api.txt
324  for (it = changed_properties.begin(); it != changed_properties.end(); ++it)
325  {
326  bool ok = false;
327  if (it.key() == "Address")
328  emit deviceAddressChanged(path, it.data().value.toString(&ok));
329  else if (it.key() == "Class")
330  emit deviceClassChanged(path, it.data().value.toUInt32(&ok));
331  else if (it.key() == "Name")
332  emit deviceNameChanged(path, it.data().value.toString(&ok));
333  else if (it.key() == "Alias")
334  emit deviceAliasChanged(path, it.data().value.toString(&ok));
335 // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
336  else if (it.key() == "Appearance")
337  emit deviceAppearanceChanged(path, it.data().value.toUInt16(&ok));
338  else if (it.key() == "Icon")
339  emit deviceIconChanged(path, it.data().value.toString(&ok));
340  else if (it.key() == "Paired")
341  emit devicePairedChanged(path, it.data().value.toBool(&ok));
342  else if (it.key() == "Trusted")
343  emit deviceTrustedChanged(path, it.data().value.toBool(&ok));
344  else if (it.key() == "Blocked")
345  emit deviceBlockedChanged(path, it.data().value.toBool(&ok));
346  else if (it.key() == "LegacyPairing")
347  emit deviceLegacyPairingChanged(path, it.data().value.toBool(&ok));
348  else if (it.key() == "RSSI")
349  emit deviceRSSIChanged(path, it.data().value.toInt16(&ok)); //INT16
350  else if (it.key() == "Connected")
351  emit deviceConnectedChanged(path, it.data().value.toBool(&ok));
352  else if (it.key() == "UUIDs")
353  {
354  TQT_DBusDataList vl = TQT_DBusDataList(it.data().value.toTQValueList(&ok));
355  emit deviceUUIDsChanged(path, vl.toStringList(&ok));
356  }
357  else if (it.key() == "Adapter")
358  emit deviceAdapterChanged(path, it.data().value.toObjectPath(&ok));
359  else if (it.key() == "ManufacturerData")
360  emit deviceManufacturerDataChanged(path, it.data().value.toUInt16KeyMap(&ok)); //a{qv}
361  else if (it.key() == "ServiceData")
362  emit deviceServiceDataChanged(path, it.data().value.toStringKeyMap(&ok)); //a{sv}
363  else if (it.key() == "TxPower")
364  emit deviceTxPowerChanged(path, it.data().value.toInt16(&ok)); //INT16
365  else if (it.key() == "ServicesResolved")
366  emit deviceServicesResolvedChanged(path, it.data().value.toBool(&ok));
367  else
368  continue;
369  if (!ok)
370  tqDebug(i18n("ObjectManagerImpl::devicePropertiesChanged conversion failed"));
371  }
372 
373 }
374 
376 {
378  for (it = changed_properties.begin(); it != changed_properties.end(); ++it)
379  {
380  bool ok = false;
381  if (it.key() == "Connected")
382  emit mediaControlConnectedChanged(path, it.data().value.toBool(&ok));
383  else if (it.key() == "Player")
384  emit mediaControlPlayerChanged(path, it.data().value.toObjectPath(&ok));
385  else
386  continue;
387  if (!ok)
388  tqDebug(i18n("ObjectManagerImpl::mediaControlPropertiesChanged conversion failed"));
389  }
390 }
391 
392 void ObjectManagerImpl::slotInterfacesAdded(const TQT_DBusObjectPath& object, const TQT_DBusDataMap<TQString>& interfaces)
393 {
394  TQT_DBusDataMap<TQString>::const_iterator it1 = interfaces.begin();
395  for (it1; it1 != interfaces.end(); it1++)
396  {
397  TQString interface = it1.key();
398  if (interface == "org.bluez.AgentManager1")
399  {
400  agentManager = new AgentManager1Proxy("org.bluez", object/*, this, "AgentManager1"*/);
401  if (agentManager)
403  }
404  else if (interface == "org.bluez.ProfileManager1")
405  {
406  profileManager = new ProfileManager1Proxy("org.bluez", object/*, this, "ProfileManager1"*/);
407  if (profileManager)
409  }
410  else if (interface == "org.bluez.HealthManager1")
411  {
412  healthManager = new HealthManager1Proxy("org.bluez", object/*, this, "HealthManager1"*/);
413  if (healthManager)
415  }
416  else if (interface == "org.bluez.Adapter1")
417  {
419  properties = new org::freedesktop::DBus::PropertiesProxy("org.bluez", object);
420  properties->setConnection(dBusConn);
421  connect(properties, TQ_SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, TQ_SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )));
422  adapters.insert(TQString(object), properties);
423  //notify others
424  emit adapterAdded(TQString(object));
425  }
426  else if (interface == "org.bluez.GattManager1")
427  {
428  kdDebug() << "Interface not implemented: org.bluez.GattManager1" << endl;
429  // TODO: Implement GattManager1
430  }
431  else if (interface == "org.bluez.Media1")
432  {
433  kdDebug() << "Interface not implemented: org.bluez.Media1" << endl;
434  // TODO: Implement Media1
435  }
436  else if (interface == "org.bluez.NetworkServer1")
437  {
438  kdDebug() << "Interface not implemented: org.bluez.NetworkServer1" << endl;
439  // TODO: Implement NetworkServer1
440  }
441  else if (interface == "org.bluez.Device1")
442  {
444  properties = new org::freedesktop::DBus::PropertiesProxy("org.bluez", object);
445  properties->setConnection(dBusConn);
446  connect(properties, TQ_SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, TQ_SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )));
447  devices.insert(TQString(object), properties);
448  //notify others
449  emit deviceAdded(TQString(object));
450  }
451  else if (interface == "org.bluez.MediaControl1")
452  {
453  kdDebug() << "Interface not implemented: org.bluez.MediaControl1" << endl;
454  kdDebug() << "as the media control is triggered via properties changed." << endl;
455  }
456  else if (interface == "org.bluez.MediaTransport1")
457  {
458  kdDebug() << "Interface not implemented: org.bluez.MediaTransport1" << endl;
459  // TODO: Implement MediaTransport1
460  }
461  else if (interface == "org.freedesktop.DBus.Introspectable")
462  {
463  // do nothing
464  }
465  else if (interface == "org.freedesktop.DBus.Properties")
466  {
467  // do nothing
468  }
469  else
470  {
471  tqWarning(i18n("Interface not implemented: %1").arg(interface));
472  }
473  }
474 }
475 
476 void ObjectManagerImpl::slotInterfacesRemoved(const TQT_DBusObjectPath& object, const TQStringList& interfaces)
477 {
478  // TODO: remove interface
479  for (TQValueListConstIterator<TQString> it = interfaces.begin();
480  it != interfaces.end(); ++it)
481  {
482  if ((*it) == "org.bluez.AgentManager1")
483  {
484  kdDebug() << "Remove org.bluez.AgentManager1" << endl;
485  // TODO: remove AgentManager1
486  }
487  else if ((*it) == "org.bluez.ProfileManager1")
488  {
489  kdDebug() << "Interface not implemented: org.bluez.ProfileManager1" << endl;
490  // TODO: remove ProfileManager1
491  }
492  else if ((*it) == "org.bluez.HealthManager1")
493  {
494  kdDebug() << "Interface not implemented: org.bluez.HealthManager1" << endl;
495  // TODO: remove HealthManager1
496  }
497  else if ((*it) == "org.bluez.Adapter1")
498  {
499  kdDebug() << "Remove org.bluez.Adapter1" << endl;
500  disconnect(adapters[object], TQ_SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, TQ_SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )));
501  adapters.remove(object);
502  emit adapterRemoved(TQString(object));
503  }
504  else if ((*it) == "org.bluez.GattManager1")
505  {
506  kdDebug() << "Interface not implemented: org.bluez.GattManager1" << endl;
507  // TODO: Implement GattManager1
508  }
509  else if ((*it) == "org.bluez.Media1")
510  {
511  kdDebug() << "Interface not implemented: org.bluez.Media1" << endl;
512  // TODO: Implement Media1
513  }
514  else if ((*it) == "org.bluez.NetworkServer1")
515  {
516  kdDebug() << "Interface not implemented: org.bluez.NetworkServer1" << endl;
517  // TODO: Implement NetworkServer1
518  }
519  else if ((*it) == "org.bluez.Device1")
520  {
521  kdDebug() << "Remove org.bluez.Device1" << endl;
522  disconnect(devices[object], TQ_SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), this, TQ_SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )));
523  devices.remove(object);
524  emit deviceRemoved(TQString(object));
525  }
526  else if ((*it) == "org.bluez.MediaControl1")
527  {
528  kdDebug() << "Interface not implemented: org.bluez.MediaControl1" << endl;
529  kdDebug() << "as the media control is triggered via properties changed." << endl;
530  // emit mediaControlRemoved(TQString ( object.data() ));
531  }
532  else if ((*it) == "org.freedesktop.DBus.Introspectable")
533  {
534  // do nothing
535  }
536  else if ((*it) == "org.freedesktop.DBus.Properties")
537  {
538  // do nothing
539  }
540  else
541  {
542  tqWarning(i18n("Interface not implemented: %1").arg((*it)));
543  }
544  }
545 }
546 
547 void ObjectManagerImpl::slotPropertiesChanged(const TQString& interface, const TQMap<TQString, TQT_DBusVariant>& changed_properties, const TQStringList& invalidated_properties)
548 {
549  // who send the signal ?
550  const TQObject * o = TQObject::sender();
552  obj = const_cast<org::freedesktop::DBus::PropertiesProxy*>(reinterpret_cast<const org::freedesktop::DBus::PropertiesProxy*>(o));
553  TQString path;
554 
555  if (interface == "org.bluez.Adapter1")
556  {
557  for (PropertiesMap::Iterator it = adapters.begin();
558  it != adapters.end(); ++it)
559  {
560  if (obj == it.data())
561  path = it.key();
562  }
563  if (!path.isEmpty())
564  adapterPropertiesChanged(path, changed_properties);
565  }
566  else if (interface == "org.bluez.Device1")
567  {
568  for (PropertiesMap::Iterator it = devices.begin(); it != devices.end();
569  ++it)
570  {
571  if (obj == it.data())
572  path = it.key();
573  }
574  if (!path.isEmpty())
575  devicePropertiesChanged(path, changed_properties);
576  }
577  else if (interface == "org.bluez.MediaControl1")
578  {
579  for (PropertiesMap::Iterator it = devices.begin(); it != devices.end();
580  ++it)
581  {
582  if (obj == it.data())
583  path = it.key();
584  }
585  if (!path.isEmpty())
586  mediaControlPropertiesChanged(path, changed_properties);
587  }
588 
589 // TQStringList::const_iterator it1;
590 // for ( it1 = invalidated_properties.begin(); it1 != invalidated_properties.end(); ++it1 )
591 // {
592 // kdDebug() << "Invalidated Key: " << (*it1) << endl;
599 // }
600 
601 }
602 
603 }; // namespace TDEBluetooth
604 
605 #include "objectmanagerImpl.moc"
606 // End of File
607 
ObjectManagerImpl(const TQString &service, const TQString &path, TQObject *parent=0, const char *name=0)
void deviceServiceDataChanged(const TQString &, TQT_DBusDataMap< TQString >)
void adapterRemoved(const TQString &)
void adapterNameChanged(const TQString &, const TQString &)
void deviceUUIDsChanged(const TQString &, TQStringList)
void deviceNameChanged(const TQString &, const TQString &)
void devicePropertiesChanged(TQString path, const TQMap< TQString, TQT_DBusVariant > &changed_properties)
bool unregisterAgent()
to unregister the agent to D-Bus
bool requestDefaultAgent()
to register the agent to D-Bus
void adapterDiscoverableChanged(const TQString &, bool state)
void deviceServicesResolvedChanged(const TQString &, bool)
void slotInterfacesRemoved(const TQT_DBusObjectPath &object, const TQStringList &interfaces)
void deviceClassChanged(const TQString &, TQ_UINT32)
void deviceAppearanceChanged(const TQString &, TQ_UINT32)
bool close()
to close the connection to D-Bus
void adapterPropertiesChanged(TQString path, const TQMap< TQString, TQT_DBusVariant > &changed_properties)
void mediaControlPropertiesChanged(TQString path, const TQMap< TQString, TQT_DBusVariant > &changed_properties)
void adapterPowerOnChanged(const TQString &, bool state)
ProfileManager1Proxy * getProfileManager()
void adapterDiscoverableTimeoutChanged(const TQString &, TQ_UINT32 timeout)
void deviceRSSIChanged(const TQString &, TQ_INT16)
HealthManager1Proxy * getHealthManager()
TQValueList< TQString > ConnectionList
void deviceAliasChanged(const TQString &, const TQString &)
void deviceManufacturerDataChanged(const TQString &, TQT_DBusDataMap< TQ_UINT16 >)
TQT_DBusConnection dBusConn
TQt connection to D-Bus.
bool isConnectedToDBUS()
to get information if TDEBluez is connected to D-Bus
void mediaControlPlayerChanged(const TQString &, const TQT_DBusObjectPath &)
void slotPropertiesChanged(const TQString &interface, const TQMap< TQString, TQT_DBusVariant > &changed_properties, const TQStringList &invalidated_properties)
void deviceIconChanged(const TQString &, const TQString &)
TQValueList< TQString > DeviceList
void deviceAdded(const TQString &)
AgentManager1Proxy * getAgentManager()
void deviceConnectedChanged(const TQString &, bool)
ConnectionList listConnections(const TQString &)
ProfileManager1Proxy * profileManager
void adapterAdded(const TQString &)
TQValueList< TQString > AdapterList
void deviceAddressChanged(const TQString &, const TQString &)
void deviceTrustedChanged(const TQString &, bool)
void devicePairedChanged(const TQString &, bool)
void deviceBlockedChanged(const TQString &, bool)
HealthManager1Proxy * healthManager
void adapterAliasChanged(const TQString &, const TQString &)
TQT_DBusConnection * getConnection()
pointer to the D-Bus connection
void adapterClassChanged(const TQString &, TQ_UINT32 classvalue)
void deviceRemoved(const TQString &)
void deviceLegacyPairingChanged(const TQString &, bool)
void mediaControlConnectedChanged(const TQString &, bool state)
void adapterDiscoveringChanged(const TQString &, bool state)
bool registerAgent()
to register the agent to D-Bus
void slotInterfacesAdded(const TQT_DBusObjectPath &object, const TQT_DBusDataMap< TQString > &interfaces)
void deviceAdapterChanged(const TQString &, const TQT_DBusObjectPath &)
void deviceTxPowerChanged(const TQString &, TQ_INT16)
void setConnection(const TQT_DBusConnection &connection)
virtual bool UnregisterAgent(const TQT_DBusObjectPath &agent, TQT_DBusError &error)
virtual bool RegisterAgent(const TQT_DBusObjectPath &agent, const TQString &capability, TQT_DBusError &error)
virtual bool RequestDefaultAgent(const TQT_DBusObjectPath &agent, TQT_DBusError &error)
void setConnection(const TQT_DBusConnection &connection)
void setConnection(const TQT_DBusConnection &connection)
virtual bool GetManagedObjects(TQT_DBusDataMap< TQT_DBusObjectPath > &objects, TQT_DBusError &error)
void InterfacesAdded(const TQT_DBusObjectPath &object, const TQT_DBusDataMap< TQString > &interfaces)
void InterfacesRemoved(const TQT_DBusObjectPath &object, const TQStringList &interfaces)
void setConnection(const TQT_DBusConnection &connection)
#define DBUS_AUTH_SERVICE_PATH
#define DEVICE_PIN_CAPABILITY
#define DBUS_CONN_NAME