Add gbs.conf
[profile/ivi/psplash.git] / psplash-console.c
1 /* 
2  *  pslash - a lightweight framebuffer splashscreen for embedded devices. 
3  *
4  *  Copyright (c) 2006 Matthew Allum <mallum@o-hand.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2, or (at your option)
9  *  any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  */
17
18 #include "psplash.h"
19
20 /* Globals, needed for signal handling */
21 static int ConsoleFd      = -1;
22 static int VTNum          = -1;
23 static int VTNumInitial   = -1;
24 static int Visible        =  1;
25
26 static void
27 vt_request (int sig)
28 {
29   DBG("mark, visible:%i", Visible);
30
31   if (Visible)
32     {
33       /* Allow Switch Away */
34       if (ioctl (ConsoleFd, VT_RELDISP, 1) < 0)
35         perror("Error cannot switch away from console");
36       Visible = 0;
37
38       /* FIXME: 
39        * We likely now want to signal the main loop as to exit   
40        * and we've now likely switched to the X tty. Note, this
41        * seems to happen anyway atm due to select() call getting
42        * a signal interuption error - not sure if this is really
43        * reliable however. 
44       */
45     }
46   else
47     {
48       if (ioctl (ConsoleFd, VT_RELDISP, VT_ACKACQ))
49         perror ("Error can't acknowledge VT switch");
50       Visible = 1;
51       /* FIXME: need to schedule repaint some how ? */
52     }
53 }
54
55 static void
56 psplash_console_ignore_switches (void)
57 {
58   struct sigaction    act;
59   struct vt_mode      vt_mode;
60   
61   if (ioctl(ConsoleFd, VT_GETMODE, &vt_mode) < 0)
62     {
63       perror("Error VT_SETMODE failed");
64       return;
65     }
66
67   act.sa_handler = SIG_IGN;
68   sigemptyset (&act.sa_mask);
69   act.sa_flags = 0;
70   sigaction (SIGUSR1, &act, 0);
71   
72   vt_mode.mode = VT_AUTO;
73   vt_mode.relsig = 0;
74   vt_mode.acqsig = 0;
75
76   if (ioctl(ConsoleFd, VT_SETMODE, &vt_mode) < 0)
77     perror("Error VT_SETMODE failed");
78 }
79
80 static void
81 psplash_console_handle_switches (void)
82 {
83   struct sigaction    act;
84   struct vt_mode      vt_mode;
85  
86   if (ioctl(ConsoleFd, VT_GETMODE, &vt_mode) < 0)
87     {
88       perror("Error VT_SETMODE failed");
89       return;
90     }
91
92   act.sa_handler = vt_request;
93   sigemptyset (&act.sa_mask);
94   act.sa_flags = 0;
95   sigaction (SIGUSR1, &act, 0);
96   
97   vt_mode.mode   = VT_PROCESS;
98   vt_mode.relsig = SIGUSR1;
99   vt_mode.acqsig = SIGUSR1;
100
101   if (ioctl(ConsoleFd, VT_SETMODE, &vt_mode) < 0)
102     perror("Error VT_SETMODE failed");
103 }
104
105 void 
106 psplash_console_switch (void) 
107 {
108   char           vtname[10];
109   int            fd;
110   struct vt_stat vt_state;
111
112   if ((fd = open("/dev/tty0",O_WRONLY,0)) < 0)
113     {
114       perror("Error Cannot open /dev/tty0");
115       return;
116     }
117
118   /* Find next free terminal */
119   if ((ioctl(fd, VT_OPENQRY, &VTNum) < 0))
120     {
121       perror("Error unable to find a free virtual terminal");
122       close(fd);
123       return;
124     }
125   
126   close(fd);
127   
128   sprintf(vtname,"/dev/tty%d", VTNum);
129
130   if ((ConsoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0)
131     {
132       fprintf(stderr, "Error cannot open %s: %s\n", vtname, strerror(errno));
133       return;
134     }
135
136   if (ioctl(ConsoleFd, VT_GETSTATE, &vt_state) == 0)
137     VTNumInitial = vt_state.v_active;
138
139   /* Switch to new free terminal */
140
141   psplash_console_ignore_switches ();
142
143   if (ioctl(ConsoleFd, VT_ACTIVATE, VTNum) != 0)
144     perror("Error VT_ACTIVATE failed");
145   
146   if (ioctl(ConsoleFd, VT_WAITACTIVE, VTNum) != 0)
147     perror("Error VT_WAITACTIVE failed\n");
148
149   psplash_console_handle_switches ();
150   
151   if (ioctl(ConsoleFd, KDSETMODE, KD_GRAPHICS) < 0)
152     perror("Error KDSETMODE KD_GRAPHICS failed\n");
153
154   return;
155 }
156
157 void
158 psplash_console_reset (void)
159 {
160   int              fd;
161   struct vt_stat   vt_state;
162
163   if (ConsoleFd < 0)
164     return;
165
166   /* Back to text mode */
167   ioctl(ConsoleFd, KDSETMODE, KD_TEXT); 
168
169   psplash_console_ignore_switches ();
170
171   /* Attempt to switch back to initial console if were still active */
172   ioctl (ConsoleFd, VT_GETSTATE, &vt_state);
173
174   if (VTNum == vt_state.v_active)
175     {
176       if (VTNumInitial > -1)
177         {
178           ioctl (ConsoleFd, VT_ACTIVATE, VTNumInitial);
179           ioctl (ConsoleFd, VT_WAITACTIVE, VTNumInitial);
180           VTNumInitial = -1;
181         }
182     }
183
184   /* Cleanup */
185
186   close(ConsoleFd); 
187
188   if ((fd = open ("/dev/tty0", O_RDWR|O_NDELAY, 0)) >= 0)
189     {
190       ioctl (fd, VT_DISALLOCATE, VTNum);
191       close (fd);
192     }
193
194   return;
195 }