blob: d1cc14a083a921f3ee8544e9a2a076cd0220daf5 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#include <stdio.h>
2#include <stdlib.h>
Olivier Baillyb93e5812010-11-17 11:47:23 -08003#include <stdint.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08004#include <fcntl.h>
Olivier Baillyb93e5812010-11-17 11:47:23 -08005#include <getopt.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08006#include <string.h>
7#include <linux/kd.h>
8#include <linux/vt.h>
9#include <errno.h>
10#include <pthread.h>
Olivier Baillyb93e5812010-11-17 11:47:23 -080011#include <sys/ioctl.h>
Elliott Hughes0badbd62014-12-29 12:24:25 -080012#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080013
14int ioctl_main(int argc, char *argv[])
15{
16 int c;
17 int fd;
18 int res;
19
20 int read_only = 0;
21 int length = -1;
22 int arg_size = 4;
23 int direct_arg = 0;
24 uint32_t ioctl_nr;
Mark Salyzynaa907762014-05-08 09:31:43 -070025 void *ioctl_args = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026 uint8_t *ioctl_argp;
Mark Salyzynaa907762014-05-08 09:31:43 -070027 uint8_t *ioctl_argp_save = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028 int rem;
29
30 do {
31 c = getopt(argc, argv, "rdl:a:h");
32 if (c == EOF)
33 break;
34 switch (c) {
35 case 'r':
36 read_only = 1;
37 break;
38 case 'd':
39 direct_arg = 1;
40 break;
41 case 'l':
42 length = strtol(optarg, NULL, 0);
43 break;
44 case 'a':
45 arg_size = strtol(optarg, NULL, 0);
46 break;
47 case 'h':
48 fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n"
Elliott Hughesa0d61ba2014-10-06 10:09:25 -070049 " -l <length> Length of io buffer\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050 " -a <argsize> Size of each argument (1-8)\n"
51 " -r Open device in read only mode\n"
52 " -d Direct argument (no iobuffer)\n"
53 " -h Print help\n", argv[0]);
54 return -1;
55 case '?':
56 fprintf(stderr, "%s: invalid option -%c\n",
57 argv[0], optopt);
58 exit(1);
59 }
60 } while (1);
61
62 if(optind + 2 > argc) {
63 fprintf(stderr, "%s: too few arguments\n", argv[0]);
64 exit(1);
65 }
66
Scott Anderson9e97fee2013-10-17 15:30:54 -070067 if (!strcmp(argv[optind], "-")) {
68 fd = STDIN_FILENO;
69 } else {
70 fd = open(argv[optind], read_only ? O_RDONLY : (O_RDWR | O_SYNC));
71 if (fd < 0) {
72 fprintf(stderr, "cannot open %s\n", argv[optind]);
73 return 1;
74 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075 }
76 optind++;
77
78 ioctl_nr = strtol(argv[optind], NULL, 0);
79 optind++;
80
81 if(direct_arg) {
82 arg_size = 4;
83 length = 4;
84 }
85
86 if(length < 0) {
87 length = (argc - optind) * arg_size;
88 }
89 if(length) {
90 ioctl_args = calloc(1, length);
91
92 ioctl_argp_save = ioctl_argp = ioctl_args;
93 rem = length;
94 while(optind < argc) {
95 uint64_t tmp = strtoull(argv[optind], NULL, 0);
96 if(rem < arg_size) {
97 fprintf(stderr, "%s: too many arguments\n", argv[0]);
98 exit(1);
99 }
100 memcpy(ioctl_argp, &tmp, arg_size);
101 ioctl_argp += arg_size;
102 rem -= arg_size;
103 optind++;
104 }
105 }
106 printf("sending ioctl 0x%x", ioctl_nr);
107 rem = length;
108 while(rem--) {
109 printf(" 0x%02x", *ioctl_argp_save++);
110 }
111 printf("\n");
112
113 if(direct_arg)
114 res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args);
115 else if(length)
116 res = ioctl(fd, ioctl_nr, ioctl_args);
117 else
118 res = ioctl(fd, ioctl_nr, 0);
119 if (res < 0) {
Mark Salyzynaa907762014-05-08 09:31:43 -0700120 free(ioctl_args);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res);
122 return 1;
123 }
124 if(length) {
125 printf("return buf:");
126 ioctl_argp = ioctl_args;
127 rem = length;
128 while(rem--) {
129 printf(" %02x", *ioctl_argp++);
130 }
131 printf("\n");
132 }
Mark Salyzynaa907762014-05-08 09:31:43 -0700133 free(ioctl_args);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800134 return 0;
135}