按照书上例程写的体验程序。
驱动程序:
#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
按照书上例程写的体验程序。