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.
tdepim/kpilot/kpilot/kpilotProbeDialog.cc

364 lines
11 KiB

/* conduitConfigDialog.cc KPilot
**
** Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
**
** This file defines a .ui-based configuration dialog for conduits.
*/
/*
** This program 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.
**
** This program 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 this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/
/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/
#include "options.h"
#include <tqlayout.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <tqvbox.h>
#include <tqtimer.h>
#include <tqptrlist.h>
#include <tqmap.h>
#include <tqvaluelist.h>
#include <kmessagebox.h>
#include <kglobal.h>
#include <klocale.h>
#include <kconfigskeleton.h>
#include <kapplication.h>
#include <kprogress.h>
#include "kpilotConfig.h"
#include "pilotUser.h"
#include "pilotSysInfo.h"
#include "options.h"
#include "kpilotdevicelink.h"
#include "kpilotProbeDialog.moc"
#include "pilotDaemonDCOP_stub.h"
/*
We can't connect to /dev/ttyUSB0 and /dev/ttyUSB1 at the same time, because that
will lock up kpilot completely. In particular, it gets a connection on /dev/ttyUSB0,
which it processes, and while processing, a connection on USB1 is also detected.
However, when kpilot gets 'round to process it, the link is already closed, and
pi_connect hangs forever.
Now, I split up the list of devices to probe into three list, one holding /dev/pilot,
the second holding all /dev/xxx0 and /dev/xxx2 (e.g. /dev/ttyUSB0 and /dev/ttyUSB2),
and finally a third holding the remaining /dev/xxx1 and /dev/xxx3 devices. Each of
these three sets of devices is activated for a few seconds, and then the next set is
probed. This way, I ensure that kpilot never listens on /dev/ttyUSB0 and /dev/ttyUSB1
at the same time.
Now the first detection works fine. However, it seems the Linux kernel has another
problem with /dev/ttyUSB0. I have a Clie, which uses ttyUSB0, and as soon as the
wizard tries to listen on ttyUSB1 (after it detected the handheld on ttyUSB0 already),
the kernel writes a warning message to the syslog:
visor ttyUSB1: Device lied about number of ports, please use a lower one.
If I continue autodetection once again afterwards, the visor module kind of crashes.
lsmod shows an impossible usage count for the module:
reinhold@einstein:/kde/builddir$ lsmod
Module Size Used by
visor 17164 4294967294
usbserial 30704 1 visor
After that, the kernel doesn't detect the device ever again (until the computer is rebooted),
and the module can't be unloaded.
*/
ProbeDialog::ProbeDialog(TQWidget *parent, const char *n) :
KDialogBase(parent, n, true, i18n("Autodetecting Your Handheld"), KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::User1, KDialogBase::Cancel, true, i18n("Restart Detection")),
mDetected(false), mUserName(), mDevice()
{
FUNCTIONSETUP;
TQVBox *mainWidget = makeVBoxMainWidget();
fInfoText = new TQLabel( i18n( "KPilot is now trying to automatically detect the device of your handheld. Please press the hotsync button if you have not done so already." ), mainWidget, "fInfoText" );
fInfoText->setAlignment( TQLabel::WordBreak );
fStatusGroup = new TQGroupBox( i18n("Status"), mainWidget, "fStatusGroup" );
fStatusGroup->setColumnLayout(0, Qt::Vertical );
fStatusGroupLayout = new TQGridLayout( fStatusGroup->layout() );
fStatus = new TQLabel( i18n("Autodetection not yet started..."), fStatusGroup, "fStatus" );
fStatus->setAlignment( TQLabel::WordBreak );
fStatusGroupLayout->addWidget( fStatus, 0, 0 );
fProgress = new KProgress( 100, fStatusGroup, "fProgress" );
fStatusGroupLayout->addWidget( fProgress, 1, 0 );
fResultsGroup = new TQGroupBox( i18n( "Detected Values" ), mainWidget, "fResultsGroup" );
fResultsGroup->setEnabled( FALSE );
fResultsGroup->setColumnLayout(0, Qt::Vertical );
fResultsGroupLayout = new TQGridLayout( fResultsGroup->layout() );
fResultsGroupLayout->setAlignment( Qt::AlignTop );
fUserLabel = new TQLabel( i18n( "Handheld user:" ), fResultsGroup, "fUserLabel" );
fUserLabel->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)4, (TQSizePolicy::SizeType)5, 0, 0, fUserLabel->sizePolicy().hasHeightForWidth() ) );
fResultsGroupLayout->addWidget( fUserLabel, 0, 0 );
fDeviceLabel = new TQLabel( i18n( "Device:" ), fResultsGroup, "fDeviceLabel" );
fResultsGroupLayout->addWidget( fDeviceLabel, 1, 0 );
fUser = new TQLabel( i18n("[Not yet known]"), fResultsGroup, "fUser" );
fResultsGroupLayout->addWidget( fUser, 0, 1 );
fDevice = new TQLabel( i18n("[Not yet known]"), fResultsGroup, "fDevice" );
fResultsGroupLayout->addWidget( fDevice, 1, 1 );
resize( TQSize(459, 298).expandedTo(minimumSizeHint()) );
clearWState( WState_Polished );
enableButtonOK(false);
mDevicesToProbe[0] << "/dev/pilot";
mDevicesToProbe[1] <<"/dev/ttyS0"<<"/dev/ttyS2"
<<"/dev/tts/0"<<"/dev/tts/2"
<<"/dev/ttyUSB0"<<"/dev/ttyUSB2"
<<"/dev/usb/tts/0"<<"/dev/usb/tts/2"
<<"/dev/cuaa0"<<"/dev/cuaa2"
<<"/dev/cuad0"<<"/dev/cuad2"
<<"/dev/ucom0"<<"/dev/ucom2";
mDevicesToProbe[2] <<"/dev/ttyS1"<<"/dev/ttyS3"
<<"/dev/tts/1"<<"/dev/tts/3"
<<"/dev/ttyUSB1"<<"/dev/ttyUSB3"
<<"/dev/usb/tts/1"<<"/dev/usb/tts/3"
<<"/dev/cuaa1"<<"/dev/cuaa3"
<<"/dev/cuad1"<<"/dev/cuad3"
<<"/dev/ucom1"<<"/dev/ucom3";
fProcessEventsTimer = new TQTimer( this );
fTimeoutTimer = new TQTimer( this );
fProgressTimer = new TQTimer( this );
fRotateLinksTimer = new TQTimer( this );
connect( fProcessEventsTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(processEvents()) );
connect( fTimeoutTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(timeout()) );
connect( fProgressTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT( progress()) );
connect( fRotateLinksTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT( detect()) );
connect( this, TQT_SIGNAL(finished()), this, TQT_SLOT(disconnectDevices()) );
}
ProbeDialog::~ProbeDialog()
{
FUNCTIONSETUP;
}
void ProbeDialog::processEvents()
{
FUNCTIONSETUP;
KApplication::kApplication()->processEvents();
}
void ProbeDialog::progress()
{
fProgress->advance(1);
}
int ProbeDialog::exec()
{
mDetected = false;
mUserName = TQString();
mDevice = TQString();
TQTimer::singleShot( 0, this, TQT_SLOT( startDetection() ) );
return KDialogBase::exec();
}
void ProbeDialog::startDetection()
{
FUNCTIONSETUP;
disconnectDevices();
fProgress->setProgress(0);
fStatus->setText( i18n("Starting detection...") );
TQTimer::singleShot(0, this, TQT_SLOT(processEvents()) );
processEvents();
PilotDaemonDCOP_stub *daemonStub = new PilotDaemonDCOP_stub("kpilotDaemon", "KPilotDaemonIface");
if (daemonStub) {
daemonStub->stopListening();
}
KPILOT_DELETE(daemonStub);
processEvents();
if (!fTimeoutTimer->start( 30000, true ) )
{
WARNINGKPILOT << "Could not start fTimeoutTimer" << endl;
}
if (!fProcessEventsTimer->start( 100, false ) )
{
WARNINGKPILOT << "Could not start fProcessEventsTimer" << endl;
}
if (!fProgressTimer->start( 300, false) )
{
WARNINGKPILOT << "Could not start Progress timer" << endl;
}
KPilotDeviceLink*link;
for (int i=0; i<3; i++)
{
TQStringList::iterator end(mDevicesToProbe[i].end());
for (TQStringList::iterator it=mDevicesToProbe[i].begin(); it!=end; ++it)
{
link = new KPilotDeviceLink();
link->setDevice((*it));
#ifdef DEBUG
DEBUGKPILOT<<"new kpilotDeviceLink for "<<(*it)<<endl;
#endif
mDeviceLinks[i].append( link );
connect( link, TQT_SIGNAL(deviceReady(KPilotDeviceLink*)), this, TQT_SLOT(connection(KPilotDeviceLink*)) );
processEvents();
}
}
fStatus->setText( i18n("Waiting for handheld to connect...") );
mProbeDevicesIndex=0;
detect();
if (!fRotateLinksTimer->start( 3000, false) )
{
WARNINGKPILOT << "Could not start Device link rotation timer" << endl;
}
}
void ProbeDialog::detect(int i)
{
FUNCTIONSETUP;
mProbeDevicesIndex = i;
PilotLinkList::iterator end(mDeviceLinks[mProbeDevicesIndex].end());
for (PilotLinkList::iterator it=mDeviceLinks[mProbeDevicesIndex].begin(); it!=end; ++it)
{
if (*it) (*it)->reset();
}
}
void ProbeDialog::detect()
{
detect( (mProbeDevicesIndex+1)%3 );
}
void ProbeDialog::timeout()
{
disconnectDevices();
if (!mDetected) {
fStatus->setText( i18n("Timeout reached, could not detect a handheld.") );
KMessageBox::information ( this, i18n("<qt>A handheld could not be detected. Possible check the following things:</p>"
"<ul><li> Have you pressed the hotsync button on the handheld?\n"
"<li> Make sure the device sits in the cradle correctly.\n"
"<li> Make sure the cradle is correctly plugged in to the computer.\n"
"<li> Have you checked that your device is actually supported by kpilot (see http://www.kpilot.org).\n"
"</ul>"
), i18n("Automatic Detection Failed"), "AutoDetectionFailed");
}
}
void ProbeDialog::connection( KPilotDeviceLink*lnk)
{
FUNCTIONSETUP;
mActiveLink = lnk;
if ( !mActiveLink ) return;
const KPilotUser &usr( mActiveLink->getPilotUser() );
mUserName = usr.name();
mDevice = mActiveLink->pilotPath();
fStatus->setText( i18n("Found a connected device on %1").arg(mDevice) );
fUser->setText( mUserName );
fDevice->setText( mDevice );
mDetected = true;
fResultsGroup->setEnabled( true );
enableButtonOK(true);
TQTimer::singleShot(0, this, TQT_SLOT(retrieveDBList()));
}
void ProbeDialog::retrieveDBList()
{
KPilotLink::DBInfoList dbs = mActiveLink->getDBList();
mDBs.clear();
char buff[7];
buff[0] = '[';
for ( KPilotLink::DBInfoList::ConstIterator i = dbs.begin();
i != dbs.end(); ++i )
{
set_long( &buff[1], (*i).creator );
buff[5] = ']';
buff[6] = '\0';
TQString cr( buff );
mDBs << cr;
mDBs << TQString( (*i).name );
}
mDBs.sort();
TQString old( TQString::null );
TQStringList::Iterator itr = mDBs.begin();
while ( itr != mDBs.end() ) {
if ( old == *itr ) {
itr = mDBs.remove( itr );
} else {
old = *itr;
++itr;
}
}
// End sync gracefully, but don't change settings on the handheld.
mActiveLink->endSync( KPilotLink::NoUpdate );
TQTimer::singleShot(0, this, TQT_SLOT(disconnectDevices()));
}
void ProbeDialog::disconnectDevices()
{
FUNCTIONSETUP;
if (!mDetected) fStatus->setText( i18n("Disconnected from all devices") );
fProcessEventsTimer->stop( );
fTimeoutTimer->stop();
fProgressTimer->stop();
fRotateLinksTimer->stop();
fProgress->setProgress(fProgress->totalSteps());
for (int i=0; i<3; ++i)
{
PilotLinkList::iterator end(mDeviceLinks[i].end());
for (PilotLinkList::iterator it=mDeviceLinks[i].begin(); it!=end; ++it)
{
(*it)->close();
KPILOT_DELETE(*it);
}
mDeviceLinks[i].clear();
}
PilotDaemonDCOP_stub *daemonStub = new PilotDaemonDCOP_stub("kpilotDaemon", "KPilotDaemonIface");
if (daemonStub)
{
daemonStub->startListening();
}
KPILOT_DELETE(daemonStub);
}