Warning: That file was not part of the compilation database. It may have many parsing errors.

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 tools applications 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 <qplatformdefs.h>
43
44#include "qvfbshmem.h"
45#include "qvfbhdr.h"
46#include "qlock_p.h"
47
48#include <QFile>
49#include <QTimer>
50
51#include <stdlib.h>
52#include <unistd.h>
53#include <sys/ipc.h>
54#include <sys/types.h>
55#include <sys/shm.h>
56#include <sys/stat.h>
57#include <fcntl.h>
58#include <errno.h>
59#include <math.h>
60
61QT_BEGIN_NAMESPACE
62
63#ifdef Q_WS_QWS
64#error qvfb must be compiled with the Qt for X11 package
65#endif
66
67// Get the name of the directory where Qt for Embedded Linux temporary data should
68// live.
69static QString qws_dataDir(int qws_display_id)
70{
71 static QString result;
72 if (!result.isEmpty())
73 return result;
74 result = QT_VFB_DATADIR(qws_display_id);
75 QByteArray dataDir = result.toLocal8Bit();
76
77#if defined(Q_OS_INTEGRITY)
78 /* ensure filesystem is ready before starting requests */
79 WaitForFileSystemInitialization();
80#endif
81
82 if (QT_MKDIR(dataDir, 0700)) {
83 if (errno != EEXIST) {
84 qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
85 }
86 }
87
88 QT_STATBUF buf;
89 if (QT_LSTAT(dataDir, &buf))
90 qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData());
91
92 if (!S_ISDIR(buf.st_mode))
93 qFatal("%s is not a directory", dataDir.constData());
94
95#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_QNX)
96 if (buf.st_uid != getuid())
97 qFatal("Qt for Embedded Linux data directory is not owned by user %uh", getuid());
98
99 if ((buf.st_mode & 0677) != 0600)
100 qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData());
101#endif
102
103 result.append(QLatin1Char('/'));
104 return result;
105}
106
107
108static QString displayPipe;
109static QString displayPiped;
110class DisplayLock
111{
112public:
113 DisplayLock() : qlock(0) {
114 if (QFile::exists(displayPiped)) {
115 qlock = new QLock(displayPipe, 'd', false);
116 qlock->lock(QLock::Read);
117 }
118 }
119 ~DisplayLock() {
120 if (qlock) {
121 qlock->unlock();
122 delete qlock;
123 qlock = 0;
124 }
125 }
126private:
127 QLock *qlock;
128};
129
130QShMemViewProtocol::QShMemViewProtocol(int displayid, const QSize &s,
131 int d, QObject *parent)
132 : QVFbViewProtocol(displayid, parent), hdr(0), dataCache(0), lockId(-1),
133 windowId(0)
134{
135 int w = s.width();
136 int h = s.height();
137
138 QString username = "unknown";
139 const char *logname = getenv("LOGNAME");
140 if ( logname )
141 username = logname;
142
143 qws_dataDir(displayid);
144
145 {
146 QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString("QtEmbedded-%1").arg(displayid);
147 QLock oldPipeLock(oldPipe, 'd', false);
148 if (oldPipeLock.isValid()) {
149 perror("QShMemViewProtocol::QShMemViewProtocol");
150 qFatal("Cannot create lock file as an old version of QVFb has "
151 "opened %s. Close other QVFb and try again",
152 oldPipe.toLatin1().constData());
153 }
154 }
155
156 displayPipe = QTE_PIPE_QVFB(displayid);
157
158 kh = new QVFbKeyPipeProtocol(displayid);
159 /* should really depend on receiving qt version, but how can
160 one tell? */
161 mh = new QVFbMousePipe(displayid);
162
163 QString mousePipe = mh->pipeName();
164
165 key_t key = ftok(mousePipe.toLatin1().constData(), 'b');
166
167 int bpl;
168 if (d < 8)
169 bpl = (w * d + 7) / 8;
170 else
171 bpl = w * ((d + 7) / 8);
172
173 displaySize = bpl * h;
174
175 unsigned char *data;
176 uint data_offset_value = sizeof(QVFbHeader);
177
178 int dataSize = bpl * h + data_offset_value;
179 shmId = shmget(key, dataSize, IPC_CREAT | 0600);
180 if (shmId != -1)
181 data = (unsigned char *)shmat(shmId, 0, 0);
182 else {
183 struct shmid_ds shm;
184 shmctl(shmId, IPC_RMID, &shm);
185 shmId = shmget(key, dataSize, IPC_CREAT | 0600);
186 if (shmId == -1) {
187 perror("QShMemViewProtocol::QShMemViewProtocol");
188 qFatal("Cannot get shared memory 0x%08x", key);
189 }
190 data = (unsigned char *)shmat(shmId, 0, 0);
191 }
192
193 if ((long)data == -1) {
194 delete kh;
195 delete mh;
196 perror("QShMemViewProtocol::QShMemViewProtocol");
197 qFatal("Cannot attach to shared memory %d",shmId);
198 }
199 dataCache = (unsigned char *)malloc(displaySize);
200 memset(dataCache, 0, displaySize);
201 memset(data+sizeof(QVFbHeader), 0, displaySize);
202
203 hdr = (QVFbHeader *)data;
204 hdr->width = w;
205 hdr->height = h;
206 hdr->depth = d;
207 hdr->linestep = bpl;
208 hdr->dataoffset = data_offset_value;
209 hdr->update = QRect();
210 hdr->dirty = 0;
211 hdr->numcols = 0;
212 hdr->viewerVersion = QT_VERSION;
213 hdr->brightness = 255;
214 hdr->windowId = 0;
215
216 displayPiped = displayPipe + 'd';
217
218
219 mRefreshTimer = new QTimer(this);
220 connect(mRefreshTimer, SIGNAL(timeout()), this, SLOT(flushChanges()));
221}
222
223QShMemViewProtocol::~QShMemViewProtocol()
224{
225 struct shmid_ds shm;
226 shmdt( (char*)hdr );
227 shmctl( shmId, IPC_RMID, &shm );
228 free(dataCache);
229 delete kh;
230 delete mh;
231}
232
233int QShMemViewProtocol::width() const
234{
235 return hdr->width;
236}
237
238int QShMemViewProtocol::height() const
239{
240 return hdr->height;
241}
242
243int QShMemViewProtocol::depth() const
244{
245 return hdr->depth;
246}
247
248int QShMemViewProtocol::linestep() const
249{
250 return hdr->linestep;
251}
252
253int QShMemViewProtocol::numcols() const
254{
255 return hdr->numcols;
256}
257
258QVector<QRgb> QShMemViewProtocol::clut() const
259{
260 QVector<QRgb> vector(hdr->numcols);
261 for (int i=0; i < hdr->numcols; ++i)
262 vector[i]=hdr->clut[i];
263
264 return vector;
265}
266
267unsigned char *QShMemViewProtocol::data() const
268{
269 return dataCache;
270 //return ((unsigned char *)hdr)+hdr->dataoffset;
271}
272
273int QShMemViewProtocol::brightness() const
274{
275 return hdr->brightness;
276}
277
278void QShMemViewProtocol::flushChanges()
279{
280 QRect r;
281 if (hdr->dirty) {
282 DisplayLock();
283
284 hdr->dirty = false;
285 r = hdr->update;
286 hdr->update = QRect();
287
288 if (hdr->windowId != windowId) {
289 windowId = hdr->windowId;
290 emit displayEmbedRequested(hdr->windowId);
291 } else if (!hdr->windowId) {
292 // copy the memory area, for now, be inefficient.
293 memcpy(dataCache, ((char *)hdr) + hdr->dataoffset, displaySize);
294 }
295 }
296 emit displayDataChanged(r);
297}
298
299void QShMemViewProtocol::setRate(int interval)
300{
301 if (interval > 0)
302 return mRefreshTimer->start(1000/interval);
303 else
304 mRefreshTimer->stop();
305}
306
307int QShMemViewProtocol::rate() const
308{
309 int i = mRefreshTimer->interval();
310 if (i > 0)
311 return 1000/i;
312 else
313 return 0;
314}
315
316QT_END_NAMESPACE
317

Warning: That file was not part of the compilation database. It may have many parsing errors.