第一个驱动程序实验

按照书上例程写的体验程序。

驱动程序:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

#include <linux/gpio.h>
#include "ldst.h"

MODULE_LICENSE("Dual BSD/GPL");

#define LDST_MAJOR 230
//#define LIGHT_ON 1
//#define LIGHT_OFF 0
#define DEVICE_NAME "ldst"

int ldst_major = LDST_MAJOR;
// device struct
struct ldst_dev {
	struct cdev cdev;
	unsigned char value; //turn led on or off
};
struct ldst_dev *ldst_devp;

static int ldst_open (struct inode *inode, struct file *filp)
{
	struct ldst_dev *dev;
	dev = container_of(inode->i_cdev, struct ldst_dev, cdev);
	filp->private_data = dev;
	return 0;
}

static int ldst_release (struct inode *inode, struct file *filp)
{
	return 0;
}

ssize_t ldst_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops)
{
	struct ldst_dev *dev = filp->private_data;
	if (copy_to_user(buf,&(dev->value),1))
		return -EFAULT;	
	return 1;
}

ssize_t ldst_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
{
	struct ldst_dev *dev = filp->private_data;
	if (copy_from_user(&(dev->value), buf, 1))
		return -EFAULT;	
	/*if (dev->value == 1)
		light_on();
	else
		light_off();*/
	return 1;
}

long ldst_ioctl (struct file *filp,unsigned int cmd,unsigned long arg)
{
	struct ldst_dev *dev = filp->private_data;
	switch (cmd){
	case LDST_ON:
		dev->value = 1;
		//mt_set_gpio_out(GPIO167,GPIO_OUT_ONE); //light_on();
		printk(KERN_NOTICE "light on\n%d\n",dev->value);
		break;
	case LDST_OFF:
		dev->value = 0;
		//mt_set_gpio_out(GPIO167,GPIO_OUT_ZERO); //light_off();
		printk(KERN_NOTICE "light off\n%d\n",dev->value);
		break;
	default:
		return -ENOTTY;
	}
	return 0;
}

struct file_operations ldst_fops = {
	.owner = THIS_MODULE,
	.read = ldst_read,
	.write = ldst_write,
	.unlocked_ioctl = ldst_ioctl,
	.open = ldst_open,
	.release = ldst_release,
};

static void ldst_setup_cdev(struct ldst_dev *dev, int index)
{
	int err, devno = MKDEV(ldst_major, index);
	cdev_init(&dev->cdev, &ldst_fops);
	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &ldst_fops;
	err = cdev_add(&dev->cdev, devno, 1);
	if (err)
		printk(KERN_NOTICE "Error %d adding LED%d", err, index);
}

int ldst_init(void)
{
	int result;
	dev_t dev = MKDEV(ldst_major, 0);
	if (ldst_major)
		result = register_chrdev_region(dev, 1, "ldst");
	else {
		result = alloc_chrdev_region(&dev, 0, 1, "ldst");
		ldst_major = MAJOR(dev);
	}
	if (result < 0)
		return result;
	printk(DEVICE_NAME"\tinitialized\n");
	ldst_devp = kmalloc(sizeof(struct ldst_dev), GFP_KERNEL);
	if (!ldst_devp) {
		result = -ENOMEM;
		goto fail_malloc;
	}
	memset(ldst_devp, 0, sizeof(struct ldst_dev));
	ldst_setup_cdev(ldst_devp, 0);
	//gpio_init();
	printk(KERN_ALERT "success!\n");
	return 0;
fail_malloc:
	unregister_chrdev(dev, ldst_devp);
	printk(KERN_ALERT "failure!\n");
	return result;
}
	
void ldst_cleanup(void)
{
	cdev_del(&ldst_devp->cdev);
	kfree(ldst_devp);
	unregister_chrdev_region(MKDEV(ldst_major, 0), 1);
}

module_init(ldst_init);
module_exit(ldst_cleanup);

 

自定义头文件:

#include <linux/ioctl.h>
#define LDST_MAGIC 't'
#define LDST_ON    _IOWR(LDST_MAGIC,0x1a,int)
#define LDST_OFF    _IOWR(LDST_MAGIC,0x1b,int)
测试程序:
#include <stdio.h>
//#include "sys/types.h"
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>//read,write等等
//#include "termios.h"
//#include "sys/stat.h"
#include <fcntl.h>

#include "ldst.h"


main(int argc,char *argv[])
{
    int fd;
    char buf[1];
    if ((fd=open("/dev/ldst",O_RDWR /*| O_NDELAY | O_NOCTTY*/)) < 0){
        printf("Open Device  failed.\r\n");
        exit(1);
    }else
    	printf("Open Device  successed.%d\r\n",argc);
    if (argc<3){
        /* code */
        printf("Usage: %s <on|off num>\n",argv[0]);
        exit(1);
    }else
    	printf("%s\n",argv[1]);
    if(read(fd,buf,1)>0)
    	printf("read succeed!!\n%s\n",buf);
    else
    	printf("read err!!\n");
    if(!strcmp(argv[1],"on")){
        printf("led1 will on!!\n");
    	if(ioctl(fd,LDST_ON)<0)
        	printf("ioctl err!!\n");
    	else
 	    	printf("ioctl succeed!!\n");
    }
    if(!strcmp(argv[1],"off")){
        printf("led1 will off!!\n");
        if(ioctl(fd,LDST_OFF)<0)
        	printf("ioctl err!!\n");
        else
 	    	printf("ioctl succeed!!\n");
    }
    //perror(t);
    //if(write(fd,argv[2],1)>0)
    	//printf("write succeed!!\n");
    if(read(fd,buf,1)>0)
    	printf("read succeed!!\n%d\n",*buf);
    else
    	printf("read err!!\n");
    close(fd);
}
   makefile:

ifneq ($(KERNELRELEASE),)
obj-m := ldst.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif

命令行:

make
sudo insmod ldst.ko
sudo mknod /dev/ldst c 230 0
gcc -o test test.c
sudo ./test "off" 0
sudo rm /dev/ldst
sudo rmmod ldst

 

按照书上例程写的体验程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值