summaryrefslogtreecommitdiffstats
path: root/kpilot/lib/kpilotdevicelinkPrivate.h
blob: be2bbda35822693ba7e3fc156f6b850bdf05be4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#ifndef _KPILOT_KPILOTDEVICELINKPRIVATE_H
#define _KPILOT_KPILOTDEVICELINKPRIVATE_H
/*
**
** Copyright (C) 2007 by Jason 'vanRijn' Kasper <vR@movingparts.net>
**
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser 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 <errno.h>

#include <qstringlist.h>
#include <qthread.h>

#include "kpilotdevicelink.h"
#include "options.h"

class QTimer;
class QSocketNotifier;

// singleton helper class
class DeviceMap
{
public:
	static DeviceMap *self()
	{
		if (!mThis)
			mThis = new DeviceMap();
		return mThis;
	}

	bool canBind(const QString &device)
	{
		FUNCTIONSETUPL(5);
		DEBUGKPILOT << fname << ": device: ["
			<< device << "]" << endl;

		showList();
		return !mBoundDevices.contains(device);
	}

	void bindDevice(const QString &device)
	{
		FUNCTIONSETUPL(5);
		DEBUGKPILOT << fname << ": device: ["
			<< device << "]" << endl;

		mBoundDevices.append(device);
		showList();
	}

	void unbindDevice(const QString &device)
	{
		FUNCTIONSETUPL(5);
		DEBUGKPILOT << fname << ": device: ["
			<< device << "]" << endl;

		mBoundDevices.remove(device);
		showList();
	}

protected:
	DeviceMap()
	{
		mBoundDevices.clear();
	}
	~DeviceMap()
	{
	}

	QStringList mBoundDevices;
	static DeviceMap *mThis;

private:
	void showList() const
	{
		FUNCTIONSETUPL(5);

		if ( !(mBoundDevices.count() > 0))
			return;

		DEBUGKPILOT << fname << ": Bound devices: ["
			<< ((mBoundDevices.count() > 0) ?
					mBoundDevices.join(CSL1(", ")) : CSL1("<none>"))
			<< "]" << endl;
	}
};

class Messages
{
public:
	Messages(KPilotDeviceLink *parent) :
		fDeviceLink(parent)
	{
		reset();
	}

	void reset()
	{
		messages = 0;
		messagesMask = ~messageIsError; // Never block errors
	}

	void block(unsigned int m, bool force=false)
	{
		if (force)
		{
			// Force blocking this message, even if it's an error msg.
			messages |= m;
		}
		else
		{
			messages |= (m & messagesMask);
		}
	}

	/**
	 * Some messages are only printed once and are suppressed
	 * after that. These are indicated by flag bits in
	 * messages. The following enum is a bitfield.
	 */
	enum
	{
		OpenMessage=1, ///< Trying to open device ..
		OpenFailMessage=2 ///< Failed to open device ...
	};
	int messages;
	int messagesMask;
	static const int messageIsError = 0;

	/** Determines whether message @p s which has an id of @p msgid (one of
	 *  the enum values mentioned above) should be printed, which is only if that
	 *  message has not been suppressed through messagesMask.
	 *  If return is true, this method also adds it to the messagesMask.
	 */
	bool shouldPrint(int msgid)
	{
		if (!(messages & msgid))
		{
			block(msgid);
			return true;
		}
		else
		{
			return false;
		}
	}

protected:
	KPilotDeviceLink *fDeviceLink;
};

class DeviceCommEvent : public QEvent
{
public:
	DeviceCommEvent(DeviceCustomEvents type, QString msg = QString::null,
			int progress = 0) :
		QEvent( (QEvent::Type)type ), fMessage(msg), fProgress(progress),
				fPilotSocket(-1)
	{
	}
	QString message() const
	{
		return fMessage;
	}
	int progress()
	{
		return fProgress;
	}

	inline void setCurrentSocket(int i)
	{
		fPilotSocket = i;
	}

	inline int currentSocket()
	{
		return fPilotSocket;
	}
private:
	QString fMessage;
	int fProgress;
	/**
	 * Pilot-link library handles for the device once it's opened.
	 */
	int fPilotSocket;
};

/** Class that handles all device communications.  We do this
 in a different thread so that we do not block the main Qt
 Event thread (similar to Swing's AWT event dispatch thread).
 */

class DeviceCommThread : public QObject, public QThread
{
friend class KPilotDeviceLink;

Q_OBJECT

public:
	DeviceCommThread(KPilotDeviceLink *d);
	virtual ~DeviceCommThread();

	virtual void run();

	void setDone(bool b)
	{
		FUNCTIONSETUP;
		fDone = b;
	}

protected:

	void close();
	
	void reset();

	/**
	 * Does the low-level opening of the device and handles the
	 * pilot-link library initialisation.
	 */
	bool open(const QString &device = QString::null);

protected slots:
	/**
	* Attempt to open the device. Called regularly to check
	* if the device exists (to handle USB-style devices).
	*/
	void openDevice();

	/**
	* Called when the device is opened *and* activity occurs on the
	* device. This indicates the beginning of a hotsync.
	*/
	void acceptDevice();
	
	/**
	* This slot fires whenever we've been trying to establish a hotsync with
	* the device for longer than a given amount of time.  When this slot is
	* fired, we will tear down the communications process and start over again.
	*/
	void workaroundUSB();

private:
	volatile bool fDone;

	KPilotDeviceLink *fHandle;
	inline KPilotDeviceLink *link()
	{
		if (fHandle)
		{
			return fHandle;
		}
		else
		{
			FUNCTIONSETUP;
			WARNINGKPILOT << "Link asked for, but either I'm "
				<< "done or I don't have a valid handle.  "
				<< "Shutting down comm thread." << endl;
			QThread::exit();
			return 0;
		}
	}

	/**
	 * Timers and Notifiers for detecting activity on the device.
	 */
	QTimer *fOpenTimer;
	QSocketNotifier *fSocketNotifier;
	bool fSocketNotifierActive;

	/** Timer used to check for a badly-connected Z31/72 */
	QTimer *fWorkaroundUSBTimer;
	
	/**
	 * Pilot-link library handles for the device once it's opened.
	 */
	int fPilotSocket;
	int fTempSocket;

	inline QString errorMessage(int e)
	{
		switch (e)
		{
		case ENOENT:
			return i18n(" The port does not exist.");
			break;
		case ENODEV:
			return i18n(" There is no such device.");
			break;
		case EPERM:
			return i18n(" You do not have permission to open the "
				"Pilot device.");
			break;
		default:
			return i18n(" Check Pilot path and permissions.");
		}
	}
	
	/**
	* Handle cases where we can't accept or open the device,
	* and data remains available on the pilot socket.
	*/
	int fAcceptedCount;

};


#endif