NXWidgets: cnxserver.cxx Source File

NXWidgets 1.19

cnxserver.cxx
Go to the documentation of this file.
1 /****************************************************************************
2 * NxWidgets/libnxwidgets/src/cnxserver.cxx
3 *
4 * Copyright (C) 2012, 2013, 2015-2016 Gregory Nutt. All rights reserved.
5 * Author: Gregory Nutt <gnutt@nuttx.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors
18 * me be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 ****************************************************************************/
35
36 /****************************************************************************
37 * Included Files
38 ****************************************************************************/
39
40 #include <nuttx/config.h>
41
42 #include <sys/types.h>
43 #include <sys/boardctl.h>
44 #include <sys/prctl.h>
45
46 #include <stdint.h>
47 #include <stdbool.h>
48 #include <unistd.h>
49 #include <cstdlib>
50 #include <cerrno>
51 #include <sched.h>
52 #include <pthread.h>
53 #include <debug.h>
54
55 #include <nuttx/board.h>
56
57 #ifdef CONFIG_VNCSERVER
58 # include <nuttx/video/vnc.h>
59 #endif
60
61 #include "nxconfig.hxx"
62 #include "singletons.hxx"
63 #include "cnxserver.hxx"
64
65 /****************************************************************************
66 * Static Data Members
67 ****************************************************************************/
68
69 using namespace NXWidgets;
70
71 uint8_t CNxServer::m_nServers; /**< The number of NX server instances */
72
73 /****************************************************************************
74 * Method Implementations
75 ****************************************************************************/
76
77 /**
78 * CNXServer constructor
79 */
80
81 CNxServer::CNxServer(void)
82 {
83 // Initialize server instance state data
84
85 m_hDevice = (FAR NX_DRIVERTYPE *)NULL; // LCD/Framebuffer device handle
86 m_hNxServer = (NXHANDLE)NULL; // NX server handle
87 m_connected = false; // True: Connected to the server
88 sem_init(&m_connsem, 0, 0); // Wait for server connection
89
90 // Increment the global count of NX servers. Normally there is only one
91 // but we don't want to preclude the case where there might be multiple
92 // displays, each with its own NX server instance
93
94 m_nServers++;
95
96 // Create miscellaneous singleton instances. Why is this done here?
97 // Because this needs to be done once before any widgets are created and we
98 // don't want to rely on static constructors.
99
100 instantiateSingletons();
101 }
102
103 /**
104 * CNXServer destructor
105 */
106
107 CNxServer::~CNxServer(void)
108 {
109 // Disconnect from the server
110
111 disconnect();
112
113 // Decrement the count of NX servers. When that count goes to zero,
114 // delete all of the fake static instances
115
116 if (--m_nServers == 0)
117 {
118 freeSingletons();
119 }
120 }
121
122 /**
123 * Connect to the NX Server
124 */
125
126 bool CNxServer::connect(void)
127 {
128 struct sched_param param;
129 pthread_t thread;
130 int ret;
131
132 // Set the client task priority
133
134 param.sched_priority = CONFIG_NXWIDGETS_CLIENTPRIO;
135 ret = sched_setparam(0, &param);
136 if (ret < 0)
137 {
138 gerr("ERROR: CNxServer::connect: sched_setparam failed: %d\n" , ret);
139 return false;
140 }
141
142 #ifdef CONFIG_NXWIDGET_SERVERINIT
143 // Start the NX server kernel thread
144
145 ginfo("CNxServer::connect: Starting NX server\n");
146 ret = boardctl(BOARDIOC_NX_START, 0);
147 if (ret < 0)
148 {
149 gerr("ERROR: CNxServer::connect: Failed to start the NX server: %d\n", errno);
150 return false;
151 }
152 #endif // CONFIG_NXWIDGET_SERVERINIT
153
154 // Connect to the server
155
156 m_hNxServer = nx_connect();
157 if (m_hNxServer)
158 {
159 pthread_attr_t attr;
160
161 #ifdef CONFIG_VNCSERVER
162 // Setup the VNC server to support keyboard/mouse inputs
163
164 ret = vnc_default_fbinitialize(0, m_hNxServer);
165 if (ret < 0)
166 {
167 gerr("ERROR: CNxServer::connect: vnc_default_fbinitialize failed: %d\n", ret);
168 m_running = false;
169 disconnect();
170 return false;
171 }
172 #endif
173
174 // Start a separate thread to listen for server events. This is probably
175 // the least efficient way to do this, but it makes this logic flow more
176 // smoothly.
177
178 (void)pthread_attr_init(&attr);
179 param.sched_priority = CONFIG_NXWIDGETS_LISTENERPRIO;
180 (void)pthread_attr_setschedparam(&attr, &param);
181 (void)pthread_attr_setstacksize(&attr, CONFIG_NXWIDGETS_LISTENERSTACK);
182
183 m_stop = false;
184 m_running = true;
185
186 ret = pthread_create(&thread, &attr, listener, (FAR void *)this);
187 if (ret != 0)
188 {
189 gerr("ERROR: NxServer::connect: pthread_create failed: %d\n", ret);
190 m_running = false;
191 disconnect();
192 return false;
193 }
194
195 // Detach from the thread
196
197 (void)pthread_detach(thread);
198
199 // Don't return until we are connected to the server
200
201 while (!m_connected && m_running)
202 {
203 // Wait for the listener thread to wake us up when we really
204 // are connected.
205
206 (void)sem_wait(&m_connsem);
207 }
208
209 // In the successful case, the listener is still running (m_running)
210 // and the server is connected (m_connected). Anything else is a failure.
211
212 if (!m_connected || !m_running)
213 {
214 disconnect();
215 return false;
216 }
217 }
218 else
219 {
220 gerr("ERROR: NxServer::connect: nx_connect failed: %d\n", errno);
221 return false;
222 }
223
224 return true;
225 }
226
227 /**
228 * Disconnect from the NX Server
229 */
230
231 void CNxServer::disconnect(void)
232 {
233 // Is the listener running?
234 // Hmm.. won't this hang is the listener is in a blocking call?
235
236 while (m_running)
237 {
238 // Yes.. stop the listener thread
239
240 m_stop = true;
241 while (m_running)
242 {
243 // Wait for the listener thread to stop
244
245 (void)sem_wait(&m_connsem);
246 }
247 }
248
249 // Disconnect from the server
250
251 if (m_hNxServer)
252 {
253 nx_disconnect(m_hNxServer);
254 m_hNxServer = NULL;
255 }
256 }
257
258 /**
259 * This is the entry point of a thread that listeners for and dispatches
260 * events from the NX server.
261 */
262
263 FAR void *CNxServer::listener(FAR void *arg)
264 {
265 // The argument must be the CNxServer instance
266
267 CNxServer *This = (CNxServer*)arg;
268
269 #if CONFIG_TASK_NAME_SIZE > 0
270 prctl(PR_SET_NAME, "CNxServer::listener", 0);
271 #endif
272
273 // Process events forever
274
275 while (!This->m_stop)
276 {
277 // Handle the next event. If we were configured blocking, then
278 // we will stay right here until the next event is received. Since
279 // we have dedicated a while thread to servicing events, it would
280 // be most natural to also select CONFIG_NX_BLOCKING -- if not, the
281 // following would be a tight infinite loop (unless we added addition
282 // logic with nx_eventnotify and sigwait to pace it).
283
284 int ret = nx_eventhandler(This->m_hNxServer);
285 if (ret < 0)
286 {
287 // An error occurred... assume that we have lost connection with
288 // the server.
289
290 gwarn("WARNING: Lost server connection: %d\n", errno);
291 break;
292 }
293
294 // If we received a message, we must be connected
295
296 if (!This->m_connected)
297 {
298 This->m_connected = true;
299 sem_post(&This->m_connsem);
300 ginfo("Connected\n");
301 }
302 }
303
304 // We fall out of the loop when either (1) the server has died or
305 // we have been requested to stop
306
307 This->m_running = false;
308 This->m_connected = false;
309 sem_post(&This->m_connsem);
310 return NULL;
311 }
312
NXWidgets::CNxServer::~CNxServer
~CNxServer(void)
Definition: cnxserver.cxx:107
singletons.hxx
NXWidgets::CNxServer::m_stop
volatile bool m_stop
Definition: cnxserver.hxx:87
NXWidgets::instantiateSingletons
void instantiateSingletons(void)
Definition: singletons.cxx:114
NXWidgets::CNxServer::disconnect
virtual void disconnect(void)
Definition: cnxserver.cxx:231
NXWidgets
Definition: cbgwindow.hxx:65
NXWidgets::CNxServer::connect
virtual bool connect(void)
Definition: cnxserver.cxx:126
NXWidgets::CNxServer::listener
static FAR void * listener(FAR void *arg)
Definition: cnxserver.cxx:263
NXWidgets::CNxServer::m_connsem
sem_t m_connsem
Definition: cnxserver.hxx:88
NXWidgets::CNxServer::m_nServers
static uint8_t m_nServers
Definition: cnxserver.hxx:89
nxconfig.hxx
NXWidgets::CNxServer::CNxServer
CNxServer(void)
Definition: cnxserver.cxx:81
NXWidgets::CNxServer::m_running
volatile bool m_running
Definition: cnxserver.hxx:85
NXWidgets::CNxServer::m_connected
volatile bool m_connected
Definition: cnxserver.hxx:86
cnxserver.hxx
NXWidgets::freeSingletons
void freeSingletons(void)
Definition: singletons.cxx:170
NXWidgets::CNxServer
Definition: cnxserver.hxx:80
NXWidgets::CNxServer::m_hNxServer
NXHANDLE m_hNxServer
Definition: cnxserver.hxx:84
NXWidgets::CNxServer::m_hDevice
FAR NX_DRIVERTYPE * m_hDevice
Definition: cnxserver.hxx:83