Mercurial > hg > Members > kono > Cerium
annotate old/framebuffer/cp_vt.c @ 982:b29547a5b85b
avoid WAIT in virtual console
author | root@henri.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Fri, 01 Oct 2010 00:26:02 +0900 |
parents | e0c254a9a865 |
children |
rev | line source |
---|---|
979 | 1 // cp_vt.c |
2 // | |
3 // Copyright (c) 2006, Mike Acton <macton@cellperformance.com> | |
4 // | |
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | |
6 // documentation files (the "Software"), to deal in the Software without restriction, including without | |
7 // limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
8 // the Software, and to permit persons to whom the Software is furnished to do so, subject to the following | |
9 // conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in all copies or substantial | |
12 // portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT | |
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO | |
16 // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
17 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE | |
18 // OR OTHER DEALINGS IN THE SOFTWARE. | |
19 | |
20 // NOTES: | |
21 // From http://www.linuxjournal.com/article/2597 | |
22 // | |
23 // "Console ttys are used when the keyboard and monitor are directly connected to the system without running | |
24 // the X Window System. Since you can have several virtual consoles, the devices are tty0 through tty63. In | |
25 // theory you can have 64 virtual consoles, but most people use only a few. The device /dev/console is | |
26 // identical to tty0 and is needed for historical reasons. If your system lets you log in on consoles 1 | |
27 // through 6, then when you run X Windows System, X uses console 7, so you'll need /dev/tty1 through /dev/ | |
28 // tty7 on your system. I recommend having files up through /dev/tty12. For more information on using | |
29 // virtual consoles, see the article Keyboards, Consoles and VT Cruising by John Fisk in the November 1996 | |
30 // issue of Linux Journal" | |
31 | |
32 #include <stdio.h> | |
33 #include <stdint.h> | |
34 #include <fcntl.h> | |
35 #include <unistd.h> | |
36 #include <sys/ioctl.h> | |
37 #include <linux/vt.h> | |
38 #include <linux/kd.h> | |
39 #include "cp_vt.h" | |
40 | |
41 | |
42 static inline const char* | |
43 select_error_str( int existing_error, const char* const existing_error_str, int new_error, const char* const new_error_str ) | |
44 { | |
45 // Only report the first error found - any error that follows is probably just a cascading effect. | |
46 const char* error_str = (char*)( (~(intptr_t)existing_error & (intptr_t)new_error & (intptr_t)new_error_str) | |
47 | ((intptr_t)existing_error & (intptr_t)existing_error_str) ); | |
48 | |
49 return (error_str); | |
50 } | |
51 | |
52 | |
53 int | |
54 cp_vt_open_graphics(cp_vt* restrict vt) | |
55 { | |
56 const char* error_str = NULL; | |
57 int error = 0; | |
58 | |
59 // Open the current tty | |
60 | |
61 // From http://tldp.org/HOWTO/Text-Terminal-HOWTO-6.html#ss6.3 | |
62 // (An excellent overview by David S. Lawyer) | |
63 // | |
64 // "In Linux the PC monitor is usually called the console and has several device special files associated | |
65 // with it: vc/0 (tty0), vc/1 (tty1), vc/2 (tty2), etc. When you log in you are on vc/1. To go to vc/2 | |
66 // (on the same screen) press down the 2 keys Alt(left)-F3. For vc/3 use Left Alt-F3, etc. These (vc/1, | |
67 // vc/2, vc/3, etc.) are called "virtual terminals". vc/0 (tty0) is just an alias for the current virtual | |
68 // terminal and it's where messages from the system are sent. Thus messages from the system will be seen | |
69 // on the console (monitor) regardless of which virtual terminal it is displaying." | |
70 | |
71 const int cur_tty = open( "/dev/tty0", O_RDWR ); | |
72 const int open_cur_tty_error = (cur_tty >> ((sizeof(int)*8)-1)); | |
73 const char* open_cur_tty_error_str = "Could not open /dev/tty0. Check permissions."; | |
74 | |
75 error_str = select_error_str( error, error_str, open_cur_tty_error, open_cur_tty_error_str ); | |
76 error = error | open_cur_tty_error; | |
77 | |
78 // From: http://www.linuxjournal.com/article/2783 | |
79 // (A little out of date, but a nice primer.) | |
80 // | |
81 // "VT_GETSTATE returns the state of all VT's in the kernel in the structure: | |
82 // | |
83 // struct vt_stat { | |
84 // ushort v_active; | |
85 // ushort v_signal; | |
86 // ushort v_state; | |
87 // }; | |
88 // | |
89 // v_active the currently active VT | |
90 // v_state mask of all the opened VT's | |
91 // | |
92 // v_active holds the number of the active VT (starting from 1), while v_state | |
93 // holds a mask where there is a 1 for each VT that has been opened by some process. | |
94 // Note that VT 0 is always opened in this scenario, since it refers to the current VT. | |
95 // | |
96 // Bugs: | |
97 // The v_signal member is unsupported." | |
98 | |
99 struct vt_stat vts; | |
100 | |
101 const int get_state_error = ioctl( cur_tty, VT_GETSTATE, &vts ); | |
102 const char* get_state_error_str = "VT_GETSTATE failed on /dev/tty0"; | |
103 | |
104 error_str = select_error_str( error, error_str, get_state_error, get_state_error_str ); | |
105 error = error | get_state_error; | |
106 | |
107 vt->prev_tty_ndx = vts.v_active; | |
108 | |
109 // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt | |
110 // (Close enough to Linux and a pretty good source of documentation.) | |
111 // | |
112 // "VT_OPENQRY | |
113 // This call is used to find an available VT. The argu- | |
114 // ment to the ioctl is a pointer to an integer. The integer | |
115 // will be filled in with the number of the first avail- | |
116 // able VT that no other process has open (and hence, is | |
117 // available to be opened). If there are no available | |
118 // VTs, then -1 will be filled in." | |
119 | |
120 const int open_query_error = ioctl( cur_tty, VT_OPENQRY, &vt->tty_ndx); | |
121 const char* open_query_error_str = "No open ttys available"; | |
122 | |
123 error_str = select_error_str( error, error_str, open_query_error, open_query_error_str ); | |
124 error = error | open_query_error; | |
125 | |
126 const int close_cur_tty_error = close( cur_tty ); | |
127 const char* close_cur_tty_error_str = "Could not close parent tty"; | |
128 | |
129 error_str = select_error_str( error, error_str, close_cur_tty_error, close_cur_tty_error_str ); | |
130 error = error | close_cur_tty_error; | |
131 | |
132 char tty_file_name[11]; | |
133 | |
134 (void)snprintf( tty_file_name, 11, "/dev/tty%d", vt->tty_ndx ); | |
135 | |
136 const int tty = open( tty_file_name, O_RDWR ); | |
137 const int open_tty_error = (cur_tty >> ((sizeof(int)*8)-1)); | |
138 const char* open_tty_error_str = "Could not open tty"; | |
139 | |
140 error_str = select_error_str( error, error_str, open_tty_error, open_tty_error_str ); | |
141 error = error | open_tty_error; | |
142 | |
143 vt->tty = tty; | |
144 | |
145 // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt | |
146 // (Close enough to Linux and a pretty good source of documentation.) | |
147 // | |
148 // "VT_ACTIVATE | |
149 // This call has the effect of making the VT specified in | |
150 // the argument the active VT. The VT manager will cause | |
151 // a switch to occur in the same manner as if a hotkey had | |
152 // initiated the switch. If the specified VT is not open | |
153 // or does not exist the call will fail and errno will be | |
154 // set to ENXIO." | |
155 // | |
156 // "VT_WAITACTIVE | |
157 // If the specified VT is already active, this call | |
158 // returns immediately. Otherwise, it will sleep until | |
159 // the specified VT becomes active, at which point it will | |
160 // return." | |
161 | |
162 | |
163 const int activate_tty_error = ioctl( vt->tty, VT_ACTIVATE, vt->tty_ndx ); | |
164 const char* activate_tty_error_str = "Could not activate tty"; | |
165 | |
166 error_str = select_error_str( error, error_str, activate_tty_error, activate_tty_error_str ); | |
167 error = error | activate_tty_error; | |
982
b29547a5b85b
avoid WAIT in virtual console
root@henri.cr.ie.u-ryukyu.ac.jp
parents:
979
diff
changeset
|
168 #if 0 |
979 | 169 const int waitactive_tty_error = ioctl( vt->tty, VT_WAITACTIVE, vt->tty_ndx ); |
170 const char* waitactive_tty_error_str = "Could not switch to tty"; | |
171 | |
172 error_str = select_error_str( error, error_str, waitactive_tty_error, waitactive_tty_error_str ); | |
173 error = error | waitactive_tty_error; | |
982
b29547a5b85b
avoid WAIT in virtual console
root@henri.cr.ie.u-ryukyu.ac.jp
parents:
979
diff
changeset
|
174 #endif |
979 | 175 |
176 // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt | |
177 // (Close enough to Linux and a pretty good source of documentation.) | |
178 // | |
179 // "KDSETMODE | |
180 // This call is used to set the text/graphics mode to the VT. | |
181 // | |
182 // KD_TEXT indicates that console text will be displayed on the screen | |
183 // with this VT. Normally KD_TEXT is combined with VT_AUTO mode for | |
184 // text console terminals, so that the console text display will | |
185 // automatically be saved and restored on the hot key screen switches. | |
186 // | |
187 // KD_GRAPHICS indicates that the user/application, usually Xserver, | |
188 // will have direct control of the display for this VT in graphics | |
189 // mode. Normally KD_GRAPHICS is combined with VT_PROCESS mode for | |
190 // this VT indicating direct control of the display in graphics mode. | |
191 // In this mode, all writes to this VT using the write system call are | |
192 // ignored, and the user is responsible for saving and restoring the | |
193 // display on the hot key screen switches." | |
194 | |
195 // Save the current VT mode. This is most likely KD_TEXT. | |
196 | |
197 const int kdgetmode_error = ioctl( vt->tty, KDGETMODE, &vt->prev_kdmode ); | |
198 const char* kdgetmode_error_str = "Could not get mode for tty"; | |
199 | |
200 error_str = select_error_str( error, error_str, kdgetmode_error, kdgetmode_error_str ); | |
201 error = error | kdgetmode_error; | |
202 | |
203 // Set VT to GRAPHICS (user draw) mode | |
204 | |
205 const int kdsetmode_graphics_error = ioctl( vt->tty, KDSETMODE, KD_GRAPHICS ); | |
206 const char* kdsetmode_graphics_error_str = "Could not set graphics mode for tty"; | |
207 | |
208 error_str = select_error_str( error, error_str, kdsetmode_graphics_error, kdsetmode_graphics_error_str ); | |
209 error = error | kdsetmode_graphics_error; | |
210 | |
211 // | |
212 // Not bothering with VT_PROCESS, VT_AUTO is fine for our purposes. | |
213 // | |
214 | |
215 // If vt blanking is active, for example when running this program from a remote terminal, | |
216 // setting KD_GRAPHICS will not disable the blanking. Reset to KD_TEXT from KD_GRAPHICS will | |
217 // force disable blanking. Then return to KD_GRAPHICS for drawing. | |
218 // | |
219 // Note: KD_TEXT (default) to KD_TEXT will do nothing, so blanking will not be disable unless | |
220 // the mode is changing. i.e. the initial set to KD_GRAPHICS above is useful. | |
221 | |
222 const int kdsetmode_text_error = ioctl( vt->tty, KDSETMODE, KD_TEXT ); | |
223 const char* kdsetmode_text_error_str = "Could not set text mode for tty"; | |
224 | |
225 error_str = select_error_str( error, error_str, kdsetmode_text_error, kdsetmode_text_error_str ); | |
226 error = error | kdsetmode_text_error; | |
227 | |
228 const int kdsetmode_graphics_reset_error = ioctl( vt->tty, KDSETMODE, KD_GRAPHICS ); | |
229 const char* kdsetmode_graphics_reset_error_str = "Could not reset graphics mode for tty"; | |
230 | |
231 error_str = select_error_str( error, error_str, kdsetmode_graphics_reset_error, kdsetmode_graphics_reset_error_str ); | |
232 error = error | kdsetmode_graphics_reset_error; | |
233 | |
234 if ( error == -1 ) | |
235 { | |
236 printf("ERROR: vt_graphics_open: %s\n",error_str); | |
237 return (-1); | |
238 } | |
239 | |
240 return (0); | |
241 } | |
242 | |
243 int | |
244 cp_vt_close(cp_vt* restrict vt) | |
245 { | |
246 const char* error_str = NULL; | |
247 int error = 0; | |
248 | |
249 // Reset previous mode on tty (likely KD_TEXT) | |
250 | |
251 const int kdsetmode_error = ioctl( vt->tty, KDSETMODE, vt->prev_kdmode ); | |
252 const char* kdsetmode_error_str = "Could not reset previous mode for tty"; | |
253 | |
254 error_str = select_error_str( error, error_str, kdsetmode_error, kdsetmode_error_str ); | |
255 error = error | kdsetmode_error; | |
256 | |
257 // Restore previous tty | |
258 | |
259 const int activate_tty_error = ioctl( vt->tty, VT_ACTIVATE, vt->prev_tty_ndx ); | |
260 const char* activate_tty_error_str = "Could not activate previous tty"; | |
261 | |
262 error_str = select_error_str( error, error_str, activate_tty_error, activate_tty_error_str ); | |
263 error = error | activate_tty_error; | |
264 | |
265 const int waitactive_tty_error = ioctl( vt->tty, VT_WAITACTIVE, vt->prev_tty_ndx ); | |
266 const char* waitactive_tty_error_str = "Could not switch to previous tty"; | |
267 | |
268 error_str = select_error_str( error, error_str, waitactive_tty_error, waitactive_tty_error_str ); | |
269 error = error | waitactive_tty_error; | |
270 | |
271 // Close tty | |
272 | |
273 const int close_tty_error = close( vt->tty ); | |
274 const char* close_tty_error_str = "Could not close tty"; | |
275 | |
276 error_str = select_error_str( error, error_str, close_tty_error, close_tty_error_str ); | |
277 error = error | close_tty_error; | |
278 | |
279 if ( error == -1 ) | |
280 { | |
281 printf("ERROR: vt_close: %s\n",error_str); | |
282 return (-1); | |
283 } | |
284 | |
285 return (0); | |
286 } |