Wednesday, November 11, 2015
simple character driver using IOCTL call in linux
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <linux/miscdevice.h>
struct test_ioctl {
int cmd_no;
char data[64];
};
#define SAMPLE_IOCTL_MAGIC_NUMBER 's'
#define SAMPLE_IOCTL_CMD_1 \
_IOR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x1, int)
#define SAMPLE_IOCTL_CMD_2 \
_IOW(SAMPLE_IOCTL_MAGIC_NUMBER, 0x2, int)
#define SAMPLE_IOCTL_CMD_3 \
_IO(SAMPLE_IOCTL_MAGIC_NUMBER, 0x3)
#define SAMPLE_IOCTL_CMD_4 \
_IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x4, struct test_ioctl)
static ssize_t sample_char_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
return count;
}
static ssize_t sample_char_write(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
return count;
}
int sample_char_open(struct inode *inode, struct file *filp)
{
printk("sample_char_open\n");
return 0;
}
int sample_char_release(struct inode *inode, struct file *filp)
{
printk("sample_char_release\n");
return 0;
}
/*
* The ioctl() implementation
*/
int sample_char_ioctl (struct file *filp,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
printk("sample_char_ioctl\n");
switch (cmd) {
case SAMPLE_IOCTL_CMD_1:
printk("IOCTL CMD1\n");
/*Do Something*/
break;
case SAMPLE_IOCTL_CMD_2:
printk("IOCTL CMD2\n");
/*Do Something*/
break;
case SAMPLE_IOCTL_CMD_3:
printk("IOCTL CMD3\n");
/*Do Something*/
break;
case SAMPLE_IOCTL_CMD_4:
printk("IOCTL CMD4\n");
/*Do Something*/
break;
default: /*Default option*/
/*Do Something or return invalid command error*/
printk("Invalid IOCTL CMD\n");
ret = -EINVAL;
}
return ret;
}
static struct file_operations sample_char_fops = {
read: sample_char_read,
write: sample_char_write,
open: sample_char_open,
release: sample_char_release,
unlocked_ioctl: sample_char_ioctl,
};
static struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "sample_misc_dev",
.fops = &sample_char_fops,
.mode = S_IRWXUGO,
};
int major_no;
int init_module(void)
{
int ret = 0;
printk("\nLoading the sample misc char device driver\n");
ret = misc_register(&misc_dev);
if (ret)
printk("Unable to register misc dev\n");
return ret;
}
void cleanup_module(void)
{
printk("\nUnloading the sample char device driver\n");
misc_deregister(&misc_dev);
}
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <linux/miscdevice.h>
struct test_ioctl {
int cmd_no;
char data[64];
};
#define SAMPLE_IOCTL_MAGIC_NUMBER 's'
#define SAMPLE_IOCTL_CMD_1 \
_IOR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x1, int)
#define SAMPLE_IOCTL_CMD_2 \
_IOW(SAMPLE_IOCTL_MAGIC_NUMBER, 0x2, int)
#define SAMPLE_IOCTL_CMD_3 \
_IO(SAMPLE_IOCTL_MAGIC_NUMBER, 0x3)
#define SAMPLE_IOCTL_CMD_4 \
_IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x4, struct test_ioctl)
static ssize_t sample_char_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
return count;
}
static ssize_t sample_char_write(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
return count;
}
int sample_char_open(struct inode *inode, struct file *filp)
{
printk("sample_char_open\n");
return 0;
}
int sample_char_release(struct inode *inode, struct file *filp)
{
printk("sample_char_release\n");
return 0;
}
/*
* The ioctl() implementation
*/
int sample_char_ioctl (struct file *filp,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
printk("sample_char_ioctl\n");
switch (cmd) {
case SAMPLE_IOCTL_CMD_1:
printk("IOCTL CMD1\n");
/*Do Something*/
break;
case SAMPLE_IOCTL_CMD_2:
printk("IOCTL CMD2\n");
/*Do Something*/
break;
case SAMPLE_IOCTL_CMD_3:
printk("IOCTL CMD3\n");
/*Do Something*/
break;
case SAMPLE_IOCTL_CMD_4:
printk("IOCTL CMD4\n");
/*Do Something*/
break;
default: /*Default option*/
/*Do Something or return invalid command error*/
printk("Invalid IOCTL CMD\n");
ret = -EINVAL;
}
return ret;
}
static struct file_operations sample_char_fops = {
read: sample_char_read,
write: sample_char_write,
open: sample_char_open,
release: sample_char_release,
unlocked_ioctl: sample_char_ioctl,
};
static struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "sample_misc_dev",
.fops = &sample_char_fops,
.mode = S_IRWXUGO,
};
int major_no;
int init_module(void)
{
int ret = 0;
printk("\nLoading the sample misc char device driver\n");
ret = misc_register(&misc_dev);
if (ret)
printk("Unable to register misc dev\n");
return ret;
}
void cleanup_module(void)
{
printk("\nUnloading the sample char device driver\n");
misc_deregister(&misc_dev);
}
TEST FILE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
struct test_ioctl {
int cmd_no;
char data[64];
};
#define SAMPLE_IOCTL_MAGIC_NUMBER 's'
#define SAMPLE_IOCTL_CMD_1 \
_IOR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x1, int)
#define SAMPLE_IOCTL_CMD_2 \
_IOW(SAMPLE_IOCTL_MAGIC_NUMBER, 0x2, int)
#define SAMPLE_IOCTL_CMD_3 \
_IO(SAMPLE_IOCTL_MAGIC_NUMBER, 0x3)
#define SAMPLE_IOCTL_CMD_4 \
_IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x4, struct test_ioctl)
int main()
{
int fd, ret = 0, val = 10;
fd = open("/dev/sample_misc_dev", O_RDWR);
printf("file descriptor fd(%d)\n", fd);
if (fd < 0) {
printf("File open error\n");
}
printf("Sending ioctl CMD 3\n");
ret = ioctl(fd, SAMPLE_IOCTL_CMD_3);
printf("ioctl ret val (%d) errno (%d)\n", ret, errno);
perror("IOCTL error: ");
printf("Sending ioctl CMD 2\n");
ret = ioctl(fd, SAMPLE_IOCTL_CMD_2, &val);
printf("ioctl ret val (%d) errno (%d)\n", ret, errno);
perror("IOCTL error: ");
close(fd);
}
Labels:
device driver
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment