|
2 | 2 | ``nxterm`` Display NuttShell (NSH) as NX Console
|
3 | 3 | ================================================
|
4 | 4 |
|
| 5 | +.. figure:: nxtermexample.png |
| 6 | + :align: center |
| 7 | + |
5 | 8 | This directory contains yet another version of the NuttShell (NSH). This version
|
6 | 9 | uses the NX console device defined in ``include/nuttx/nx/nxterm.h`` for output.
|
7 | 10 | the result is that the NSH input still come from the standard console input
|
@@ -45,3 +48,174 @@ The following configuration options can be selected to customize the test:
|
45 | 48 | - ``CONFIG_EXAMPLES_NXTERM_SERVERPRIO`` – The server priority. Default: ``120``.
|
46 | 49 | - ``CONFIG_EXAMPLES_NXTERM_LISTENERPRIO`` – The priority of the event listener
|
47 | 50 | thread. Default: ``80``.
|
| 51 | + |
| 52 | +Initialization |
| 53 | +============== |
| 54 | + |
| 55 | +NX Server |
| 56 | +--------- |
| 57 | + |
| 58 | +The NxTerm example initializes the NX Server through the following steps: |
| 59 | + |
| 60 | +* Calls ``boardctl(BOARDIOC_NX_START, 0)`` to start the NX server, then |
| 61 | +* Calls ``nx_connect()`` to connect to the NX server. |
| 62 | +* It also creates a separate thread at entry ``nxterm_listener()`` to listen for |
| 63 | + NX server events. |
| 64 | + |
| 65 | +Window Creation |
| 66 | +--------------- |
| 67 | + |
| 68 | +The Nxterm Example then initializes the Windows: |
| 69 | + |
| 70 | +* Calls ``nxtk_openwindow()`` to create a bordered window, |
| 71 | +* Calls ``nxtk_setposition()`` and ``nxtk_setsize()`` to position the window in |
| 72 | + the display, |
| 73 | +* Calls ``nxtk_opentoolbar()`` to create a toolbar sub-window on the main window |
| 74 | + (This toolbar window is not used by the example, it is just for illustration). |
| 75 | + |
| 76 | +A more practical use case for, say, a handheld device with a single NxTerm display |
| 77 | +would be to use the background window. The background is a window like any other |
| 78 | +with these special properties: It cannot be moved; it is always positioned at (0,0). |
| 79 | +It cannot be resized; it is always the full size of the display. And it cannot be |
| 80 | +raised, it is always the lowest windows in the z-axis. |
| 81 | + |
| 82 | +NxTerm Driver |
| 83 | +------------- |
| 84 | + |
| 85 | +And binds the Nxterm driver to the permit drawing in the window. This is done when it: |
| 86 | + |
| 87 | +* Calls ``boardctl(BOARDIOC_NXTERM, (uintptr_t)&nxcreate)`` |
| 88 | + |
| 89 | +Console Task |
| 90 | +------------ |
| 91 | + |
| 92 | +Finally, it sets up the NxTerm and starts the console task: |
| 93 | + |
| 94 | +* Opens the NxTerm driver, |
| 95 | +* It then re-directs stdout and stderr to the NxTerm driver. This will cause all |
| 96 | + standard output to be rendered into the main windows, and |
| 97 | +* It then starts a separate console daemon that inherits the re-directed output |
| 98 | + and exits. |
| 99 | + |
| 100 | +Character I/O |
| 101 | +============= |
| 102 | + |
| 103 | +Normal Keyboard Input |
| 104 | +--------------------- |
| 105 | + |
| 106 | +Keyboard and mouse inputs are received by the application through window callbacks, |
| 107 | +just like with the Xorg X server. Some listener needs to inject the keyboard input |
| 108 | +via ``nx_kbdin()`` (``libs/libnx/nx_kbdin.c``) which sends a message containing the |
| 109 | +keyboard input to the NX server. The NX server will forward that keyboard input to |
| 110 | +the window that has focus. |
| 111 | + |
| 112 | +The Window application listens for NX server events by calling ``nx_eventhandler()`` |
| 113 | +(``libs/libnx/nx_eventhandler``) on another listener thread. If the window has |
| 114 | +focus when the key press is entered, ``nx_eventhandler()`` will forward the key |
| 115 | +press information to the registered window event handler. |
| 116 | + |
| 117 | +In ``apps/examples/nxterm``, ``nxterm_listener.c`` is the thread that drives |
| 118 | +``nx_eventhandler()``. The window NX keyboard callback is the function ``nxwndo_kbdin()`` |
| 119 | +in ``nxterm_wndo.c``. That callback function is just a stub that writes the keyboard |
| 120 | +data to stdout. It is a stub because keyboard input is not received from the NxTerm |
| 121 | +in this example. |
| 122 | + |
| 123 | +The apps/examples/nxterm/ Kludge |
| 124 | +-------------------------------- |
| 125 | + |
| 126 | +``apps/examples/nxterm`` does not do things in the normal way. NSH does not receive |
| 127 | +keyboard input from NX; it gets keyboard input directly from the default stdin which |
| 128 | +is probably not a keyboard at all but more likely the host PC serial console. This is |
| 129 | +okay because only a single window is used and that example does not need the help of |
| 130 | +NX to select the window that has focus. |
| 131 | + |
| 132 | +Re-direction of stdout and stderr |
| 133 | +--------------------------------- |
| 134 | + |
| 135 | +stdin in and stderr are re-directed to the NxTerm character driver in ``nxterm_main.c`` |
| 136 | +just before starting the console task. That logic looks like this: |
| 137 | + |
| 138 | +.. code-block:: C |
| 139 | +
|
| 140 | + /* Now re-direct stdout and stderr so that they use the NX console driver. |
| 141 | + * Note that stdin is retained (file descriptor 0, probably the serial |
| 142 | + * console). |
| 143 | + */ |
| 144 | +
|
| 145 | + printf("nxterm_main: Starting the console task\n"); |
| 146 | +
|
| 147 | + fflush(stdout); |
| 148 | + fflush(stderr); |
| 149 | +
|
| 150 | + fclose(stdout); |
| 151 | + fclose(stderr); |
| 152 | +
|
| 153 | + dup2(fd, 1); |
| 154 | + dup2(fd, 2); |
| 155 | +
|
| 156 | +Note that stdin is not re-directed in this example! This means that keyboard |
| 157 | +input does not come from the NxTerm driver but, rather, from whatever input |
| 158 | +device was previously configured for stdin, often a serial console. |
| 159 | + |
| 160 | +There is a configuration option that determines if NxTerm receives keyboard |
| 161 | +input or not: ``CONFIG_NXTERM_NXKBDIN``, For this NxTerm example, that option can be disabled. |
| 162 | + |
| 163 | +What Is BOARDIOC_NXTERM_IOCTL and Where Is It Used? |
| 164 | +--------------------------------------------------- |
| 165 | + |
| 166 | +The ``boardctl()`` command ``BOARDIOC_NXTERM_IOCTL`` allows an application to |
| 167 | +inject keyboard data into NX for forwarding to the window with focus. |
| 168 | +In ``apps/examples/nxterm``, the ``BOARDIOC_NXTERM_IOCTL`` is only called for the |
| 169 | +case of a redraw event. A redraw event may happen when a window above the current |
| 170 | +window is moved and the text is exposed. |
| 171 | + |
| 172 | +If you use only a single window for the NxTerm example, then that window will |
| 173 | +always have focus. It will always have focus and will never be redrawn and the |
| 174 | +``BOARDIOC_NXTERM_IOCTL`` will never be used (Unless, perhaps, you choose to implement |
| 175 | +pop-up error messages or menus on top of the NxTerm window). |
| 176 | + |
| 177 | +Redraw callbacks will not be received even in a multi-window configuration if you |
| 178 | +use per-window frame buffers, either. In that case, the system will automatically |
| 179 | +redraw windows as needed using the per-window frame buffer shadow memory. This is |
| 180 | +controlled by the option ``CONFIG_NX_RAMBACKED``. This option is recommended for |
| 181 | +performance reasons if you have sufficient memory to support it. |
| 182 | + |
| 183 | +Character Data Flow: Keyboard to Display |
| 184 | +========================================= |
| 185 | + |
| 186 | +Character Data Flow in apps/examples/nxterm |
| 187 | +------------------------------------------- |
| 188 | + |
| 189 | +* Character input driver receives input |
| 190 | +* NSH receives input on stdin and processes it (stdin is not redirected) |
| 191 | +* Data is output to stdout (redirected to the NxTerm driver) |
| 192 | + |
| 193 | +In this simple, single-window case, ``BOARDIOC_NXTERM_IOCTL`` will never be used. |
| 194 | + |
| 195 | +Character Data Flow in the Generic Window Case |
| 196 | +---------------------------------------------- |
| 197 | + |
| 198 | +See, for an example, ``apps/graphics/nxwm/src/cnxterm.cxx``. In this case, the |
| 199 | +behavior will change, depending on the selection of ``CONFIG_NXTERM_NXKBDIN``: |
| 200 | +If ``CONFIG_NXTERM_NXKBDIN`` is not selected, then the behavior will be similar |
| 201 | +to ``apps/examples/nxterm``; stdin will not be redirected an keyboard input will |
| 202 | +come directly from the the system console. |
| 203 | + |
| 204 | +But is ``CONFIG_NXTERM_NXKBDIN`` is select, NSH's stdin will be re-redirected to |
| 205 | +the to the NxTerm character driver. Keyboard input will arrive on stdin from the |
| 206 | +NxTerm driver rather than from the system console. The following sequence describes |
| 207 | +the keyboard input in this latter case: |
| 208 | + |
| 209 | +* Character input driver receives input, |
| 210 | +* Some keyboard listener thread receives input and injects it into NX via |
| 211 | + a call to ``nx_kbdin()``, |
| 212 | +* NX sends an event to the registered ``kbdin()`` method of the window that has |
| 213 | + focus, providing the keyboard input to the window application. In this case, |
| 214 | + the window application of interest is the window bound to the NxTerm character |
| 215 | + driver by the application. The ``kbin()`` callback provides the focused keyboard |
| 216 | + input to the NxTerm driver via ``boardctl(BOARDIOC_NXTERM_IOCTL, (uintptr_t)&iocargs)``, |
| 217 | +* The NxTerm character driver receives keyboard data, buffers it, and provides |
| 218 | + that keyboard input for the next read operation, |
| 219 | +* NSH receives input on stdin which was re-directed to the NxTerm character driver. |
| 220 | + NSH processes the input, and |
| 221 | +* ,NSH outputs data to stdout which was re-directed to the NxTerm character driver. |
0 commit comments