|
| 1 | + |
| 2 | +/* userspace_ioctl.c - the process to use ioctl's to control the kernel module |
| 3 | + * |
| 4 | + * Until now we could have used cat for input and output. But now |
| 5 | + * we need to do ioctl's, which require writing our own process. |
| 6 | + */ |
| 7 | + |
| 8 | +/* device specifics, such as ioctl numbers and the |
| 9 | + * major device file. */ |
| 10 | +#include "../chardev.h" |
| 11 | + |
| 12 | +#include <stdio.h> /* standard I/O */ |
| 13 | +#include <fcntl.h> /* open */ |
| 14 | +#include <unistd.h> /* close */ |
| 15 | +#include <stdlib.h> /* exit */ |
| 16 | +#include <sys/ioctl.h> /* ioctl */ |
| 17 | + |
| 18 | +/* Functions for the ioctl calls */ |
| 19 | + |
| 20 | +int ioctl_set_msg(int file_desc, char *message) |
| 21 | +{ |
| 22 | + int ret_val; |
| 23 | + |
| 24 | + ret_val = ioctl(file_desc, IOCTL_SET_MSG, message); |
| 25 | + |
| 26 | + if (ret_val < 0) { |
| 27 | + printf("ioctl_set_msg failed:%d\n", ret_val); |
| 28 | + } |
| 29 | + |
| 30 | + return ret_val; |
| 31 | +} |
| 32 | + |
| 33 | +int ioctl_get_msg(int file_desc) |
| 34 | +{ |
| 35 | + int ret_val; |
| 36 | + char message[100] = { 0 }; |
| 37 | + |
| 38 | + /* Warning - this is dangerous because we don't tell |
| 39 | + * the kernel how far it's allowed to write, so it |
| 40 | + * might overflow the buffer. In a real production |
| 41 | + * program, we would have used two ioctls - one to tell |
| 42 | + * the kernel the buffer length and another to give |
| 43 | + * it the buffer to fill |
| 44 | + */ |
| 45 | + ret_val = ioctl(file_desc, IOCTL_GET_MSG, message); |
| 46 | + |
| 47 | + if (ret_val < 0) { |
| 48 | + printf("ioctl_get_msg failed:%d\n", ret_val); |
| 49 | + } |
| 50 | + printf("get_msg message:%s", message); |
| 51 | + |
| 52 | + return ret_val; |
| 53 | +} |
| 54 | + |
| 55 | +int ioctl_get_nth_byte(int file_desc) |
| 56 | +{ |
| 57 | + int i, c; |
| 58 | + |
| 59 | + printf("get_nth_byte message:"); |
| 60 | + |
| 61 | + i = 0; |
| 62 | + do { |
| 63 | + c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++); |
| 64 | + |
| 65 | + if (c < 0) { |
| 66 | + printf("\nioctl_get_nth_byte failed at the %d'th byte:\n", i); |
| 67 | + return c; |
| 68 | + } |
| 69 | + |
| 70 | + putchar(c); |
| 71 | + } while (c != 0); |
| 72 | + |
| 73 | + return 0; |
| 74 | +} |
| 75 | + |
| 76 | +/* Main - Call the ioctl functions */ |
| 77 | +int main(void) |
| 78 | +{ |
| 79 | + int file_desc, ret_val; |
| 80 | + char *msg = "Message passed by ioctl\n"; |
| 81 | + |
| 82 | + file_desc = open(DEVICE_PATH, O_RDWR); |
| 83 | + if (file_desc < 0) { |
| 84 | + printf("Can't open device file: %s, error:%d\n", DEVICE_PATH, |
| 85 | + file_desc); |
| 86 | + exit(EXIT_FAILURE); |
| 87 | + } |
| 88 | + |
| 89 | + ret_val = ioctl_set_msg(file_desc, msg); |
| 90 | + if (ret_val) |
| 91 | + goto error; |
| 92 | + ret_val = ioctl_get_nth_byte(file_desc); |
| 93 | + if (ret_val) |
| 94 | + goto error; |
| 95 | + ret_val = ioctl_get_msg(file_desc); |
| 96 | + if (ret_val) |
| 97 | + goto error; |
| 98 | + |
| 99 | + close(file_desc); |
| 100 | + return 0; |
| 101 | +error: |
| 102 | + close(file_desc); |
| 103 | + exit(EXIT_FAILURE); |
| 104 | +} |
0 commit comments