嵌入式LINUX驱动学习之5.ioctl字符设备驱动编程(二)内核空间实现代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
struct led_source {
char *name;
unsigned led_num;
};
struct led_source led_info[] = {
{
.name = "LED1",
.led_num = PAD_GPIO_C +12
},
{
.name = "LED2",
.led_num = PAD_GPIO_C +11
},
{
.name = "LED3",
.led_num = PAD_GPIO_C +7
},
{
.name = "LED4",
.led_num = PAD_GPIO_B +26
}
};
long led_ioctl(struct file * file,unsigned int cmd,unsigned long arg){
unsigned long kindex[4] ;
copy_from_user(kindex,arg,4);
switch(cmd){
case LED_ON :
gpio_set_value(led_info[kindex[0]-1].led_num,0);
break;
case LED_OFF :
gpio_set_value(led_info[kindex[0]-1].led_num,1);
break;
case LED_STATE :
led_state(kindex);
copy_to_user(arg,kindex,sizeof(int) *4);
break;
default :
break;
}
}
static struct file_operations fops={
.owner = THIS_MODULE,
.unlocked_ioctl = led_ioctl
};
static dev_t dev_num;
static struct cdev cdev;
static int led_init(void){
int i = 0;
for(; i < ARRAY_SIZE(led_info); i++){
gpio_request(led_info[i].led_num,led_info[i].name);
gpio_direction_output(led_info[i].led_num,1);
}
alloc_chrdev_region(&dev_num,0,4,"led_ioctl_test");
cdev_init(&cdev,&fops);
cdev_add(&cdev,dev_num,4);
return 0;
}
static void led_exit(void){
int i = 0 ;
for(; i< ARRAY_SIZE(led_info);i++){
gpio_set_value(led_info[i].led_num,1);
gpio_free(led_info[i].led_num);
}
cdev_del(&cdev);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");