You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
10 KiB
373 lines
10 KiB
/*
|
|
*
|
|
* New Bluetooth App for TDE and bluez5
|
|
*
|
|
* Copyright (C) 2018 Emanoil Kotsev <deloptes@gmail.com>
|
|
*
|
|
*
|
|
* This file is part of tdebluez.
|
|
*
|
|
* tdebluez 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.
|
|
*
|
|
* tdebluez 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 <dcopclient.h>
|
|
#include <kuser.h>
|
|
#include <tqregexp.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <signal.h>
|
|
|
|
#include "trayicon.h"
|
|
#include "application.h"
|
|
|
|
#define WAIT_BEFORE_KILL 5000 // 5sec
|
|
#define CONFIGURATION_FILE "tdebluezrc"
|
|
#define TDEBLUEZAUTH_EXE "tdebluezauth"
|
|
#define OBEX_EXE "/usr/lib/bluetooth/obexd"
|
|
#define OBEX_EXE_ALT "/usr/libexec/bluetooth/obexd"
|
|
#define BLUEZ_DN "org.bluez"
|
|
#define DOWNLOAD_DIRECTORY "Downloads"
|
|
|
|
TDEBluetoothApp::TDEBluetoothApp() :
|
|
KUniqueApplication()
|
|
{
|
|
// set default config file
|
|
m_config = new TDEConfig(CONFIGURATION_FILE);
|
|
m_config->setGroup("General");
|
|
bool autostart = m_config->readBoolEntry("autoStart", false);
|
|
m_waitBeforeKill = m_config->readNumEntry("waitBeforeKill", WAIT_BEFORE_KILL);
|
|
TQString authAgentExe = m_config->readEntry("authAgentExe", TDEBLUEZAUTH_EXE);
|
|
TQString obexSrvExe = m_config->readEntry("obexSrvExe", OBEX_EXE);
|
|
TQString downloadDir = m_config->readPathEntry("downloadDir", "");
|
|
|
|
if (!autostart)
|
|
disableSessionManagement();
|
|
|
|
if (m_waitBeforeKill == 0)
|
|
{
|
|
m_waitBeforeKill = WAIT_BEFORE_KILL;
|
|
m_config->writeEntry("waitBeforeKill", m_waitBeforeKill);
|
|
}
|
|
|
|
if (obexSrvExe.isEmpty())
|
|
{
|
|
obexSrvExe=TQString(OBEX_EXE);
|
|
}
|
|
|
|
if (authAgentExe.isEmpty())
|
|
{
|
|
authAgentExe = TDEBLUEZAUTH_EXE;
|
|
m_config->writePathEntry("authAgentExe", authAgentExe);
|
|
}
|
|
|
|
if (downloadDir.isEmpty())
|
|
{
|
|
downloadDir = DOWNLOAD_DIRECTORY;
|
|
m_config->writePathEntry("downloadDir", downloadDir);
|
|
}
|
|
|
|
manager = new ObjectManagerImpl(BLUEZ_DN, "/", this, "ObjectManager");
|
|
if (!manager->isConnectedToDBUS())
|
|
{
|
|
tqDebug(i18n("ObjectManager is not connected to DBus"));
|
|
return;
|
|
}
|
|
|
|
ObjectManagerImpl::AdapterList al = manager->getAdapters();
|
|
ObjectManagerImpl::AdapterList::Iterator ait = al.begin();
|
|
for (ait; ait != al.end(); ++ait)
|
|
{
|
|
AdapterImpl *a = new AdapterImpl(BLUEZ_DN, (*ait));
|
|
a->setConnection((*(manager->getConnection())));
|
|
adapters.insert((*ait), a);
|
|
}
|
|
|
|
ObjectManagerImpl::DeviceList dl = manager->getDevices();
|
|
ObjectManagerImpl::DeviceList::Iterator dit = dl.begin();
|
|
for (dit; dit != dl.end(); ++dit)
|
|
{
|
|
DeviceImpl *d = new DeviceImpl(BLUEZ_DN, (*dit));
|
|
d->setConnection((*(manager->getConnection())));
|
|
devices.insert((*dit), d);
|
|
}
|
|
|
|
authAgent = new TQProcess(authAgentExe, this);
|
|
authAgent->addArgument("--nofork");
|
|
|
|
TQFileInfo obexSrvExeFile( obexSrvExe );
|
|
if (!obexSrvExeFile.exists())
|
|
{
|
|
obexSrvExeFile.setFile(OBEX_EXE_ALT);
|
|
if (obexSrvExeFile.exists())
|
|
{
|
|
m_config->writePathEntry("obexSrvExe", obexSrvExeFile.filePath());
|
|
}
|
|
else
|
|
{
|
|
tqWarning(i18n("obexd executable was not found\nSet path in configuration file \"%1\"\nVariable: obexSrvExe=<path to obexd>").arg(CONFIGURATION_FILE));
|
|
m_config->writeEntry("obexSrv", false);
|
|
}
|
|
}
|
|
|
|
obexServer = new TQProcess(obexSrvExeFile.filePath(), this);
|
|
obexServer->addArgument("-n");
|
|
obexServer->addArgument("-a");
|
|
obexServer->addArgument("-l");
|
|
obexServer->addArgument("-r");
|
|
obexServer->addArgument(downloadDir);
|
|
|
|
//stop tdebluezauth or obexd daemon to regain control
|
|
KUser user;
|
|
long uid = user.uid();
|
|
|
|
TQDir d("/proc");
|
|
d.setFilter(TQDir::Dirs);
|
|
|
|
TQRegExp rx( "^\\d+$" );
|
|
for (int i = 0; i < d.count(); i++)
|
|
{
|
|
if ( ! rx.exactMatch(d[i]) )
|
|
continue;
|
|
|
|
TQFile f("/proc/" + d[i] + "/status");
|
|
if ( ! f.open( IO_ReadOnly ) )
|
|
{
|
|
tqDebug(i18n("Failed to open file for reading: %1").arg(f.name()));
|
|
continue;
|
|
}
|
|
|
|
TQTextStream stream( &f );
|
|
TQString pid;
|
|
bool tokill = false;
|
|
while ( !stream.atEnd() ) {
|
|
TQString line = stream.readLine(); // line of text excluding '\n'
|
|
if (line.startsWith("Name:") &&
|
|
( line.endsWith("tdebluezauth") || line.endsWith("obexd") ))
|
|
{
|
|
pid = d[i];
|
|
}
|
|
if (line.find(TQRegExp(TQString("Uid:\\s+%1").arg(uid))) != -1)
|
|
{
|
|
tokill = true;
|
|
}
|
|
}
|
|
f.close();
|
|
|
|
if (tokill && ! pid.isEmpty())
|
|
{
|
|
if ( kill( (pid_t) pid.toLong(), SIGKILL ) == -1 )
|
|
{
|
|
switch ( errno )
|
|
{
|
|
case EINVAL:
|
|
tqDebug(i18n("4\t%1").arg(pid) );
|
|
break;
|
|
case ESRCH:
|
|
tqDebug(i18n("3\t%1").arg(pid) );
|
|
break;
|
|
case EPERM:
|
|
tqDebug(i18n("2\t%1").arg(pid) );
|
|
break;
|
|
default: /* unknown error */
|
|
tqDebug(i18n("1\t%1").arg(pid) );
|
|
break;
|
|
}
|
|
} else {
|
|
tqWarning(i18n("Cleanup pid\t%1").arg(pid) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// connect to manager signals
|
|
connect(manager, TQ_SIGNAL(adapterAdded(const TQString&)), TQ_SLOT(slotAdapterAdded(const TQString&)));
|
|
connect(manager, TQ_SIGNAL(adapterRemoved(const TQString&)), TQ_SLOT(slotAdapterRemoved(const TQString&)));
|
|
connect(manager, TQ_SIGNAL(deviceAdded(const TQString&)), TQ_SLOT(slotDeviceAdded(const TQString&)));
|
|
connect(manager, TQ_SIGNAL(deviceRemoved(const TQString&)), TQ_SLOT(slotDeviceRemoved(const TQString&)));
|
|
// connect(manager, TQ_SIGNAL(adapterPowerOnChanged(const TQString&, bool)), TQ_SLOT(slotPowerOnChanged(const TQString&, bool)));
|
|
|
|
trayIcon = new TrayIcon(this);
|
|
setMainWidget(trayIcon);
|
|
}
|
|
|
|
TDEBluetoothApp::~TDEBluetoothApp()
|
|
{
|
|
|
|
if (obexServer)
|
|
{
|
|
if (obexServer->isRunning())
|
|
obexServer->kill();
|
|
delete obexServer;
|
|
}
|
|
if (authAgent)
|
|
{
|
|
if (authAgent->isRunning())
|
|
authAgent->kill();
|
|
delete authAgent;
|
|
}
|
|
delete trayIcon;
|
|
|
|
if (manager->isConnectedToDBUS())
|
|
{
|
|
DevicesMap::Iterator dit = devices.begin();
|
|
for (dit; dit != devices.end(); ++dit)
|
|
{
|
|
DeviceImpl *d = dit.data();
|
|
if (d)
|
|
delete d;
|
|
}
|
|
devices.clear();
|
|
|
|
AdaptersMap::Iterator ait = adapters.begin();
|
|
for (ait; ait != adapters.end(); ++ait)
|
|
{
|
|
AdapterImpl *a = ait.data();
|
|
if (a)
|
|
{
|
|
TQT_DBusError error;
|
|
if (a->getDiscovering(error))
|
|
a->StopDiscovery(error);
|
|
if (error.isValid())
|
|
tqDebug(i18n("Stop discoverable for the adapter failed: %1").arg(error.message()));
|
|
delete a;
|
|
}
|
|
}
|
|
adapters.clear();
|
|
}
|
|
delete manager;
|
|
|
|
if (m_config->isDirty())
|
|
m_config->sync();
|
|
|
|
delete m_config;
|
|
}
|
|
|
|
bool TDEBluetoothApp::startAuthAgent()
|
|
{
|
|
if (!authAgent->isRunning())
|
|
{
|
|
if (!authAgent->start())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TDEBluetoothApp::stopAuthAgent()
|
|
{
|
|
if (authAgent->isRunning())
|
|
{
|
|
authAgent->tryTerminate();
|
|
TQTimer::singleShot(m_waitBeforeKill, authAgent, TQ_SLOT(kill()));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TDEBluetoothApp::startObexSrv()
|
|
{
|
|
if (!obexServer->isRunning())
|
|
{
|
|
if (!obexServer->start())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TDEBluetoothApp::stopObexSrv()
|
|
{
|
|
if (obexServer->isRunning())
|
|
{
|
|
obexServer->tryTerminate();
|
|
TQTimer::singleShot(m_waitBeforeKill, obexServer, TQ_SLOT(kill()));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TDEBluetoothApp::isConnected()
|
|
{
|
|
return manager->isConnectedToDBUS();
|
|
}
|
|
|
|
void TDEBluetoothApp::setAutoStart(bool val)
|
|
{
|
|
if (val)
|
|
enableSessionManagement();
|
|
else
|
|
disableSessionManagement();
|
|
|
|
m_config->setGroup("General");
|
|
m_config->writeEntry("autoStart", val);
|
|
}
|
|
|
|
void TDEBluetoothApp::setStartObex(bool val)
|
|
{
|
|
m_config->setGroup("General");
|
|
m_config->writeEntry("obexSrv", val);
|
|
}
|
|
|
|
void TDEBluetoothApp::setStartAuthAgent(bool val)
|
|
{
|
|
m_config->setGroup("General");
|
|
m_config->writeEntry("authAgent", val);
|
|
}
|
|
|
|
bool TDEBluetoothApp::getAutoStart()
|
|
{
|
|
m_config->setGroup("General");
|
|
return m_config->readBoolEntry("autoStart");
|
|
}
|
|
|
|
bool TDEBluetoothApp::getStartObex()
|
|
{
|
|
m_config->setGroup("General");
|
|
return m_config->readBoolEntry("obexSrv");
|
|
}
|
|
|
|
bool TDEBluetoothApp::getStartAuthAgent()
|
|
{
|
|
m_config->setGroup("General");
|
|
return m_config->readBoolEntry("authAgent");
|
|
}
|
|
|
|
void TDEBluetoothApp::slotAdapterAdded(const TQString &adapter)
|
|
{
|
|
AdapterImpl *a = new AdapterImpl(BLUEZ_DN, adapter);
|
|
a->setConnection((*(manager->getConnection())));
|
|
adapters.insert(adapter, a);
|
|
emit signalAdapterAdded(adapter);
|
|
}
|
|
|
|
void TDEBluetoothApp::slotAdapterRemoved(const TQString &adapter)
|
|
{
|
|
delete adapters[adapter];
|
|
adapters.remove(adapter);
|
|
emit signalAdapterRemoved(adapter);
|
|
}
|
|
|
|
void TDEBluetoothApp::slotDeviceAdded(const TQString &device)
|
|
{
|
|
DeviceImpl *d = new DeviceImpl(BLUEZ_DN, device);
|
|
d->setConnection((*(manager->getConnection())));
|
|
devices.insert(device, d);
|
|
}
|
|
|
|
void TDEBluetoothApp::slotDeviceRemoved(const TQString &device)
|
|
{
|
|
delete devices[device];
|
|
devices.remove(device);
|
|
}
|
|
|
|
#include "application.moc"
|