blob: 0159c07ee3612d520a12ea198f83b953e2c719ba [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#include <stdio.h>
2#include <stdlib.h>
3#include <fcntl.h>
4#include <string.h>
5#include <linux/kd.h>
6#include <linux/vt.h>
7#include <errno.h>
8#include <pthread.h>
Olivier Baillyb93e5812010-11-17 11:47:23 -08009#include <unistd.h>
10#include <sys/ioctl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080011
12static int activate_thread_switch_vc;
13static void *activate_thread(void *arg)
14{
15 int res;
16 int fd = (int)arg;
17 while(activate_thread_switch_vc >= 0) {
18 do {
19 res = ioctl(fd, VT_ACTIVATE, (void*)activate_thread_switch_vc);
20 } while(res < 0 && errno == EINTR);
21 if (res < 0) {
22 fprintf(stderr, "ioctl( vcfd, VT_ACTIVATE, vtnum) failed, %d %d %s for %d\n", res, errno, strerror(errno), activate_thread_switch_vc);
23 }
24 if(activate_thread_switch_vc >= 0)
25 sleep(1);
26 }
27 return NULL;
28}
29
30
31int setconsole_main(int argc, char *argv[])
32{
33 int c;
34 int fd;
35 int res;
36
37 int mode = -1;
38 int new_vc = 0;
39 int close_vc = 0;
40 int switch_vc = -1;
41 int printvc = 0;
42 char *ttydev = "/dev/tty0";
43
44 do {
45 c = getopt(argc, argv, "d:gtncv:poh");
46 if (c == EOF)
47 break;
48 switch (c) {
49 case 'd':
50 ttydev = optarg;
51 break;
52 case 'g':
53 if(mode == KD_TEXT) {
54 fprintf(stderr, "%s: cannot specify both -g and -t\n", argv[0]);
55 exit(1);
56 }
57 mode = KD_GRAPHICS;
58 break;
59 case 't':
60 if(mode == KD_GRAPHICS) {
61 fprintf(stderr, "%s: cannot specify both -g and -t\n", argv[0]);
62 exit(1);
63 }
64 mode = KD_TEXT;
65 break;
66 case 'n':
67 new_vc = 1;
68 break;
69 case 'c':
70 close_vc = 1;
71 break;
72 case 'v':
73 switch_vc = atoi(optarg);
74 break;
75 case 'p':
76 printvc |= 1;
77 break;
78 case 'o':
79 printvc |= 2;
80 break;
81 case 'h':
82 fprintf(stderr, "%s [-d <dev>] [-v <vc>] [-gtncpoh]\n"
83 " -d <dev> Use <dev> instead of /dev/tty0\n"
84 " -v <vc> Switch to virtual console <vc>\n"
85 " -g Switch to graphics mode\n"
86 " -t Switch to text mode\n"
87 " -n Create and switch to new virtual console\n"
88 " -c Close unused virtual consoles\n"
89 " -p Print new virtual console\n"
90 " -o Print old virtual console\n"
91 " -h Print help\n", argv[0]);
92 return -1;
93 case '?':
94 fprintf(stderr, "%s: invalid option -%c\n",
95 argv[0], optopt);
96 exit(1);
97 }
98 } while (1);
99 if(mode == -1 && new_vc == 0 && close_vc == 0 && switch_vc == -1 && printvc == 0) {
100 fprintf(stderr,"%s [-d <dev>] [-v <vc>] [-gtncpoh]\n", argv[0]);
101 return -1;
102 }
103
104 fd = open(ttydev, O_RDWR | O_SYNC);
105 if (fd < 0) {
106 fprintf(stderr, "cannot open %s\n", ttydev);
107 return -1;
108 }
109
110 if ((printvc && !new_vc) || (printvc & 2)) {
111 struct vt_stat vs;
112
113 res = ioctl(fd, VT_GETSTATE, &vs);
114 if (res < 0) {
115 fprintf(stderr, "ioctl(vcfd, VT_GETSTATE, &vs) failed, %d\n", res);
116 }
117 printf("%d\n", vs.v_active);
118 }
119
120 if (new_vc) {
121 int vtnum;
122 res = ioctl(fd, VT_OPENQRY, &vtnum);
123 if (res < 0 || vtnum == -1) {
124 fprintf(stderr, "ioctl(vcfd, VT_OPENQRY, &vtnum) failed, res %d, vtnum %d\n", res, vtnum);
125 }
126 switch_vc = vtnum;
127 }
128 if (switch_vc != -1) {
129 pthread_t thread;
130 pthread_attr_t attr;
131 activate_thread_switch_vc = switch_vc;
132 pthread_attr_init(&attr);
133 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
134 pthread_create(&thread, &attr, activate_thread, (void*)fd);
135
136 do {
137 res = ioctl(fd, VT_WAITACTIVE, (void*)switch_vc);
138 } while(res < 0 && errno == EINTR);
139 activate_thread_switch_vc = -1;
140 if (res < 0) {
141 fprintf(stderr, "ioctl( vcfd, VT_WAITACTIVE, vtnum) failed, %d %d %s for %d\n", res, errno, strerror(errno), switch_vc);
142 }
143 if(printvc & 1)
144 printf("%d\n", switch_vc);
145
146 close(fd);
147 fd = open(ttydev, O_RDWR | O_SYNC);
148 if (fd < 0) {
149 fprintf(stderr, "cannot open %s\n", ttydev);
150 return -1;
151 }
152 }
153 if (close_vc) {
154 res = ioctl(fd, VT_DISALLOCATE, 0);
155 if (res < 0) {
156 fprintf(stderr, "ioctl(vcfd, VT_DISALLOCATE, 0) failed, %d\n", res);
157 }
158 }
159 if (mode != -1) {
160 if (ioctl(fd, KDSETMODE, (void*)mode) < 0) {
161 fprintf(stderr, "KDSETMODE %d failed\n", mode);
162 return -1;
163 }
164 }
165 return 0;
166}