OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / shared / symbianutils / bluetoothlistener.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "bluetoothlistener.h"
34 #include "trkdevice.h"
35
36 #include <QtCore/QDebug>
37
38 #ifdef Q_OS_UNIX
39 #   include <unistd.h>
40 #   include <signal.h>
41 #else
42 #   include <windows.h>
43 #endif
44
45 // Process id helpers.
46 #ifdef Q_OS_WIN
47 inline DWORD processId(const QProcess &p)
48 {
49     if (const Q_PID processInfoStruct = p.pid())
50         return processInfoStruct->dwProcessId;
51     return 0;
52 }
53 #else
54 inline Q_PID processId(const QProcess &p)
55 {
56     return p.pid();
57 }
58 #endif
59
60
61 enum { debug = 0 };
62
63 namespace trk {
64
65 struct BluetoothListenerPrivate {
66     BluetoothListenerPrivate();
67     QString device;
68     QProcess process;
69 #ifdef Q_OS_WIN
70     DWORD pid;
71 #else
72     Q_PID pid;
73 #endif
74     bool printConsoleMessages;
75     BluetoothListener::Mode mode;
76 };
77
78 BluetoothListenerPrivate::BluetoothListenerPrivate() :
79     pid(0),
80     printConsoleMessages(false),
81     mode(BluetoothListener::Listen)
82 {
83 }
84
85 BluetoothListener::BluetoothListener(QObject *parent) :
86     QObject(parent),
87     d(new BluetoothListenerPrivate)
88 {
89     d->process.setProcessChannelMode(QProcess::MergedChannels);
90
91     connect(&d->process, SIGNAL(readyReadStandardError()),
92             this, SLOT(slotStdError()));
93     connect(&d->process, SIGNAL(readyReadStandardOutput()),
94             this, SLOT(slotStdOutput()));
95     connect(&d->process, SIGNAL(finished(int, QProcess::ExitStatus)),
96             this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
97     connect(&d->process, SIGNAL(error(QProcess::ProcessError)),
98             this, SLOT(slotProcessError(QProcess::ProcessError)));
99 }
100
101 BluetoothListener::~BluetoothListener()
102 {
103     const int trc = terminateProcess();
104     if (debug)
105         qDebug() << "~BluetoothListener: terminated" << trc;
106     delete d;
107 }
108
109 BluetoothListener::Mode BluetoothListener::mode() const
110 {
111     return d->mode;
112 }
113
114 void BluetoothListener::setMode(Mode m)
115 {
116     d->mode = m;
117 }
118
119 bool BluetoothListener::printConsoleMessages() const
120 {
121     return d->printConsoleMessages;
122 }
123
124 void BluetoothListener::setPrintConsoleMessages(bool p)
125 {
126     d->printConsoleMessages = p;
127 }
128
129 int BluetoothListener::terminateProcess()
130 {
131     enum { TimeOutMS = 200 };
132     if (debug)
133         qDebug() << "terminateProcess" << d->process.pid() << d->process.state();
134     if (d->process.state() == QProcess::NotRunning)
135         return -1;
136     emitMessage(tr("%1: Stopping listener %2...").arg(d->device).arg(processId(d->process)));
137     // When listening, the process should terminate by itself after closing the connection
138     if (mode() == Listen && d->process.waitForFinished(TimeOutMS))
139         return 0;
140 #ifdef Q_OS_UNIX
141     kill(d->process.pid(), SIGHUP); // Listens for SIGHUP
142     if (d->process.waitForFinished(TimeOutMS))
143         return 1;
144 #endif
145     d->process.terminate();
146     if (d->process.waitForFinished(TimeOutMS))
147         return 2;
148     d->process.kill();
149     return 3;
150 }
151
152 bool BluetoothListener::start(const QString &device, QString *errorMessage)
153 {
154     if (d->process.state() != QProcess::NotRunning) {
155         *errorMessage = QLatin1String("Internal error: Still running.");
156         return false;
157     }
158     d->device = device;
159     const QString binary = QLatin1String("rfcomm");
160     QStringList arguments;
161     arguments << QLatin1String("-r")
162               << (d->mode == Listen ? QLatin1String("listen") : QLatin1String("watch"))
163               << device << QString(QLatin1Char('1'));
164     if (debug)
165         qDebug() << binary << arguments;
166     emitMessage(tr("%1: Starting Bluetooth listener %2...").arg(device, binary));
167     d->pid = 0;
168     d->process.start(binary, arguments);
169     if (!d->process.waitForStarted()) {
170         *errorMessage = tr("Unable to run '%1': %2").arg(binary, d->process.errorString());
171         return false;
172     }
173     d->pid = processId(d->process); // Forgets it after crash/termination
174     emitMessage(tr("%1: Bluetooth listener running (%2).").arg(device).arg(processId(d->process)));
175     return true;
176 }
177
178 void BluetoothListener::slotStdOutput()
179 {
180     emitMessage(QString::fromLocal8Bit(d->process.readAllStandardOutput()));
181 }
182
183 void BluetoothListener::emitMessage(const QString &m)
184 {
185     if (d->printConsoleMessages || debug)
186         qDebug("%s\n", qPrintable(m));
187     emit message(m);
188 }
189
190 void BluetoothListener::slotStdError()
191 {
192     emitMessage(QString::fromLocal8Bit(d->process.readAllStandardError()));
193 }
194
195 void BluetoothListener::slotProcessFinished(int ex, QProcess::ExitStatus state)
196 {
197     switch (state) {
198     case QProcess::NormalExit:
199         emitMessage(tr("%1: Process %2 terminated with exit code %3.")
200                     .arg(d->device).arg(d->pid).arg(ex));
201         break;
202     case QProcess::CrashExit:
203         emitMessage(tr("%1: Process %2 crashed.").arg(d->device).arg(d->pid));
204         break;
205     }
206     emit terminated();
207 }
208
209 void BluetoothListener::slotProcessError(QProcess::ProcessError error)
210 {
211     emitMessage(tr("%1: Process error %2: %3")
212         .arg(d->device).arg(error).arg(d->process.errorString()));
213 }
214
215 } // namespace trk