ioctl.c revision b93e5812faffd3b6c5fb349072413aace31918d8
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 3b93e5812faffd3b6c5fb349072413aace31918d8Olivier Bailly#include <stdint.h> 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 5b93e5812faffd3b6c5fb349072413aace31918d8Olivier Bailly#include <getopt.h> 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/kd.h> 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/vt.h> 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h> 11b93e5812faffd3b6c5fb349072413aace31918d8Olivier Bailly#include <sys/ioctl.h> 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ioctl_main(int argc, char *argv[]) 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int c; 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int res; 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int read_only = 0; 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int length = -1; 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int arg_size = 4; 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int direct_arg = 0; 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint32_t ioctl_nr; 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void *ioctl_args; 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint8_t *ioctl_argp; 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint8_t *ioctl_argp_save; 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int rem; 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project do { 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project c = getopt(argc, argv, "rdl:a:h"); 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (c == EOF) 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch (c) { 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case 'r': 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project read_only = 1; 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case 'd': 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project direct_arg = 1; 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case 'l': 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project length = strtol(optarg, NULL, 0); 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case 'a': 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project arg_size = strtol(optarg, NULL, 0); 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case 'h': 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n" 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " -l <lenght> Length of io buffer\n" 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " -a <argsize> Size of each argument (1-8)\n" 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " -r Open device in read only mode\n" 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " -d Direct argument (no iobuffer)\n" 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " -h Print help\n", argv[0]); 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case '?': 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "%s: invalid option -%c\n", 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project argv[0], optopt); 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } while (1); 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(optind + 2 > argc) { 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "%s: too few arguments\n", argv[0]); 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = open(argv[optind], O_RDWR | O_SYNC); 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "cannot open %s\n", argv[optind]); 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 1; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project optind++; 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl_nr = strtol(argv[optind], NULL, 0); 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project optind++; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(direct_arg) { 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project arg_size = 4; 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project length = 4; 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(length < 0) { 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project length = (argc - optind) * arg_size; 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(length) { 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl_args = calloc(1, length); 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl_argp_save = ioctl_argp = ioctl_args; 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rem = length; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(optind < argc) { 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uint64_t tmp = strtoull(argv[optind], NULL, 0); 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(rem < arg_size) { 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "%s: too many arguments\n", argv[0]); 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(ioctl_argp, &tmp, arg_size); 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl_argp += arg_size; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rem -= arg_size; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project optind++; 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("sending ioctl 0x%x", ioctl_nr); 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rem = length; 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(rem--) { 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf(" 0x%02x", *ioctl_argp_save++); 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("\n"); 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(direct_arg) 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args); 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else if(length) 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project res = ioctl(fd, ioctl_nr, ioctl_args); 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project else 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project res = ioctl(fd, ioctl_nr, 0); 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (res < 0) { 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 1; 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(length) { 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("return buf:"); 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl_argp = ioctl_args; 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rem = length; 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(rem--) { 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf(" %02x", *ioctl_argp++); 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printf("\n"); 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 129