Aprendizaje del controlador LINUX integrado Programación del controlador del dispositivo de caracteres 5.ioctl (dos) Código de implementación del espacio del kernel

Aprendizaje del controlador LINUX integrado Programación del controlador del dispositivo de caracteres 5.ioctl (dos) Código de implementación del espacio del kernel

#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>
//定LED灯硬件信息
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
    }


};
/*获取每个LED灯的状态,保存到kindex数组内
void led_state(unsigned long kindex[4]){
    int i = 0;
    for(;i < 4;i++){
    kindex[i] = (int ) gpio_get_value(led_info[i].led_num);
    }
}
#define LED_ON    0X100
#define LED_OFF   0X101
#define LED_STATE 0X110
/*
file  : 对应用户空间的fd(文件描述符
cmd   : 对应用户空间的ucmd
arg   : 在用户空间时是地址,内核空间是无符号长整形,
        在执行copy_from_user()函数时,可以将arg看做地址形参
*/
long led_ioctl(struct file * file,unsigned int cmd,unsigned long arg){
    
    
    unsigned long kindex[4] ;//用于保存用用户空间arg地址内的数据
    copy_from_user(kindex,arg,4);
    switch(cmd){
    
    
        case LED_ON :
            gpio_set_value(led_info[kindex[0]-1].led_num,0);
            //        用户空间对灯编号为:1~4                        
            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;
    }
}
//定义ioctl函数操作接口
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){
    
    
    /*申请GPIO资源*/
    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){
    
    
    /*释放GPIO资源*/
    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");


Supongo que te gusta

Origin blog.csdn.net/weixin_47273317/article/details/107848572
Recomendado
Clasificación