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 | |
61 | QT_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. |
69 | static 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 | |
108 | static QString displayPipe; |
109 | static QString displayPiped; |
110 | class DisplayLock |
111 | { |
112 | public: |
113 | DisplayLock() : qlock(0) { |
114 | if (QFile::exists(displayPiped)) { |
115 | qlock = new QLock(displayPipe, |
116 | qlock->lock(QLock::Read); |
117 | } |
118 | } |
119 | ~DisplayLock() { |
120 | if (qlock) { |
121 | qlock->unlock(); |
122 | delete qlock; |
123 | qlock = 0; |
124 | } |
125 | } |
126 | private: |
127 | QLock *qlock; |
128 | }; |
129 | |
130 | QShMemViewProtocol::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, |
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(), |
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 + |
217 | |
218 | |
219 | mRefreshTimer = new QTimer(this); |
220 | connect(mRefreshTimer, SIGNAL(timeout()), this, SLOT(flushChanges())); |
221 | } |
222 | |
223 | QShMemViewProtocol::~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 | |
233 | int QShMemViewProtocol::width() const |
234 | { |
235 | return hdr->width; |
236 | } |
237 | |
238 | int QShMemViewProtocol::height() const |
239 | { |
240 | return hdr->height; |
241 | } |
242 | |
243 | int QShMemViewProtocol::depth() const |
244 | { |
245 | return hdr->depth; |
246 | } |
247 | |
248 | int QShMemViewProtocol::linestep() const |
249 | { |
250 | return hdr->linestep; |
251 | } |
252 | |
253 | int QShMemViewProtocol::numcols() const |
254 | { |
255 | return hdr->numcols; |
256 | } |
257 | |
258 | QVector<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 | |
267 | unsigned char *QShMemViewProtocol::data() const |
268 | { |
269 | return dataCache; |
270 | //return ((unsigned char *)hdr)+hdr->dataoffset; |
271 | } |
272 | |
273 | int QShMemViewProtocol::brightness() const |
274 | { |
275 | return hdr->brightness; |
276 | } |
277 | |
278 | void 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 | |
299 | void QShMemViewProtocol::setRate(int interval) |
300 | { |
301 | if (interval > 0) |
302 | return mRefreshTimer->start(1000/interval); |
303 | else |
304 | mRefreshTimer->stop(); |
305 | } |
306 | |
307 | int QShMemViewProtocol::rate() const |
308 | { |
309 | int i = mRefreshTimer->interval(); |
310 | if (i > 0) |
311 | return 1000/i; |
312 | else |
313 | return 0; |
314 | } |
315 | |
316 | QT_END_NAMESPACE |
317 |
Warning: That file was not part of the compilation database. It may have many parsing errors.