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