Qt 4.8
qostdevice.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qostdevice.h"
43 #include <e32base.h>
44 
45 #include "usbostcomm.h"
46 
47 class QOstDevicePrivate : public CActive
48 {
51 
52 public:
53  QOstDevicePrivate() : CActive(CActive::EPriorityStandard) {
55  }
57  Cancel();
58  }
59 
60  TInt& AoFlags() { return ((TInt*)&iStatus)[1]; }
61 
62 private:
63  void RunL();
64  void DoCancel();
65 
66 private:
68  TBuf8<4096> readBuf;
70  TBool inReadyRead;
71 };
72 
74  QIODevice(parent), d_ptr(new QOstDevicePrivate)
75 {
76  d_ptr->q_ptr = this;
77 }
78 
80 {
81  close();
82  delete d_ptr;
83 }
84 
85 bool QOstDevice::open(int ostProtocolId)
86 {
87  if (isOpen())
88  return false;
89 
90  Q_D(QOstDevice);
91  TInt err = d->ost.Connect();
92  if (!err) err = d->ost.Open();
93  const TVersion KRequiredVersion(1,1,0);
94  TVersion version = d->ost.Version();
95  if (version.iMajor < KRequiredVersion.iMajor ||
96  (version.iMajor == KRequiredVersion.iMajor && version.iMinor < KRequiredVersion.iMinor)) {
97  setErrorString("CODA version too old. At least version 4.0.18 (without TRK) is required.");
98  return false;
99  }
100 
101  if (!err) err = d->ost.RegisterProtocolID((TOstProtIds)ostProtocolId, EFalse);
102  if (!err) {
103  d->ost.ReadMessage(d->iStatus, d->readBuf);
104  d->SetActive();
106  }
107  return false;
108 }
109 
111 {
112  Q_Q(QOstDevice);
113  //qDebug("QOstDevice received %d bytes q=%x", readBuf.Size(), q);
114  if (iStatus == KErrNone) {
115  QByteArray data = QByteArray::fromRawData((const char*)readBuf.Ptr(), readBuf.Size());
116  dataBuf.append(data);
117 
118  readBuf.Zero();
119  ost.ReadMessage(iStatus, readBuf);
120  SetActive();
121 
122  if (!inReadyRead) {
123  inReadyRead = true;
124  emit q->readyRead();
125  inReadyRead = false;
126  }
127  } else {
128  q->setErrorString(QString("Error %1 from RUsbOstComm::ReadMessage()").arg(iStatus.Int()));
129  }
130  //qDebug("-QOstDevicePrivate RunL");
131 }
132 
134 {
135  ost.ReadCancel();
136 }
137 
139 {
140  Q_D(QOstDevice);
142  d->Cancel();
143  // RDbgTrcComm::Close isn't safe to call when not open, sigh
144  if (d->ost.Handle()) {
145  d->ost.Close();
146  }
147 }
148 
150 {
151  Q_D(QOstDevice);
152  if (d->dataBuf.length() == 0 && !d->IsActive())
153  return -1;
154  qint64 available = qMin(maxSize, (qint64)d->dataBuf.length());
155  memcpy(data, d->dataBuf.constData(), available);
156  d->dataBuf.remove(0, available);
157  return available;
158 }
159 
160 static const TInt KMaxOstPacketLen = 4096;
161 
163 {
164  Q_D(QOstDevice);
165  TPtrC8 ptr((const TUint8*)data, (TInt)maxSize);
166  while (ptr.Length()) {
167  TPtrC8 fragment = ptr.Left(qMin(ptr.Length(), KMaxOstPacketLen));
168  //qDebug("QOstDevice writing %d bytes", fragment.Length());
169  TRequestStatus stat;
170  d->ost.WriteMessage(stat, fragment);
171  User::WaitForRequest(stat);
172  if (stat.Int() != KErrNone) {
173  setErrorString(QString("Error %1 from RUsbOstComm::WriteMessage()").arg(stat.Int()));
174  return -1;
175  }
176  ptr.Set(ptr.Mid(fragment.Length()));
177  }
178  emit bytesWritten(maxSize); //TODO does it matter this is emitted synchronously?
179  //qDebug("QOstDevice wrote %d bytes", ptr.Size());
180  return maxSize;
181 }
182 
184 {
185  Q_D(const QOstDevice);
186  return d->dataBuf.length();
187 }
188 
190 {
191  Q_D(QOstDevice);
192  if (msecs >= 0) {
193  RTimer timer;
194  TInt err = timer.CreateLocal();
195  if (err) return false;
196  TRequestStatus timeoutStat;
197  timer.After(timeoutStat, msecs*1000);
198  User::WaitForRequest(timeoutStat, d->iStatus);
199  if (timeoutStat != KRequestPending) {
200  // Timed out
201  timer.Close();
202  return false;
203  } else {
204  // We got data, so cancel timer
205  timer.Cancel();
206  User::WaitForRequest(timeoutStat);
207  timer.Close();
208  // And drop through
209  }
210  } else {
211  // Just wait forever for data
212  User::WaitForRequest(d->iStatus);
213  }
214 
215  // If we get here we have data
216  TInt err = d->iStatus.Int();
217  d->AoFlags() &= ~3; // This is necessary to clean up the scheduler as you're not supposed to bypass it like this
218  TRAP_IGNORE(d->RunL());
219  return err == KErrNone;
220 }
double d
Definition: qnumeric_p.h:62
bool waitForReadyRead(int msecs)
Blocks until new data is available for reading and the readyRead() signal has been emitted...
Definition: qostdevice.cpp:189
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
QOstDevice * q_ptr
Definition: qostdevice.cpp:49
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
Definition: qiodevice.cpp:590
qint64 writeData(const char *data, qint64 maxSize)
Writes up to maxSize bytes from data to the device.
Definition: qostdevice.cpp:162
QByteArray & append(char c)
Appends the character ch to this byte array.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QOstDevicePrivate * d_ptr
Definition: qostdevice.h:72
void bytesWritten(qint64 bytes)
This signal is emitted every time a payload of data has been written to the device.
EventLoopTimerRef timer
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_D(Class)
Definition: qglobal.h:2482
#define Q_Q(Class)
Definition: qglobal.h:2483
bool isOpen() const
Returns true if the device is open; otherwise returns false.
Definition: qiodevice.cpp:530
int TOstProtIds
Definition: usbostcomm.h:50
QByteArray dataBuf
Definition: qostdevice.cpp:69
qint64 readData(char *data, qint64 maxSize)
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
Definition: qostdevice.cpp:149
#define emit
Definition: qobjectdefs.h:76
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
static const char * data(const QByteArray &arr)
RUsbOstComm ost
Definition: qostdevice.cpp:67
bool open(int ostProtocolId)
Definition: qostdevice.cpp:85
const T * ptr(const T &t)
__int64 qint64
Definition: qglobal.h:942
qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
Definition: qostdevice.cpp:183
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
void setErrorString(const QString &errorString)
Sets the human readable description of the last device error that occurred to str.
Definition: qiodevice.cpp:1660
TBuf8< 4096 > readBuf
Definition: qostdevice.cpp:68
virtual bool open(OpenMode mode)
Opens the device and sets its OpenMode to mode.
Definition: qiodevice.cpp:570
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
QOstDevice(QObject *parent=0)
Definition: qostdevice.cpp:73
static const TInt KMaxOstPacketLen
Definition: qostdevice.cpp:160
void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
Definition: qostdevice.cpp:138