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