kpilot/kpilot

kpilotProbeDialog.cc

00001 /* conduitConfigDialog.cc                KPilot
00002 **
00003 ** Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00004 **
00005 ** This file defines a .ui-based configuration dialog for conduits.
00006 */
00007 
00008 /*
00009 ** This program is free software; you can redistribute it and/or modify
00010 ** it under the terms of the GNU General Public License as published by
00011 ** the Free Software Foundation; either version 2 of the License, or
00012 ** (at your option) any later version.
00013 **
00014 ** This program is distributed in the hope that it will be useful,
00015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 ** GNU General Public License for more details.
00018 **
00019 ** You should have received a copy of the GNU General Public License
00020 ** along with this program in a file called COPYING; if not, write to
00021 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00022 ** MA 02110-1301, USA.
00023 */
00024 
00025 /*
00026 ** Bug reports and questions can be sent to kde-pim@kde.org
00027 */
00028 
00029 #include "options.h"
00030 
00031 #include <qlayout.h>
00032 #include <qgroupbox.h>
00033 #include <qlabel.h>
00034 #include <qvbox.h>
00035 #include <qtimer.h>
00036 #include <qptrlist.h>
00037 #include <qmap.h>
00038 #include <qvaluelist.h>
00039 
00040 #include <kmessagebox.h>
00041 #include <kglobal.h>
00042 #include <klocale.h>
00043 #include <kconfigskeleton.h>
00044 #include <kapplication.h>
00045 #include <kprogress.h>
00046 
00047 #include "kpilotConfig.h"
00048 #include "pilotUser.h"
00049 #include "pilotSysInfo.h"
00050 #include "options.h"
00051 #include "kpilotlink.h"
00052 
00053 #include "kpilotProbeDialog.moc"
00054 #ifndef __PILOTDAEMONDCOP_STUB__
00055 #include "pilotDaemonDCOP_stub.h"
00056 #endif
00057 
00058 /*
00059 We can't connect to /dev/ttyUSB0 and /dev/ttyUSB1 at the same time, because that
00060 will lock up kpilot completely. In particular, it gets a connection on /dev/ttyUSB0,
00061 which it processes, and while processing, a connection on USB1 is also detected.
00062 However, when kpilot gets 'round to process it, the link is already closed, and
00063 pi_connect hangs forever.
00064 
00065 Now, I split up the list of devices to probe into three list, one holding /dev/pilot,
00066 the second holding all /dev/xxx0 and /dev/xxx2 (e.g. /dev/ttyUSB0 and /dev/ttyUSB2),
00067 and finally a third holding the remaining /dev/xxx1 and /dev/xxx3 devices. Each of
00068 these three sets of devices is activated for a few seconds, and then the next set is
00069 probed. This way, I ensure that kpilot never listens on /dev/ttyUSB0 and /dev/ttyUSB1
00070 at the same time.
00071 
00072 Now the first detection works fine. However, it seems the Linux kernel has another
00073 problem with /dev/ttyUSB0. I have a Clie, which uses ttyUSB0, and as soon as the
00074 wizard tries to listen on ttyUSB1 (after it detected the handheld on ttyUSB0 already),
00075 the kernel writes a warning message to the syslog:
00076 visor ttyUSB1: Device lied about number of ports, please use a lower one.
00077 
00078 If I continue autodetection once again afterwards, the visor module kind of crashes.
00079 lsmod shows an impossible usage count for the module:
00080 
00081 reinhold@einstein:/kde/builddir$ lsmod
00082 Module                  Size  Used by
00083 visor                  17164  4294967294
00084 usbserial              30704  1 visor
00085 
00086 After that, the kernel doesn't detect the device ever again (until the computer is rebooted),
00087 and the module can't be unloaded.
00088 */
00089 
00090 
00091 ProbeDialog::ProbeDialog(QWidget *parent, const char *n) :
00092     KDialogBase(parent, n, true, i18n("Autodetecting Your Handheld"), KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::User1, KDialogBase::Cancel, true, i18n("Restart Detection")),
00093     mDetected(false), mUserName(""), mDevice(""), mUID(0)
00094 {
00095     QVBox *mainWidget = makeVBoxMainWidget();
00096 
00097     fInfoText = new QLabel( 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" );
00098     fInfoText->setAlignment( QLabel::WordBreak );
00099 
00100     fStatusGroup = new QGroupBox( i18n("Status"), mainWidget, "fStatusGroup" );
00101     fStatusGroup->setColumnLayout(0, Qt::Vertical );
00102     fStatusGroupLayout = new QGridLayout( fStatusGroup->layout() );
00103 
00104     fStatus = new QLabel( i18n("Autodetection not yet started..."), fStatusGroup, "fStatus" );
00105     fStatus->setAlignment( QLabel::WordBreak );
00106     fStatusGroupLayout->addWidget( fStatus, 0, 0 );
00107 
00108     fProgress = new KProgress( 100, fStatusGroup, "fProgress" );
00109     fStatusGroupLayout->addWidget( fProgress, 1, 0 );
00110 
00111 
00112 
00113     fResultsGroup = new QGroupBox( i18n( "Detected Values" ), mainWidget, "fResultsGroup" );
00114     fResultsGroup->setEnabled( FALSE );
00115     fResultsGroup->setColumnLayout(0, Qt::Vertical );
00116     fResultsGroupLayout = new QGridLayout( fResultsGroup->layout() );
00117     fResultsGroupLayout->setAlignment( Qt::AlignTop );
00118 
00119     fUserLabel = new QLabel( i18n( "Handheld user:" ), fResultsGroup, "fUserLabel" );
00120     fUserLabel->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)4, (QSizePolicy::SizeType)5, 0, 0, fUserLabel->sizePolicy().hasHeightForWidth() ) );
00121     fResultsGroupLayout->addWidget( fUserLabel, 0, 0 );
00122 
00123     fDeviceLabel = new QLabel( i18n( "Device:" ), fResultsGroup, "fDeviceLabel" );
00124     fResultsGroupLayout->addWidget( fDeviceLabel, 1, 0 );
00125 
00126     fUser = new QLabel( i18n("[Not yet known]"), fResultsGroup, "fUser" );
00127     fResultsGroupLayout->addWidget( fUser, 0, 1 );
00128 
00129     fDevice = new QLabel( i18n("[Not yet known]"), fResultsGroup, "fDevice" );
00130     fResultsGroupLayout->addWidget( fDevice, 1, 1 );
00131 
00132 
00133     resize( QSize(459, 298).expandedTo(minimumSizeHint()) );
00134     clearWState( WState_Polished );
00135     enableButtonOK(false);
00136 
00137     mDevicesToProbe[0] << "/dev/pilot";
00138     mDevicesToProbe[1] <<"/dev/ttyS0"<<"/dev/ttyS2"
00139                     <<"/dev/tts/0"<<"/dev/tts/2"
00140                     <<"/dev/ttyUSB0"<<"/dev/ttyUSB2"
00141                     <<"/dev/usb/tts/0"<<"/dev/usb/tts/2"
00142                     <<"/dev/cuaa0"<<"/dev/cuaa2"
00143             <<"/dev/cuad0"<<"/dev/cuad2"
00144                     <<"/dev/ucom0"<<"/dev/ucom2";
00145     mDevicesToProbe[2] <<"/dev/ttyS1"<<"/dev/ttyS3"
00146                     <<"/dev/tts/1"<<"/dev/tts/3"
00147                     <<"/dev/ttyUSB1"<<"/dev/ttyUSB3"
00148                     <<"/dev/usb/tts/1"<<"/dev/usb/tts/3"
00149                     <<"/dev/cuaa1"<<"/dev/cuaa3"
00150             <<"/dev/cuad1"<<"/dev/cuad3"
00151                     <<"/dev/ucom1"<<"/dev/ucom3";
00152 
00153     fProcessEventsTimer = new QTimer( this );
00154     fTimeoutTimer = new QTimer( this );
00155     fProgressTimer = new QTimer( this );
00156     fRotateLinksTimer = new QTimer( this );
00157     connect( fProcessEventsTimer, SIGNAL(timeout()), this, SLOT(processEvents()) );
00158     connect( fTimeoutTimer, SIGNAL(timeout()), this, SLOT(timeout()) );
00159     connect( fProgressTimer, SIGNAL(timeout()), this, SLOT( progress()) );
00160     connect( fRotateLinksTimer, SIGNAL(timeout()), this, SLOT( detect()) );
00161     connect( this, SIGNAL(finished()), this, SLOT(disconnectDevices()) );
00162 }
00163 
00164 ProbeDialog::~ProbeDialog()
00165 {
00166 }
00167 
00168 void ProbeDialog::processEvents()
00169 {
00170     FUNCTIONSETUP;
00171     KApplication::kApplication()->processEvents();
00172 }
00173 
00174 void ProbeDialog::progress()
00175 {
00176     fProgress->advance(1);
00177 }
00178 
00179 int ProbeDialog::exec()
00180 {
00181     mDetected = false;
00182     mUserName = "";
00183     mDevice = "";
00184     mUID = 0;
00185     QTimer::singleShot( 0, this, SLOT( startDetection() ) );
00186     return KDialogBase::exec();
00187 }
00188 
00189 void ProbeDialog::startDetection()
00190 {
00191     FUNCTIONSETUP;
00192 
00193     disconnectDevices();
00194     fProgress->setProgress(0);
00195     fStatus->setText( i18n("Starting detection...") );
00196     QTimer::singleShot(0, this, SLOT(processEvents()) );
00197     processEvents();
00198     PilotDaemonDCOP_stub *daemonStub = new PilotDaemonDCOP_stub("kpilotDaemon", "KPilotDaemonIface");
00199     if (daemonStub) {
00200         daemonStub->stopListening();
00201     }
00202     KPILOT_DELETE(daemonStub);
00203     processEvents();
00204     if (!fTimeoutTimer->start( 30000, true ) ) 
00205         kdWarning()<<"Could not start fTimeoutTimer"<<endl;
00206     if (!fProcessEventsTimer->start( 100, false ) ) 
00207         kdWarning()<<"Could not start fProcessEventsTimer"<<endl;
00208     if (!fProgressTimer->start( 300, false) ) 
00209         kdWarning()<<"Could not start Progress timer"<<endl;
00210 
00211     KPilotDeviceLink*link;
00212     for (int i=0; i<3; i++)
00213     {
00214         QStringList::iterator end(mDevicesToProbe[i].end());
00215         for (QStringList::iterator it=mDevicesToProbe[i].begin(); it!=end; ++it)
00216         {
00217             link = new KPilotDeviceLink();
00218 #ifdef DEBUG
00219             DEBUGKPILOT<<"new kpilotDeviceLink for "<<(*it)<<endl;
00220 #endif
00221             link->reset( *it );
00222             link->close();
00223 //          mDeviceLinkMap[*it] = link;
00224             mDeviceLinks[i].append( link );
00225             connect( link, SIGNAL(deviceReady(KPilotDeviceLink*)), this, SLOT(connection(KPilotDeviceLink*)) );
00226             processEvents();
00227         }
00228     }
00229     fStatus->setText( i18n("Waiting for handheld to connect...") );
00230     mProbeDevicesIndex=0;
00231 
00232     detect();
00233     if (!fRotateLinksTimer->start( 3000, false) ) 
00234         kdWarning()<<"Could not start Device link rotation timer"<<endl;
00235 }
00236 
00237 
00238 void ProbeDialog::detect(int i)
00239 {
00240     FUNCTIONSETUP;
00241     PilotLinkList::iterator end(mDeviceLinks[mProbeDevicesIndex].end());
00242     for (PilotLinkList::iterator it=mDeviceLinks[mProbeDevicesIndex].begin(); it!=end; ++it)
00243     {
00244         if (*it) (*it)->close();
00245     }
00246     mProbeDevicesIndex = i;
00247     end=mDeviceLinks[mProbeDevicesIndex].end();
00248     for (PilotLinkList::iterator it=mDeviceLinks[mProbeDevicesIndex].begin(); it!=end; ++it)
00249     {
00250         if (*it) (*it)->reset();
00251     }
00252 }
00253 
00254 void ProbeDialog::detect()
00255 {
00256     detect( (mProbeDevicesIndex+1)%3 );
00257 }
00258 
00259 void ProbeDialog::timeout()
00260 {
00261     disconnectDevices();
00262     if (!mDetected) {
00263         fStatus->setText( i18n("Timeout reached, could not detect a handheld.") );
00264         KMessageBox::information ( this, i18n("<qt>A handheld could not be detected. Possible check the following things:</p>"
00265             "<ul><li> Have you pressed the hotsync button on the handheld?\n"
00266             "<li> Make sure the device sits in the cradle correctly.\n"
00267             "<li> Make sure the cradle is correctly plugged in to the computer.\n"
00268             "<li> Have you checked that your device is actually supported by kpilot (see http://www.kpilot.org).\n"
00269             "</ul>"
00270             ), i18n("Automatic Detection Failed"), "AutoDetectionFailed");
00271     }
00272 }
00273 
00274 void ProbeDialog::connection( KPilotDeviceLink*lnk)
00275 {
00276     FUNCTIONSETUP;
00277 
00278     mActiveLink = lnk;
00279     if ( !mActiveLink ) return;
00280     KPilotUser*usr( mActiveLink->getPilotUser() );
00281 
00282     mUserName = usr->getUserName();
00283     mUID = usr->getUserID();
00284     mDevice = mActiveLink->pilotPath();
00285 
00286     fStatus->setText( i18n("Found a connected device on %1").arg(mDevice) );
00287     fUser->setText( mUserName );
00288     fDevice->setText( mDevice );
00289     mDetected = true;
00290 
00291     fResultsGroup->setEnabled( true );
00292     enableButtonOK(true);
00293     
00294     QTimer::singleShot(0, this, SLOT(retrieveDBList()));
00295 }
00296 
00297 void ProbeDialog::retrieveDBList()
00298 {
00299     QPtrList<DBInfo> dbs = mActiveLink->getDBList();
00300     mDBs.clear();
00301     dbs.setAutoDelete( true );
00302     char buff[7];
00303     buff[0] = '[';
00304 
00305     DBInfo *dbi;
00306     for ( dbi = dbs.first(); dbi; dbi = dbs.next() ) {
00307         if ( dbi ) {
00308             set_long( &buff[1], dbi->creator );
00309             buff[5] = ']';
00310             buff[6] = '\0';
00311             QString cr( buff );
00312             mDBs << cr;
00313             dbi->name[33]='\0';
00314             mDBs << QString( dbi->name );
00315         }
00316     }
00317     mDBs.sort();
00318     
00319     QString old( QString::null ); 
00320     QStringList::Iterator itr = mDBs.begin();
00321     while ( itr != mDBs.end() ) {
00322         if ( old == *itr ) {
00323             itr = mDBs.remove( itr );
00324         } else {
00325             old = *itr;
00326             ++itr;
00327         }
00328     }
00329     mActiveLink->endOfSync();
00330 
00331     QTimer::singleShot(0, this, SLOT(disconnectDevices()));
00332 }
00333 void ProbeDialog::disconnectDevices()
00334 {
00335     FUNCTIONSETUP;
00336 
00337     if (!mDetected) fStatus->setText( i18n("Disconnected from all devices") );
00338     fProcessEventsTimer->stop( );
00339     fTimeoutTimer->stop();
00340     fProgressTimer->stop();
00341     fRotateLinksTimer->stop();
00342     fProgress->setProgress(fProgress->totalSteps());
00343     for (int i=0; i<3; ++i)
00344     {
00345         PilotLinkList::iterator end(mDeviceLinks[i].end());
00346         for (PilotLinkList::iterator it=mDeviceLinks[i].begin(); it!=end; ++it)
00347         {
00348             (*it)->close();
00349             KPILOT_DELETE(*it);
00350         }
00351         mDeviceLinks[i].clear();
00352     }
00353 
00354 
00355     PilotDaemonDCOP_stub *daemonStub = new PilotDaemonDCOP_stub("kpilotDaemon", "KPilotDaemonIface");
00356     if (daemonStub)
00357     {
00358         daemonStub->startListening();
00359     }
00360     KPILOT_DELETE(daemonStub);
00361 }
00362 
KDE Home | KDE Accessibility Home | Description of Access Keys