diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore_fb/ecore_fb_vt.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore_fb/ecore_fb_vt.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_fb/ecore_fb_vt.c b/libraries/ecore/src/lib/ecore_fb/ecore_fb_vt.c new file mode 100644 index 0000000..09e3f37 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_fb/ecore_fb_vt.c | |||
@@ -0,0 +1,322 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #include "Ecore_Fb.h" | ||
6 | #include "ecore_fb_private.h" | ||
7 | |||
8 | static int _ecore_fb_vt_do_switch = 0; | ||
9 | |||
10 | static int _ecore_fb_vt_tty0_fd = -1; | ||
11 | static int _ecore_fb_vt_tty_fd = -1; | ||
12 | static int _ecore_fb_vt_current_vt = 0; | ||
13 | static int _ecore_fb_vt_prev_vt = 0; | ||
14 | |||
15 | static struct termios _ecore_fb_tty_prev_tio_mode; | ||
16 | static struct vt_mode _ecore_fb_vt_prev_mode; | ||
17 | |||
18 | static Eina_Bool _ecore_fb_signal_usr_handler(void *data, int type, void *ev); | ||
19 | static Ecore_Event_Handler *_ecore_fb_user_handler = NULL; | ||
20 | static int _ecore_fb_tty_prev_mode = 0; | ||
21 | static int _ecore_fb_tty_prev_kd_mode = 0; | ||
22 | |||
23 | /* callbacks for an attach/release of a vt */ | ||
24 | static void (*_ecore_fb_func_fb_lost) (void *data) = NULL; | ||
25 | static void *_ecore_fb_func_fb_lost_data = NULL; | ||
26 | static void (*_ecore_fb_func_fb_gain) (void *data) = NULL; | ||
27 | static void *_ecore_fb_func_fb_gain_data = NULL; | ||
28 | |||
29 | /* FIXME what is the filter for? */ | ||
30 | static Ecore_Event_Filter *_ecore_fb_filter_handler = NULL; | ||
31 | |||
32 | /* prototypes */ | ||
33 | /* XXX: unused | ||
34 | static void _ecore_fb_vt_switch(int vt); | ||
35 | static void *_ecore_fb_event_filter_start(void *data); | ||
36 | static Eina_Bool _ecore_fb_event_filter_filter(void *data, void *loop_data, int type, void *event); | ||
37 | static void _ecore_fb_event_filter_end(void *data, void *loop_data); | ||
38 | */ | ||
39 | |||
40 | static Eina_Bool | ||
41 | _ecore_fb_signal_usr_handler(void *data __UNUSED__, int type __UNUSED__, void *ev) | ||
42 | { | ||
43 | Ecore_Event_Signal_User *e; | ||
44 | |||
45 | e = (Ecore_Event_Signal_User *)ev; | ||
46 | if (e->number == 1) | ||
47 | { | ||
48 | /* release vt */ | ||
49 | if (_ecore_fb_func_fb_lost) _ecore_fb_func_fb_lost(_ecore_fb_func_fb_lost_data); | ||
50 | /* TODO stop listening from the devices? let the callback do it? */ | ||
51 | ioctl(_ecore_fb_vt_tty_fd, VT_RELDISP, 1); | ||
52 | } | ||
53 | else if (e->number == 2) | ||
54 | { | ||
55 | /* attach vt */ | ||
56 | if (_ecore_fb_func_fb_gain) _ecore_fb_func_fb_gain(_ecore_fb_func_fb_gain_data); | ||
57 | /* TODO reattach all devices */ | ||
58 | } | ||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | /* XXX: unused | ||
63 | static void | ||
64 | _ecore_fb_vt_switch(int vt) | ||
65 | { | ||
66 | vt++; | ||
67 | if (_ecore_fb_vt_tty_fd != 0) | ||
68 | { | ||
69 | if (vt != _ecore_fb_vt_current_vt) | ||
70 | { | ||
71 | tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); | ||
72 | ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); | ||
73 | ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); | ||
74 | } | ||
75 | } | ||
76 | ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, vt); | ||
77 | } | ||
78 | */ | ||
79 | |||
80 | static int | ||
81 | _ecore_fb_vt_setup(void) | ||
82 | { | ||
83 | char buf[64]; | ||
84 | // XXX: unused | ||
85 | // struct termios tio; | ||
86 | struct vt_mode new_vtmode; | ||
87 | |||
88 | if (_ecore_fb_vt_current_vt != _ecore_fb_vt_prev_vt) | ||
89 | { | ||
90 | snprintf(buf, sizeof(buf), "/dev/tty%i", _ecore_fb_vt_current_vt); | ||
91 | if ((_ecore_fb_vt_tty_fd = open(buf, O_RDWR)) < 0) | ||
92 | { | ||
93 | printf("[ecore_fb:vt_setup] can't open tty %d\n", _ecore_fb_vt_current_vt); | ||
94 | return 0; | ||
95 | } | ||
96 | close(_ecore_fb_vt_tty0_fd); | ||
97 | _ecore_fb_vt_tty0_fd = -1; | ||
98 | /* FIXME detach the process from current tty ? */ | ||
99 | } | ||
100 | else | ||
101 | _ecore_fb_vt_tty_fd = _ecore_fb_vt_tty0_fd; | ||
102 | /* for backup */ | ||
103 | tcgetattr(_ecore_fb_vt_tty_fd, &_ecore_fb_tty_prev_tio_mode); | ||
104 | ioctl(_ecore_fb_vt_tty_fd, KDGETMODE, &_ecore_fb_tty_prev_kd_mode); | ||
105 | ioctl(_ecore_fb_vt_tty_fd, VT_GETMODE, &_ecore_fb_vt_prev_mode); | ||
106 | |||
107 | if (ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) | ||
108 | { | ||
109 | perror("[ecore_fb:vt_setup] can't set the mode to KD_GRAPHICS"); | ||
110 | close(_ecore_fb_vt_tty_fd); | ||
111 | _ecore_fb_vt_tty_fd = -1; | ||
112 | return 0; | ||
113 | } | ||
114 | ioctl(_ecore_fb_vt_tty_fd, KDGKBMODE, &_ecore_fb_tty_prev_mode); | ||
115 | |||
116 | /* support of switching */ | ||
117 | new_vtmode.mode = VT_PROCESS; | ||
118 | new_vtmode.waitv = 0; | ||
119 | new_vtmode.relsig = SIGUSR1; | ||
120 | new_vtmode.acqsig = SIGUSR2; | ||
121 | if (ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &new_vtmode) < 0) | ||
122 | { | ||
123 | perror("[ecore_fb:vt_setup] can't set the tty mode"); | ||
124 | close(_ecore_fb_vt_tty_fd); | ||
125 | _ecore_fb_vt_tty_fd = -1; | ||
126 | return 0; | ||
127 | } | ||
128 | /* register signal handlers when alloc/detach of vt */ | ||
129 | _ecore_fb_user_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, | ||
130 | _ecore_fb_signal_usr_handler, | ||
131 | NULL); | ||
132 | /* What does this do? */ | ||
133 | /* | ||
134 | _ecore_fb_filter_handler = ecore_event_filter_add(_ecore_fb_event_filter_start, _ecore_fb_event_filter_filter, _ecore_fb_event_filter_end, NULL); | ||
135 | */ | ||
136 | |||
137 | usleep(40000); | ||
138 | if (ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, _ecore_fb_vt_current_vt) < 0) | ||
139 | { | ||
140 | perror("[ecore_fb:vt_setup] error on VT_ACTIVATE"); | ||
141 | close(_ecore_fb_vt_tty_fd); | ||
142 | _ecore_fb_vt_tty_fd = -1; | ||
143 | return 0; | ||
144 | } | ||
145 | if(ioctl(_ecore_fb_vt_tty_fd, VT_WAITACTIVE, _ecore_fb_vt_current_vt) < 0) | ||
146 | { | ||
147 | perror("[ecore_fb:vt_setup] error on VT_WAITACTIVE"); | ||
148 | close(_ecore_fb_vt_tty_fd); | ||
149 | _ecore_fb_vt_tty_fd = -1; | ||
150 | return 0; | ||
151 | } | ||
152 | /* FIXME assign the fb to the tty in case isn't setup */ | ||
153 | return 1; | ||
154 | } | ||
155 | |||
156 | int | ||
157 | ecore_fb_vt_init(void) | ||
158 | { | ||
159 | struct vt_stat vtstat; | ||
160 | |||
161 | /* as root you can allocate another tty */ | ||
162 | if (!geteuid()) | ||
163 | _ecore_fb_vt_do_switch = 1; | ||
164 | if ((_ecore_fb_vt_tty0_fd = open("/dev/tty0", O_RDONLY)) < 0) | ||
165 | { | ||
166 | printf("[ecore_fb:init] can't open /dev/tty0\n"); | ||
167 | return 0; | ||
168 | } | ||
169 | /* query current vt state */ | ||
170 | if ((ioctl(_ecore_fb_vt_tty0_fd, VT_GETSTATE, &vtstat)) < 0) | ||
171 | { | ||
172 | printf("[ecore_fb:init] can't get current tty state\n"); | ||
173 | return 0; | ||
174 | } | ||
175 | _ecore_fb_vt_prev_vt = vtstat.v_active; | ||
176 | /* switch to another tty */ | ||
177 | if (_ecore_fb_vt_do_switch) | ||
178 | { | ||
179 | int vtno; | ||
180 | |||
181 | if ((ioctl(_ecore_fb_vt_tty0_fd, VT_OPENQRY, &vtno) < 0)) | ||
182 | { | ||
183 | printf("[ecore_fb:init] can't query for a vt\n"); | ||
184 | return 0; | ||
185 | } | ||
186 | _ecore_fb_vt_current_vt = vtno; | ||
187 | } | ||
188 | /* use current tty */ | ||
189 | else | ||
190 | _ecore_fb_vt_current_vt = _ecore_fb_vt_prev_vt; | ||
191 | if (!_ecore_fb_vt_setup()) | ||
192 | { | ||
193 | printf("[ecore_fb:init] can't setup the vt, restoring previous mode...\n"); | ||
194 | /* TODO finish this */ | ||
195 | if (_ecore_fb_vt_do_switch) | ||
196 | { | ||
197 | printf("[ecore_fb:init] switching back to vt %d\n", _ecore_fb_vt_prev_vt); | ||
198 | } | ||
199 | return 0; | ||
200 | } | ||
201 | return 1; | ||
202 | } | ||
203 | |||
204 | void | ||
205 | ecore_fb_vt_shutdown(void) | ||
206 | { | ||
207 | /* restore the previous mode */ | ||
208 | if (_ecore_fb_vt_tty_fd != -1) | ||
209 | { | ||
210 | tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); | ||
211 | ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); | ||
212 | ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); | ||
213 | ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &_ecore_fb_vt_prev_mode); | ||
214 | /* go back to previous vt */ | ||
215 | close(_ecore_fb_vt_tty_fd); | ||
216 | _ecore_fb_vt_tty_fd = -1; | ||
217 | } | ||
218 | |||
219 | if (_ecore_fb_user_handler) ecore_event_handler_del(_ecore_fb_user_handler); | ||
220 | _ecore_fb_user_handler = NULL; | ||
221 | |||
222 | if (_ecore_fb_filter_handler) ecore_event_filter_del(_ecore_fb_filter_handler); | ||
223 | _ecore_fb_filter_handler = NULL; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions. | ||
228 | * | ||
229 | * @{ | ||
230 | */ | ||
231 | |||
232 | /** | ||
233 | * @brief Set a callback called when a virtual terminal is gained. | ||
234 | * | ||
235 | * @param func The callback called when vt is gained. | ||
236 | * @param data The data to pass to the callback. | ||
237 | * | ||
238 | * This function sets the callback @p func which will be called when a | ||
239 | * virtual terminal is gained (for example you press Ctrl-Alt-F1 to go | ||
240 | * to vt1 and your app was using vt1). @p data will be pass to @p func if | ||
241 | * the callback is called. | ||
242 | */ | ||
243 | EAPI void | ||
244 | ecore_fb_callback_gain_set(void (*func) (void *data), void *data) | ||
245 | { | ||
246 | _ecore_fb_func_fb_gain = func; | ||
247 | _ecore_fb_func_fb_gain_data = data; | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * @brief Set a callback called when a virtual terminal is lost. | ||
252 | * | ||
253 | * @param func The callback called when vt is lost. | ||
254 | * @param data The data to pass to the callback. | ||
255 | * | ||
256 | * This function sets the callback @p func which will be called when a | ||
257 | * virtual terminal is lost (someone wants the tv from you and you | ||
258 | * want to give up that vt). @p data will be pass to @p func if the | ||
259 | * callback is called. | ||
260 | */ | ||
261 | EAPI void | ||
262 | ecore_fb_callback_lose_set(void (*func) (void *data), void *data) | ||
263 | { | ||
264 | _ecore_fb_func_fb_lost = func; | ||
265 | _ecore_fb_func_fb_lost_data = data; | ||
266 | |||
267 | } | ||
268 | |||
269 | /** | ||
270 | * @} | ||
271 | */ | ||
272 | |||
273 | /* | ||
274 | * This filter should take into account that the MOUSE_MOVE event can be | ||
275 | * triggered by a mouse, not just a touchscreen device, so you can't discard | ||
276 | * them (only those generated by a device that sends events with absolute | ||
277 | * coordinates). | ||
278 | |||
279 | typedef struct _Ecore_Fb_Filter_Data Ecore_Fb_Filter_Data; | ||
280 | |||
281 | struct _Ecore_Fb_Filter_Data | ||
282 | { | ||
283 | int last_event_type; | ||
284 | }; | ||
285 | |||
286 | static void * | ||
287 | _ecore_fb_event_filter_start(void *data __UNUSED__) | ||
288 | { | ||
289 | Ecore_Fb_Filter_Data *filter_data; | ||
290 | |||
291 | filter_data = calloc(1, sizeof(Ecore_Fb_Filter_Data)); | ||
292 | return filter_data; | ||
293 | } | ||
294 | |||
295 | static Eina_Bool | ||
296 | _ecore_fb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__) | ||
297 | { | ||
298 | Ecore_Fb_Filter_Data *filter_data; | ||
299 | |||
300 | filter_data = loop_data; | ||
301 | if (!filter_data) return EINA_TRUE; | ||
302 | if (type == ECORE_EVENT_MOUSE_MOVE) | ||
303 | { | ||
304 | if ((filter_data->last_event_type) == ECORE_EVENT_MOUSE_MOVE) | ||
305 | { | ||
306 | filter_data->last_event_type = type; | ||
307 | return EINA_FALSE; | ||
308 | } | ||
309 | } | ||
310 | filter_data->last_event_type = type; | ||
311 | return EINA_TRUE; | ||
312 | } | ||
313 | |||
314 | static void | ||
315 | _ecore_fb_event_filter_end(void *data __UNUSED__, void *loop_data) | ||
316 | { | ||
317 | Ecore_Fb_Filter_Data *filter_data; | ||
318 | |||
319 | filter_data = loop_data; | ||
320 | if (filter_data) free(filter_data); | ||
321 | } | ||
322 | */ | ||