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