|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <stdint.h> | 
|  | #include <fcntl.h> | 
|  | #include <getopt.h> | 
|  | #include <string.h> | 
|  | #include <linux/kd.h> | 
|  | #include <linux/vt.h> | 
|  | #include <errno.h> | 
|  | #include <pthread.h> | 
|  | #include <sys/ioctl.h> | 
|  |  | 
|  | int ioctl_main(int argc, char *argv[]) | 
|  | { | 
|  | int c; | 
|  | int fd; | 
|  | int res; | 
|  |  | 
|  | int read_only = 0; | 
|  | int length = -1; | 
|  | int arg_size = 4; | 
|  | int direct_arg = 0; | 
|  | uint32_t ioctl_nr; | 
|  | void *ioctl_args; | 
|  | uint8_t *ioctl_argp; | 
|  | uint8_t *ioctl_argp_save; | 
|  | int rem; | 
|  |  | 
|  | do { | 
|  | c = getopt(argc, argv, "rdl:a:h"); | 
|  | if (c == EOF) | 
|  | break; | 
|  | switch (c) { | 
|  | case 'r': | 
|  | read_only = 1; | 
|  | break; | 
|  | case 'd': | 
|  | direct_arg = 1; | 
|  | break; | 
|  | case 'l': | 
|  | length = strtol(optarg, NULL, 0); | 
|  | break; | 
|  | case 'a': | 
|  | arg_size = strtol(optarg, NULL, 0); | 
|  | break; | 
|  | case 'h': | 
|  | fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n" | 
|  | "  -l <lenght>   Length of io buffer\n" | 
|  | "  -a <argsize>  Size of each argument (1-8)\n" | 
|  | "  -r            Open device in read only mode\n" | 
|  | "  -d            Direct argument (no iobuffer)\n" | 
|  | "  -h            Print help\n", argv[0]); | 
|  | return -1; | 
|  | case '?': | 
|  | fprintf(stderr, "%s: invalid option -%c\n", | 
|  | argv[0], optopt); | 
|  | exit(1); | 
|  | } | 
|  | } while (1); | 
|  |  | 
|  | if(optind + 2 > argc) { | 
|  | fprintf(stderr, "%s: too few arguments\n", argv[0]); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | fd = open(argv[optind], O_RDWR | O_SYNC); | 
|  | if (fd < 0) { | 
|  | fprintf(stderr, "cannot open %s\n", argv[optind]); | 
|  | return 1; | 
|  | } | 
|  | optind++; | 
|  |  | 
|  | ioctl_nr = strtol(argv[optind], NULL, 0); | 
|  | optind++; | 
|  |  | 
|  | if(direct_arg) { | 
|  | arg_size = 4; | 
|  | length = 4; | 
|  | } | 
|  |  | 
|  | if(length < 0) { | 
|  | length = (argc - optind) * arg_size; | 
|  | } | 
|  | if(length) { | 
|  | ioctl_args = calloc(1, length); | 
|  |  | 
|  | ioctl_argp_save = ioctl_argp = ioctl_args; | 
|  | rem = length; | 
|  | while(optind < argc) { | 
|  | uint64_t tmp = strtoull(argv[optind], NULL, 0); | 
|  | if(rem < arg_size) { | 
|  | fprintf(stderr, "%s: too many arguments\n", argv[0]); | 
|  | exit(1); | 
|  | } | 
|  | memcpy(ioctl_argp, &tmp, arg_size); | 
|  | ioctl_argp += arg_size; | 
|  | rem -= arg_size; | 
|  | optind++; | 
|  | } | 
|  | } | 
|  | printf("sending ioctl 0x%x", ioctl_nr); | 
|  | rem = length; | 
|  | while(rem--) { | 
|  | printf(" 0x%02x", *ioctl_argp_save++); | 
|  | } | 
|  | printf("\n"); | 
|  |  | 
|  | if(direct_arg) | 
|  | res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args); | 
|  | else if(length) | 
|  | res = ioctl(fd, ioctl_nr, ioctl_args); | 
|  | else | 
|  | res = ioctl(fd, ioctl_nr, 0); | 
|  | if (res < 0) { | 
|  | fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res); | 
|  | return 1; | 
|  | } | 
|  | if(length) { | 
|  | printf("return buf:"); | 
|  | ioctl_argp = ioctl_args; | 
|  | rem = length; | 
|  | while(rem--) { | 
|  | printf(" %02x", *ioctl_argp++); | 
|  | } | 
|  | printf("\n"); | 
|  | } | 
|  | return 0; | 
|  | } |