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