blob: 73539d140e8349037859b907fa6e9d682bc1dd5d [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>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080012
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;
Mark Salyzynaa907762014-05-08 09:31:43 -070024 void *ioctl_args = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025 uint8_t *ioctl_argp;
Mark Salyzynaa907762014-05-08 09:31:43 -070026 uint8_t *ioctl_argp_save = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080027 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"
Elliott Hughesa0d61ba2014-10-06 10:09:25 -070048 " -l <length> Length of io buffer\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049 " -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
Scott Anderson9e97fee2013-10-17 15:30:54 -070066 if (!strcmp(argv[optind], "-")) {
67 fd = STDIN_FILENO;
68 } else {
69 fd = open(argv[optind], read_only ? O_RDONLY : (O_RDWR | O_SYNC));
70 if (fd < 0) {
71 fprintf(stderr, "cannot open %s\n", argv[optind]);
72 return 1;
73 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 }
75 optind++;
76
77 ioctl_nr = strtol(argv[optind], NULL, 0);
78 optind++;
79
80 if(direct_arg) {
81 arg_size = 4;
82 length = 4;
83 }
84
85 if(length < 0) {
86 length = (argc - optind) * arg_size;
87 }
88 if(length) {
89 ioctl_args = calloc(1, length);
90
91 ioctl_argp_save = ioctl_argp = ioctl_args;
92 rem = length;
93 while(optind < argc) {
94 uint64_t tmp = strtoull(argv[optind], NULL, 0);
95 if(rem < arg_size) {
96 fprintf(stderr, "%s: too many arguments\n", argv[0]);
97 exit(1);
98 }
99 memcpy(ioctl_argp, &tmp, arg_size);
100 ioctl_argp += arg_size;
101 rem -= arg_size;
102 optind++;
103 }
104 }
105 printf("sending ioctl 0x%x", ioctl_nr);
106 rem = length;
107 while(rem--) {
108 printf(" 0x%02x", *ioctl_argp_save++);
109 }
110 printf("\n");
111
112 if(direct_arg)
113 res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args);
114 else if(length)
115 res = ioctl(fd, ioctl_nr, ioctl_args);
116 else
117 res = ioctl(fd, ioctl_nr, 0);
118 if (res < 0) {
Mark Salyzynaa907762014-05-08 09:31:43 -0700119 free(ioctl_args);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120 fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res);
121 return 1;
122 }
123 if(length) {
124 printf("return buf:");
125 ioctl_argp = ioctl_args;
126 rem = length;
127 while(rem--) {
128 printf(" %02x", *ioctl_argp++);
129 }
130 printf("\n");
131 }
Mark Salyzynaa907762014-05-08 09:31:43 -0700132 free(ioctl_args);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800133 return 0;
134}