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