9831ef3e3c90505cb81ff1bb8ec5939603c91fff
[framework/uifw/ecore.git] / src / lib / ecore_fb / ecore_fb_vt.c
1 #include "Ecore_Fb.h"
2 #include "ecore_fb_private.h"
3
4 static int _ecore_fb_vt_do_switch = 0;
5
6 static int _ecore_fb_vt_tty0_fd = 0;
7 static int _ecore_fb_vt_tty_fd = 0;
8 static int _ecore_fb_vt_current_vt = 0;
9 static int _ecore_fb_vt_prev_vt = 0;
10
11 static struct termios _ecore_fb_tty_prev_tio_mode;
12 static struct vt_mode _ecore_fb_vt_prev_mode;
13
14 static int _ecore_fb_signal_usr_handler(void *data, int type, void *ev);
15 static Ecore_Event_Handler *_ecore_fb_user_handler = NULL;
16 static int _ecore_fb_tty_prev_mode = 0;
17 static int _ecore_fb_tty_prev_kd_mode = 0;
18
19 /* callbacks for an attach/release of a vt */
20 static void (*_ecore_fb_func_fb_lost) (void *data) = NULL;
21 static void *_ecore_fb_func_fb_lost_data = NULL;
22 static void (*_ecore_fb_func_fb_gain) (void *data) = NULL;
23 static void *_ecore_fb_func_fb_gain_data = NULL;
24
25 /* FIXME what is the filter for? */
26 static Ecore_Event_Filter *_ecore_fb_filter_handler = NULL;
27
28 static void *_ecore_fb_event_filter_start(void *data);
29 static int   _ecore_fb_event_filter_filter(void *data, void *loop_data, int type, void *event);
30 static void  _ecore_fb_event_filter_end(void *data, void *loop_data);
31
32 /* prototypes */
33 static void _ecore_fb_vt_switch(int vt);
34
35 static int
36 _ecore_fb_signal_usr_handler(void *data __UNUSED__, int type __UNUSED__, void *ev)
37 {
38
39         Ecore_Event_Signal_User *e;
40    
41         e = (Ecore_Event_Signal_User *)ev;
42         if (e->number == 1)
43         {
44                 /* release vt */
45                 if (_ecore_fb_func_fb_lost) _ecore_fb_func_fb_lost(_ecore_fb_func_fb_lost_data);
46                 /* TODO stop listening from the devices? let the callback do it? */
47                 ioctl(_ecore_fb_vt_tty_fd, VT_RELDISP, 1);
48         }
49         else if (e->number == 2)
50         {
51                 /* attach vt */
52                 if (_ecore_fb_func_fb_gain) _ecore_fb_func_fb_gain(_ecore_fb_func_fb_gain_data);
53                 /* TODO reattach all devices */
54         }
55         return 1;
56 }
57
58 static void
59 _ecore_fb_vt_switch(int vt)
60 {
61         vt++;
62         if (_ecore_fb_vt_tty_fd != 0)
63         {
64                 if (vt != _ecore_fb_vt_current_vt)
65                 {
66                         tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode);
67                         ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode);
68                         ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode);
69                 }
70         }
71         ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, vt);
72 }
73
74 static int
75 _ecore_fb_vt_setup(void)
76 {
77         char buf[64];
78         struct termios tio;
79         struct vt_mode new_vtmode;
80
81         if(_ecore_fb_vt_current_vt != _ecore_fb_vt_prev_vt)
82         {
83                 snprintf(buf, sizeof(buf), "/dev/tty%i", _ecore_fb_vt_current_vt);
84                 if((_ecore_fb_vt_tty_fd = open(buf, O_RDWR)) < 0)
85                 {
86                         printf("[ecore_fb:vt_setup] cant open tty %d\n", _ecore_fb_vt_current_vt);
87                         return 0;
88                 }
89                 close(_ecore_fb_vt_tty0_fd);
90                 _ecore_fb_vt_tty0_fd = 0;
91                 /* FIXME detach the process from current tty ? */
92         }
93         else
94                 _ecore_fb_vt_tty_fd = _ecore_fb_vt_tty0_fd;
95         /* for backup */
96         tcgetattr(_ecore_fb_vt_tty_fd, &_ecore_fb_tty_prev_tio_mode);
97         ioctl(_ecore_fb_vt_tty_fd, KDGETMODE, &_ecore_fb_tty_prev_kd_mode);
98         ioctl(_ecore_fb_vt_tty_fd, VT_GETMODE, &_ecore_fb_vt_prev_mode);
99
100         if(ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, KD_GRAPHICS) < 0)
101         {
102                 perror("[ecore_fb:vt_setup] cant set the mode to KD_GRAPHICS");
103                 close(_ecore_fb_vt_tty_fd);
104                 return 0;
105         }
106         ioctl(_ecore_fb_vt_tty_fd, KDGKBMODE, &_ecore_fb_tty_prev_mode);
107         
108         /* support of switching */
109         new_vtmode.mode = VT_PROCESS;
110         new_vtmode.waitv = 0;
111         new_vtmode.relsig = SIGUSR1;
112         new_vtmode.acqsig = SIGUSR2;
113         if(ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &new_vtmode) < 0)
114         {
115                 perror("[ecore_fb:vt_setup] cant set the tty mode");
116                 close(_ecore_fb_vt_tty_fd);
117                 return 0;
118         }
119         /* register signal handlers when alloc/detach of vt */
120         _ecore_fb_user_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
121                                                     _ecore_fb_signal_usr_handler,
122                                                     NULL);
123         /* What does this does? */
124         _ecore_fb_filter_handler = ecore_event_filter_add(_ecore_fb_event_filter_start, _ecore_fb_event_filter_filter, _ecore_fb_event_filter_end, NULL);
125         
126         usleep(40000);
127         if(ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, _ecore_fb_vt_current_vt) < 0)
128         {
129                 perror("[ecore_fb:vt_setup] error on VT_ACTIVATE");
130                 close(_ecore_fb_vt_tty_fd);
131                 return 0;
132         }
133         if(ioctl(_ecore_fb_vt_tty_fd, VT_WAITACTIVE, _ecore_fb_vt_current_vt) < 0)
134         {
135                 perror("[ecore_fb:vt_setup] error on VT_WAITACTIVE");
136                 close(_ecore_fb_vt_tty_fd);
137                 return 0;
138         }
139         /* FIXME assign the fb to the tty in case isnt setup */
140         return 1;
141 }
142
143 int
144 ecore_fb_vt_init(void)
145 {
146         struct vt_stat vtstat;
147
148         /* as root you can allocate another tty */
149         if(!geteuid())
150                 _ecore_fb_vt_do_switch = 1;
151         if((_ecore_fb_vt_tty0_fd = open("/dev/tty0", O_RDONLY)) < 0)
152         {
153                 printf("[ecore_fb:init] cant open /dev/tty0\n");
154                 return 0;
155         }
156         /* query current vt state */
157         if((ioctl(_ecore_fb_vt_tty0_fd, VT_GETSTATE, &vtstat)) < 0)
158         {
159                 printf("[ecore_fb:init] cant get current tty state\n");
160                 return 0;
161         }
162         _ecore_fb_vt_prev_vt = vtstat.v_active;
163         /* switch to another tty */
164         if(_ecore_fb_vt_do_switch)
165         {
166                 int vtno;
167
168                 if ((ioctl(_ecore_fb_vt_tty0_fd, VT_OPENQRY, &vtno) < 0))
169                 {
170                         printf("[ecore_fb:init] cant query for a vt\n");
171                         return 0;
172                 }
173                 _ecore_fb_vt_current_vt = vtno;
174         }
175         /* use current tty */
176         else
177                 _ecore_fb_vt_current_vt = _ecore_fb_vt_prev_vt;
178         if(!_ecore_fb_vt_setup())
179         {
180                 printf("[ecore_fb:init] cant setup the vt, restoring previous mode...\n");
181                 /* TODO finish this */
182                 if(_ecore_fb_vt_do_switch)
183                 {
184                         printf("[ecore_fb:init] switching back to vt %d\n", _ecore_fb_vt_prev_vt);
185                 }
186                 return 0;
187         }
188         return 1;
189 }
190
191 void
192 ecore_fb_vt_shutdown(void)
193 {
194         /* restore the previous mode */
195         if(_ecore_fb_vt_tty_fd != 0)
196         {
197                 tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode);
198                 ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode);
199                 ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode);
200                 ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &_ecore_fb_vt_prev_mode);
201                 /* go back to previous vt */
202                 close(_ecore_fb_vt_tty_fd);
203                 _ecore_fb_vt_tty_fd = 0;
204         }
205         
206         if(_ecore_fb_user_handler)
207                 ecore_event_handler_del(_ecore_fb_user_handler);
208         _ecore_fb_user_handler = NULL;
209
210         if(_ecore_fb_filter_handler)
211                 ecore_event_filter_del(_ecore_fb_filter_handler);
212         _ecore_fb_filter_handler = NULL;
213 }
214
215 /**
216  * To be documented.
217  *
218  * FIXME: To be fixed.
219  * @todo Documentation: Find out what this does.
220  */
221 EAPI void
222 ecore_fb_callback_gain_set(void (*func) (void *data), void *data)
223 {
224    _ecore_fb_func_fb_gain = func;
225    _ecore_fb_func_fb_gain_data = data;
226 }
227
228 /**
229  * To be documented.
230  *
231  * FIXME: To be fixed.
232  * @todo Documentation: Find out what this does.
233  */
234 EAPI void
235 ecore_fb_callback_lose_set(void (*func) (void *data), void *data)
236 {
237    _ecore_fb_func_fb_lost = func;
238    _ecore_fb_func_fb_lost_data = data;
239 }
240 typedef struct _Ecore_Fb_Filter_Data Ecore_Fb_Filter_Data;
241    
242 struct _Ecore_Fb_Filter_Data
243 {
244    int last_event_type;
245 };
246                 
247 static void *
248 _ecore_fb_event_filter_start(void *data __UNUSED__)
249 {
250    Ecore_Fb_Filter_Data *filter_data;
251    
252    filter_data = calloc(1, sizeof(Ecore_Fb_Filter_Data));
253    return filter_data;
254 }
255
256 static int
257 _ecore_fb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__)
258 {
259    Ecore_Fb_Filter_Data *filter_data;
260    
261    filter_data = loop_data;
262    if (!filter_data) return 1;
263    if (type == ECORE_FB_EVENT_MOUSE_MOVE)
264      {
265         if ((filter_data->last_event_type) == ECORE_FB_EVENT_MOUSE_MOVE)
266           {
267              filter_data->last_event_type = type;
268              return 0;
269           }
270      }
271    filter_data->last_event_type = type;
272    return 1;
273 }
274
275 static void
276 _ecore_fb_event_filter_end(void *data __UNUSED__, void *loop_data)
277 {
278    Ecore_Fb_Filter_Data *filter_data;
279    
280    filter_data = loop_data;
281    if (filter_data) free(filter_data);
282 }