kpilot

kpilotdevicelink.cc

Go to the documentation of this file.
00001 /* KPilot
00002  **
00003  ** Copyright (C) 1998-2001 by Dan Pilone
00004  ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005  ** Copyright (C) 2006-2007 Adriaan de Groot <groot@kde.org>
00006  ** Copyright (C) 2007 Jason 'vanRijn' Kasper <vR@movingparts.net>
00007  **
00008  */
00009 
00010 /*
00011  ** This program is free software; you can redistribute it and/or modify
00012  ** it under the terms of the GNU Lesser General Public License as published by
00013  ** the Free Software Foundation; either version 2.1 of the License, or
00014  ** (at your option) any later version.
00015  **
00016  ** This program is distributed in the hope that it will be useful,
00017  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019  ** GNU Lesser General Public License for more details.
00020  **
00021  ** You should have received a copy of the GNU Lesser General Public License
00022  ** along with this program in a file called COPYING; if not, write to
00023  ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00024  ** MA 02110-1301, USA.
00025  */
00026 
00027 /*
00028  ** Bug reports and questions can be sent to kde-pim@kde.org
00029  */
00030 
00031 #include "options.h"
00032 
00033 #include <sys/stat.h>
00034 #include <sys/types.h>
00035 #include <stdio.h>
00036 #include <unistd.h>
00037 #include <fcntl.h>
00038 #include <errno.h>
00039 
00040 #include <iostream>
00041 
00042 #include <pi-source.h>
00043 #include <pi-socket.h>
00044 #include <pi-dlp.h>
00045 #include <pi-file.h>
00046 #include <pi-buffer.h>
00047 
00048 #include <qdir.h>
00049 #include <qtimer.h>
00050 #include <qdatetime.h>
00051 #include <qthread.h>
00052 #include <qsocketnotifier.h>
00053 
00054 #include <kconfig.h>
00055 #include <kmessagebox.h>
00056 #include <kstandarddirs.h>
00057 #include <kurl.h>
00058 #include <kio/netaccess.h>
00059 
00060 #include "pilotUser.h"
00061 #include "pilotSysInfo.h"
00062 #include "pilotCard.h"
00063 #include "pilotSerialDatabase.h"
00064 #include "pilotLocalDatabase.h"
00065 
00066 #include "kpilotlink.h"
00067 #include "kpilotdevicelinkPrivate.moc"
00068 #include "kpilotdevicelink.moc"
00069 
00070 
00071 DeviceMap *DeviceMap::mThis = 0L;
00072 
00073 
00074 static inline void startOpenTimer(DeviceCommThread *dev, QTimer *&t)
00075 {
00076     if ( !t)
00077     {
00078         t = new QTimer(dev);
00079         QObject::connect(t, SIGNAL(timeout()), dev, SLOT(openDevice()));
00080     }
00081     // just a single-shot timer.  we'll know when to start it again...
00082     t->start(1000, true);
00083 }
00084 
00085 DeviceCommThread::DeviceCommThread(KPilotDeviceLink *d) :
00086     QThread(),
00087     fDone(true),
00088     fHandle(d),
00089     fOpenTimer(0L),
00090     fSocketNotifier(0L),
00091     fSocketNotifierActive(false),
00092     fWorkaroundUSBTimer(0L),
00093     fPilotSocket(-1),
00094     fTempSocket(-1),
00095     fAcceptedCount(0)
00096 {
00097     FUNCTIONSETUP;
00098 }
00099 
00100 
00101 DeviceCommThread::~DeviceCommThread()
00102 {
00103     FUNCTIONSETUPL(2);
00104     close();
00105     KPILOT_DELETE(fWorkaroundUSBTimer);
00106 }
00107 
00108 void DeviceCommThread::close()
00109 {
00110     FUNCTIONSETUPL(2);
00111 
00112     KPILOT_DELETE(fWorkaroundUSBTimer);
00113     KPILOT_DELETE(fOpenTimer);
00114     KPILOT_DELETE(fSocketNotifier);
00115     fSocketNotifierActive=false;
00116 
00117     if (fTempSocket != -1)
00118     {
00119         DEBUGKPILOT << fname
00120         << ": device comm thread closing socket: ["
00121         << fTempSocket << "]" << endl;
00122 
00123         pi_close(fTempSocket);
00124     }
00125 
00126     if (fPilotSocket != -1)
00127     {
00128         DEBUGKPILOT << fname
00129         << ": device comm thread closing socket: ["
00130         << fPilotSocket << "]" << endl;
00131 
00132         pi_close(fPilotSocket);
00133     }
00134 
00135     fTempSocket = (-1);
00136     fPilotSocket = (-1);
00137 
00138     DeviceMap::self()->unbindDevice(link()->fRealPilotPath);
00139 }
00140 
00141 void DeviceCommThread::reset()
00142 {
00143     FUNCTIONSETUP;
00144 
00145     if (link()->fMessages->shouldPrint(Messages::OpenFailMessage))
00146     {
00147         QApplication::postEvent(link(), new DeviceCommEvent(EventLogMessage,
00148                 i18n("Could not open device: %1 (will retry)")
00149                 .arg(link()->pilotPath() )));
00150     }
00151 
00152     link()->fMessages->reset();
00153     close();
00154 
00155     // Timer already deleted by close() call.
00156     startOpenTimer(this,fOpenTimer);
00157 
00158     link()->fLinkStatus = WaitingForDevice;
00159 }
00160 
00170 void DeviceCommThread::openDevice()
00171 {
00172     FUNCTIONSETUPL(2);
00173 
00174     bool deviceOpened = false;
00175 
00176     // This transition (from Waiting to Found) can only be
00177     // taken once.
00178     //
00179     if (link()->fLinkStatus == WaitingForDevice)
00180     {
00181         link()->fLinkStatus = FoundDevice;
00182     }
00183 
00184     if (link()->fMessages->shouldPrint(Messages::OpenMessage))
00185     {
00186         QApplication::postEvent(link(), new DeviceCommEvent(EventLogMessage,
00187                 i18n("Trying to open device %1...")
00188                 .arg(link()->fPilotPath)));
00189     }
00190 
00191     // if we're not supposed to be done, try to open the main pilot
00192     // path...
00193     if (!fDone && link()->fPilotPath.length() > 0)
00194     {
00195         DEBUGKPILOT << fname << ": Opening main pilot path: ["
00196             << link()->fPilotPath << "]." << endl;
00197         deviceOpened = open(link()->fPilotPath);
00198     }
00199 
00200     // only try the temp device if our earlier attempt didn't work and the temp
00201     // device is different than the main device, and it's a non-empty
00202     // string
00203     bool tryTemp = !deviceOpened && (link()->fTempDevice.length() > 0) && (link()->fPilotPath != link()->fTempDevice);
00204 
00205     // if we're not supposed to be done, and we should try the temp
00206     // device, try the temp device...
00207     if (!fDone && tryTemp)
00208     {
00209         DEBUGKPILOT << fname << ": Couldn't open main pilot path. "
00210             << "Now trying temp device: ["
00211             << link()->fTempDevice << "]." << endl;
00212         deviceOpened = open(link()->fTempDevice);
00213     }
00214 
00215     // if we couldn't connect, try to connect again...
00216     if (!fDone && !deviceOpened)
00217     {
00218         startOpenTimer(this, fOpenTimer);
00219     }
00220 }
00221 
00222 bool DeviceCommThread::open(const QString &device)
00223 {
00224     FUNCTIONSETUPL(2);
00225 
00226     int ret;
00227     int e = 0;
00228     QString msg;
00229 
00230     if (fTempSocket != -1)
00231     {
00232         pi_close(fTempSocket);
00233     }
00234     fTempSocket = (-1);
00235 
00236     link()->fRealPilotPath
00237             = KStandardDirs::realFilePath(device.isEmpty() ? link()->fPilotPath : device);
00238 
00239     if ( !DeviceMap::self()->canBind(link()->fRealPilotPath) )
00240     {
00241         msg = i18n("Already listening on that device");
00242 
00243         WARNINGKPILOT << "Pilot Path: ["
00244             << link()->fRealPilotPath << "] already connected." << endl;
00245         WARNINGKPILOT << msg << endl;
00246 
00247         link()->fLinkStatus = PilotLinkError;
00248 
00249         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg));
00250 
00251         return false;
00252     }
00253 
00254     DEBUGKPILOT << fname << ": Trying to create socket." << endl;
00255 
00256     fTempSocket = pi_socket(PI_AF_PILOT, PI_SOCK_STREAM, PI_PF_DLP);
00257 
00258     if (fTempSocket < 0)
00259     {
00260         e = errno;
00261         msg = i18n("Cannot create socket for communicating "
00262                 "with the Pilot (%1)").arg(errorMessage(e));
00263         DEBUGKPILOT << msg << endl;
00264         DEBUGKPILOT << "(" << strerror(e) << ")" << endl;
00265 
00266         link()->fLinkStatus = PilotLinkError;
00267 
00268         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg));
00269 
00270         return false;
00271     }
00272 
00273     DEBUGKPILOT << fname << ": Got socket: [" << fTempSocket << "]" << endl;
00274 
00275     link()->fLinkStatus = CreatedSocket;
00276 
00277     DEBUGKPILOT << fname << ": Binding to path: ["
00278         << link()->fRealPilotPath << "]" << endl;
00279 
00280     ret = pi_bind(fTempSocket, QFile::encodeName(link()->fRealPilotPath));
00281 
00282     if (ret < 0)
00283     {
00284         DEBUGKPILOT << fname
00285             << ": pi_bind error: ["
00286             << strerror(errno) << "]" << endl;
00287 
00288         e = errno;
00289         msg = i18n("Cannot open Pilot port \"%1\". ").arg(link()->fRealPilotPath);
00290 
00291         DEBUGKPILOT << msg << endl;
00292         DEBUGKPILOT << "(" << strerror(e) << ")" << endl;
00293 
00294         link()->fLinkStatus = PilotLinkError;
00295 
00296         if (link()->fMessages->shouldPrint(Messages::OpenFailMessage))
00297         {
00298             QApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg));
00299         }
00300 
00301         return false;
00302     }
00303 
00304     link()->fLinkStatus = DeviceOpen;
00305     DeviceMap::self()->bindDevice(link()->fRealPilotPath);
00306 
00307     fSocketNotifier = new QSocketNotifier(fTempSocket,
00308             QSocketNotifier::Read, this);
00309     QObject::connect(fSocketNotifier, SIGNAL(activated(int)),
00310             this, SLOT(acceptDevice()));
00311     fSocketNotifierActive=true;
00312 
00319     int timeout=20000;
00320     if (link()->fWorkaroundUSB)
00321     {
00322         timeout=5000;
00323     }
00324 
00325     fWorkaroundUSBTimer = new QTimer(this);
00326     connect(fWorkaroundUSBTimer, SIGNAL(timeout()), this, SLOT(workaroundUSB()));
00327     fWorkaroundUSBTimer->start(timeout, true);
00328 
00329     return true;
00330 }
00331 
00339 void DeviceCommThread::acceptDevice()
00340 {
00341     FUNCTIONSETUP;
00342 
00343     int ret;
00344 
00350     if (!fSocketNotifierActive)
00351     {
00352         if (!fAcceptedCount)
00353         {
00354         kdWarning() << k_funcinfo << ": Accidentally in acceptDevice()"
00355             << endl;
00356         }
00357         fAcceptedCount++;
00358         if (fAcceptedCount>10)
00359         {
00360             // Damn the torpedoes
00361             KPILOT_DELETE(fSocketNotifier);
00362         }
00363         return;
00364     }
00365 
00366     if (fSocketNotifier)
00367     {
00368         // fSocketNotifier->setEnabled(false);
00369         fSocketNotifierActive=false;
00370         KPILOT_DELETE(fSocketNotifier);
00371     }
00372 
00373     DEBUGKPILOT << fname << ": Found connection on device: ["
00374         << link()->pilotPath().latin1() << "]." <<endl;
00375 
00376     DEBUGKPILOT << fname
00377         << ": Current status: ["
00378         << link()->statusString()
00379         << "] and socket: [" << fTempSocket << "]" << endl;
00380 
00381     ret = pi_listen(fTempSocket, 1);
00382     if (ret < 0)
00383     {
00384         char *s = strerror(errno);
00385 
00386         WARNINGKPILOT << "pi_listen returned: [" << s << "]" << endl;
00387 
00388         // Presumably, strerror() returns things in
00389         // local8Bit and not latin1.
00390         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError,
00391                 i18n("Cannot listen on Pilot socket (%1)").
00392                 arg(QString::fromLocal8Bit(s))));
00393         reset();
00394         return;
00395     }
00396 
00397     QApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, QString::null, 10));
00398 
00399     DEBUGKPILOT << fname <<
00400         ": Listening to pilot. Now trying accept..." << endl;
00401 
00402     int timeout = 20;
00403     fPilotSocket = pi_accept_to(fTempSocket, 0, 0, timeout);
00404 
00405     if (fPilotSocket < 0)
00406     {
00407         char *s = strerror(errno);
00408 
00409         WARNINGKPILOT << "pi_accept returned: [" << s << "]" << endl;
00410 
00411         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError, i18n("Cannot accept Pilot (%1)")
00412                 .arg(QString::fromLocal8Bit(s))));
00413 
00414         link()->fLinkStatus = PilotLinkError;
00415         reset();
00416         return;
00417     }
00418 
00419     DEBUGKPILOT << fname << ": Link accept done." << endl;
00420 
00421     if ((link()->fLinkStatus != DeviceOpen) || (fPilotSocket == -1))
00422     {
00423         link()->fLinkStatus = PilotLinkError;
00424         WARNINGKPILOT << "Already connected or unable to connect!" << endl;
00425 
00426         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError, i18n("Cannot accept Pilot (%1)")
00427                 .arg(i18n("already connected"))));
00428 
00429         reset();
00430         return;
00431     }
00432 
00433     QApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, QString::null, 30));
00434 
00435     DEBUGKPILOT << fname << ": doing dlp_ReadSysInfo..." << endl;
00436 
00437     struct SysInfo sys_info;
00438     if (dlp_ReadSysInfo(fPilotSocket, &sys_info) < 0)
00439     {
00440         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError,
00441                 i18n("Unable to read system information from Pilot")));
00442 
00443         link()->fLinkStatus=PilotLinkError;
00444         reset();
00445         return;
00446     }
00447     else
00448     {
00449         DEBUGKPILOT << fname << ": dlp_ReadSysInfo successful..." << endl;
00450 
00451         KPILOT_DELETE(link()->fPilotSysInfo);
00452         link()->fPilotSysInfo = new KPilotSysInfo(&sys_info);
00453         DEBUGKPILOT << fname
00454             << ": RomVersion: [" << link()->fPilotSysInfo->getRomVersion()
00455             << "] Locale: [" << link()->fPilotSysInfo->getLocale()
00456             << "] Product: [" << link()->fPilotSysInfo->getProductID()
00457             << "]" << endl;
00458     }
00459 
00460     // If we've made it this far, make sure our USB workaround timer doesn't fire!
00461     fWorkaroundUSBTimer->stop();
00462     KPILOT_DELETE(fWorkaroundUSBTimer);
00463 
00464     QApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, QString::null, 60));
00465 
00466     KPILOT_DELETE(link()->fPilotUser);
00467     link()->fPilotUser = new KPilotUser;
00468 
00469     DEBUGKPILOT << fname << ": doing dlp_ReadUserInfo..." << endl;
00470 
00471     /* Ask the pilot who it is.  And see if it's who we think it is. */
00472     dlp_ReadUserInfo(fPilotSocket, link()->fPilotUser->data());
00473 
00474     QString n = link()->getPilotUser().name();
00475     DEBUGKPILOT << fname
00476         << ": Read user name: [" << n << "]" << endl;
00477 
00478     QApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, i18n("Checking last PC..."), 90));
00479 
00480     /* Tell user (via Pilot) that we are starting things up */
00481     if ((ret=dlp_OpenConduit(fPilotSocket)) < 0)
00482     {
00483         DEBUGKPILOT << fname
00484             << ": dlp_OpenConduit returned: [" << ret << "]" << endl;
00485 
00486         QApplication::postEvent(link(), new DeviceCommEvent(EventLogError,
00487                 i18n("Could not read user information from the Pilot. "
00488                         "Perhaps you have a password set on the device?")));
00489 
00490     }
00491     link()->fLinkStatus = AcceptedDevice;
00492 
00493     QApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, QString::null, 100));
00494 
00495     DeviceCommEvent * ev = new DeviceCommEvent(EventDeviceReady);
00496     ev->setCurrentSocket(fPilotSocket);
00497     QApplication::postEvent(link(), ev);
00498 
00499 }
00500 
00501 void DeviceCommThread::workaroundUSB()
00502 {
00503     FUNCTIONSETUP;
00504 
00505     reset();
00506 }
00507 
00508 void DeviceCommThread::run()
00509 {
00510     FUNCTIONSETUP;
00511     fDone = false;
00512 
00513     startOpenTimer(this, fOpenTimer);
00514 
00515     int sleepBetweenPoll = 2;
00516     // keep the thread alive until we're supposed to be done
00517     while (!fDone)
00518     {
00519         QThread::sleep(sleepBetweenPoll);
00520     }
00521 
00522     close();
00523     // now sleep one last bit to make sure the pthread inside
00524     // pilot-link (potentially, if it's libusb) is done before we exit
00525     QThread::sleep(1);
00526 
00527     DEBUGKPILOT << fname << ": comm thread now done..." << endl;
00528 }
00529 
00530 KPilotDeviceLink::KPilotDeviceLink(QObject * parent, const char *name,
00531         const QString &tempDevice) :
00532     KPilotLink(parent, name), fLinkStatus(Init), fWorkaroundUSB(false),
00533             fPilotSocket(-1), fTempDevice(tempDevice), fMessages(new Messages(this)), fDeviceCommThread(0L)
00534 {
00535     FUNCTIONSETUP;
00536 
00537     DEBUGKPILOT << fname
00538         << ": Pilot-link version: [" << PILOT_LINK_NUMBER
00539         << "]" << endl;
00540 }
00541 
00542 KPilotDeviceLink::~KPilotDeviceLink()
00543 {
00544     FUNCTIONSETUP;
00545     close();
00546     KPILOT_DELETE(fPilotSysInfo);
00547     KPILOT_DELETE(fPilotUser);
00548     KPILOT_DELETE(fMessages);
00549 }
00550 
00551 /* virtual */bool KPilotDeviceLink::isConnected() const
00552 {
00553     return fLinkStatus == AcceptedDevice;
00554 }
00555 
00556 /* virtual */bool KPilotDeviceLink::event(QEvent *e)
00557 {
00558     FUNCTIONSETUP;
00559 
00560     bool handled = false;
00561 
00562     if ((int)e->type() == EventDeviceReady)
00563     {
00564         DeviceCommEvent* t = static_cast<DeviceCommEvent*>(e);
00565         fPilotSocket = t->currentSocket();
00566         emit deviceReady( this);
00567         handled = true;
00568     }
00569     else if ((int)e->type() == EventLogMessage)
00570     {
00571         DeviceCommEvent* t = static_cast<DeviceCommEvent*>(e);
00572         emit logMessage(t->message());
00573         handled = true;
00574     }
00575     else if ((int)e->type() == EventLogError)
00576     {
00577         DeviceCommEvent* t = static_cast<DeviceCommEvent*>(e);
00578         emit logError(t->message());
00579         handled = true;
00580     }
00581     else if ((int)e->type() == EventLogProgress)
00582     {
00583         DeviceCommEvent* t = static_cast<DeviceCommEvent*>(e);
00584         emit logProgress(t->message(), t->progress());
00585         handled = true;
00586     }
00587     else
00588     {
00589         handled = KPilotLink::event(e);
00590     }
00591 
00592     return handled;
00593 }
00594 
00595 void KPilotDeviceLink::stopCommThread()
00596 {
00597     FUNCTIONSETUP;
00598     if (fDeviceCommThread)
00599     {
00600         fDeviceCommThread->setDone(true);
00601 
00602         // try to wait for our thread to finish, but don't
00603         // block the main thread forever
00604         if (fDeviceCommThread->running())
00605         {
00606             DEBUGKPILOT << fname
00607                 << ": comm thread still running. "
00608                 << "waiting for it to complete." << endl;
00609             bool done = fDeviceCommThread->wait(5000);
00610             if (!done)
00611             {
00612                 DEBUGKPILOT << fname
00613                     << ": comm thread still running "
00614                     << "after wait(). "
00615                     << "going to have to terminate it."
00616                     << endl;
00617                 // not normally to be done, but we must make sure
00618                 // that this device doesn't come back alive
00619                 fDeviceCommThread->terminate();
00620                 fDeviceCommThread->wait();
00621             }
00622         }
00623 
00624         fDeviceCommThread->close();
00625 
00626         KPILOT_DELETE(fDeviceCommThread);
00627     }
00628 }
00629 
00630 void KPilotDeviceLink::close()
00631 {
00632     FUNCTIONSETUP;
00633 
00634     stopCommThread();
00635 
00636     fPilotSocket = (-1);
00637 }
00638 
00639 void KPilotDeviceLink::reset(const QString & dP)
00640 {
00641     FUNCTIONSETUP;
00642 
00643     fLinkStatus = Init;
00644 
00645     // Release all resources
00646     //
00647     close();
00648     fPilotPath = QString::null;
00649 
00650     fPilotPath = dP;
00651     if (fPilotPath.isEmpty())
00652         fPilotPath = fTempDevice;
00653     if (fPilotPath.isEmpty())
00654         return;
00655 
00656     reset();
00657 }
00658 
00659 void KPilotDeviceLink::startCommThread()
00660 {
00661     FUNCTIONSETUP;
00662 
00663     stopCommThread();
00664 
00665     if (fTempDevice.isEmpty() && pilotPath().isEmpty())
00666     {
00667         WARNINGKPILOT << "No point in trying empty device."
00668             << endl;
00669 
00670         QString msg = i18n("The Pilot device is not configured yet.");
00671         WARNINGKPILOT << msg << endl;
00672 
00673         fLinkStatus = PilotLinkError;
00674 
00675         emit logError(msg);
00676         return;
00677     }
00678 
00679     fDeviceCommThread = new DeviceCommThread(this);
00680     fDeviceCommThread->start();
00681 }
00682 
00683 void KPilotDeviceLink::reset()
00684 {
00685     FUNCTIONSETUP;
00686 
00687     fMessages->reset();
00688     close();
00689 
00690     checkDevice();
00691 
00692     fLinkStatus = WaitingForDevice;
00693 
00694     startCommThread();
00695 }
00696 
00697 void KPilotDeviceLink::checkDevice()
00698 {
00699     // If the device exists yet doesn't have the right
00700     // permissions, complain and then continue anyway.
00701     //
00702     QFileInfo fi(fPilotPath);
00703     if (fi.exists())
00704     {
00705         // If it exists, it ought to be RW already.
00706         //
00707         if (!(fi.isReadable() && fi.isWritable()))
00708         {
00709             emit logError(i18n("Pilot device %1 is not read-write.")
00710             .arg(fPilotPath));
00711         }
00712     }
00713     else
00714     {
00715         // It doesn't exist, mention this in the log
00716         // (relevant as long as we use only one device type)
00717         //
00718         emit
00719                 logError(i18n("Pilot device %1 does not exist. "
00720                         "Probably it is a USB device and will appear during a HotSync.")
00721                 .arg(fPilotPath));
00722         // Suppress all normal and error messages about opening the device.
00723         fMessages->block(Messages::OpenMessage | Messages::OpenFailMessage,
00724                 true);
00725     }
00726 }
00727 
00728 void KPilotDeviceLink::setTempDevice(const QString &d)
00729 {
00730     fTempDevice = d;
00731     DeviceMap::self()->bindDevice(fTempDevice);
00732 }
00733 
00734 /* virtual */bool KPilotDeviceLink::tickle()
00735 {
00736     // No FUNCTIONSETUP here because it may be called from
00737     // a separate thread.
00738     return pi_tickle(pilotSocket()) >= 0;
00739 }
00740 
00741 /* virtual */void KPilotDeviceLink::addSyncLogEntryImpl(const QString &entry)
00742 {
00743     dlp_AddSyncLogEntry(fPilotSocket,
00744             const_cast<char *>((const char *)Pilot::toPilot(entry)));
00745 }
00746 
00747 bool KPilotDeviceLink::installFile(const QString & f, const bool deleteFile)
00748 {
00749     FUNCTIONSETUP;
00750 
00751     DEBUGKPILOT << fname << ": Installing file " << f << endl;
00752 
00753     if (!QFile::exists(f))
00754         return false;
00755 
00756     char buffer[PATH_MAX];
00757     memset(buffer, 0, PATH_MAX);
00758     strlcpy(buffer, QFile::encodeName(f), PATH_MAX);
00759     struct pi_file *pf = pi_file_open(buffer);
00760 
00761     if (!f)
00762     {
00763         WARNINGKPILOT << "Cannot open file " << f << endl;
00764         emit logError(i18n
00765             ("<qt>Cannot install the file &quot;%1&quot;.</qt>").
00766         arg(f));
00767         return false;
00768     }
00769 
00770     if (pi_file_install(pf, fPilotSocket, 0, 0L) < 0)
00771     {
00772         WARNINGKPILOT << "Cannot pi_file_install " << f << endl;
00773         emit logError(i18n
00774                 ("<qt>Cannot install the file &quot;%1&quot;.</qt>").
00775         arg(f));
00776         return false;
00777     }
00778 
00779     pi_file_close(pf);
00780     if (deleteFile)
00781         QFile::remove(f);
00782 
00783     return true;
00784 }
00785 
00786 int KPilotDeviceLink::openConduit()
00787 {
00788     return dlp_OpenConduit(fPilotSocket);
00789 }
00790 
00791 QString KPilotDeviceLink::statusString(LinkStatus l)
00792 {
00793     QString s= CSL1("KPilotDeviceLink=");
00794 
00795     switch (l)
00796     {
00797     case Init:
00798         s.append(CSL1("Init"));
00799         break;
00800     case WaitingForDevice:
00801         s.append(CSL1("WaitingForDevice"));
00802         break;
00803     case FoundDevice:
00804         s.append(CSL1("FoundDevice"));
00805         break;
00806     case CreatedSocket:
00807         s.append(CSL1("CreatedSocket"));
00808         break;
00809     case DeviceOpen:
00810         s.append(CSL1("DeviceOpen"));
00811         break;
00812     case AcceptedDevice:
00813         s.append(CSL1("AcceptedDevice"));
00814         break;
00815     case SyncDone:
00816         s.append(CSL1("SyncDone"));
00817         break;
00818     case PilotLinkError:
00819         s.append(CSL1("PilotLinkError"));
00820         break;
00821     case WorkaroundUSB:
00822         s.append(CSL1("WorkaroundUSB"));
00823         break;
00824     }
00825 
00826     return s;
00827 }
00828 
00829 QString KPilotDeviceLink::statusString() const
00830 {
00831     return statusString(status() );
00832 }
00833 
00834 void KPilotDeviceLink::endSync(EndOfSyncFlags f)
00835 {
00836     FUNCTIONSETUP;
00837 
00838     if (UpdateUserInfo == f)
00839     {
00840         getPilotUser().setLastSyncPC((unsigned long) gethostid());
00841         getPilotUser().setLastSyncDate(time(0));
00842 
00843         DEBUGKPILOT << fname << ": Writing username " << getPilotUser().name() << endl;
00844 
00845         dlp_WriteUserInfo(pilotSocket(), getPilotUser().data());
00846         addSyncLogEntry(i18n("End of HotSync\n"));
00847     }
00848     dlp_EndOfSync(pilotSocket(), 0);
00849     KPILOT_DELETE(fPilotSysInfo);
00850     KPILOT_DELETE(fPilotUser);
00851 }
00852 
00853 int KPilotDeviceLink::getNextDatabase(int index, struct DBInfo *dbinfo)
00854 {
00855     FUNCTIONSETUP;
00856 
00857     pi_buffer_t buf =   { 0, 0, 0 };
00858     int r = dlp_ReadDBList(pilotSocket(), 0, dlpDBListRAM, index, &buf);
00859     if (r >= 0)
00860     {
00861         memcpy(dbinfo, buf.data, sizeof(struct DBInfo));
00862     }
00863     return r;
00864 }
00865 
00866 // Find a database with the given name. Info about the DB is stored into dbinfo (e.g. to be used later on with retrieveDatabase).
00867 int KPilotDeviceLink::findDatabase(const char *name, struct DBInfo *dbinfo,
00868         int index, unsigned long type, unsigned long creator)
00869 {
00870     FUNCTIONSETUP;
00871     return dlp_FindDBInfo(pilotSocket(), 0, index, const_cast<char *>(name),
00872             type, creator, dbinfo);
00873 }
00874 
00875 bool KPilotDeviceLink::retrieveDatabase(const QString &fullBackupName,
00876         DBInfo *info)
00877 {
00878     FUNCTIONSETUP;
00879 
00880     if (fullBackupName.isEmpty() || !info)
00881     {
00882         // Don't even bother trying to convert or retrieve.
00883         return false;
00884     }
00885 
00886     DEBUGKPILOT << fname << ": Writing DB <" << info->name << "> "
00887         << " to " << fullBackupName << endl;
00888 
00889     QCString encodedName = QFile::encodeName(fullBackupName);
00890     struct pi_file *f = pi_file_create(encodedName, info);
00891 
00892     if (!f)
00893     {
00894         WARNINGKPILOT << "Failed, unable to create file" << endl;
00895         return false;
00896     }
00897 
00898     if (pi_file_retrieve(f, pilotSocket(), 0, 0L) < 0)
00899     {
00900         WARNINGKPILOT << "Failed, unable to back up database" << endl;
00901 
00902         pi_file_close(f);
00903         return false;
00904     }
00905 
00906     pi_file_close(f);
00907     return true;
00908 }
00909 
00910 KPilotLink::DBInfoList KPilotDeviceLink::getDBList(int cardno, int flags)
00911 {
00912     bool cont=true;
00913     DBInfoList dbs;
00914     int index=0;
00915     while (cont)
00916     {
00917         pi_buffer_t buf = { 0, 0, 0 };
00918         pi_buffer_clear(&buf);
00919         // DBInfo*dbi=new DBInfo();
00920         if (dlp_ReadDBList(pilotSocket(), cardno, flags | dlpDBListMultiple,
00921                 index, &buf)<0)
00922         {
00923             cont=false;
00924         }
00925         else
00926         {
00927             DBInfo db_n;
00928             DBInfo *db_it = (DBInfo *)buf.data;
00929             int info_count = buf.used / sizeof(struct DBInfo);
00930 
00931             while (info_count>0)
00932             {
00933                 memcpy(&db_n, db_it, sizeof(struct DBInfo));
00934                 ++db_it;
00935                 info_count--;
00936                 dbs.append(db_n);
00937             }
00938             index=db_n.index+1;
00939         }
00940     }
00941     return dbs;
00942 }
00943 
00944 const KPilotCard *KPilotDeviceLink::getCardInfo(int card)
00945 {
00946     KPilotCard *cardinfo=new KPilotCard();
00947     if (dlp_ReadStorageInfo(pilotSocket(), card, cardinfo->cardInfo())<0)
00948     {
00949         WARNINGKPILOT << "Could not get info for card " << card << endl;
00950 
00951         KPILOT_DELETE(cardinfo);
00952         return 0L;
00953     }
00954     return cardinfo;
00955 }
00956 
00957 PilotDatabase *KPilotDeviceLink::database(const QString &name)
00958 {
00959     return new PilotSerialDatabase( this, name );
00960 }
00961 
00962 PilotDatabase *KPilotDeviceLink::database(const DBInfo *info)
00963 {
00964     return new PilotSerialDatabase( this, info );
00965 }
00966