字符設備註冊實例

實驗平臺:s5pv210開發板 + kernel2.6

功能:驅動三顆led,led1 led2,共用一個fops,led3單獨使用一個fops。當open led1/led2 時,led1 和 led2 同時亮,open led3 時, led3亮;release 對應熄滅。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <mach/gpio-bank.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>

#define GPJ0CON    S5PV210_GPJ0CON
#define GPJ0DAT    S5PV210_GPJ0DAT

#define rGPJ0CON   *((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT   *((volatile unsigned int *)GPJ0DAT)

#define LED1_OFF    (1 << 3)
#define LED2_OFF    (1 << 4)
#define LED3_OFF    (1 << 5)

unsigned int  major_led1,major_led2;
struct cdev led1;
struct cdev led2;


static int led_01_open(struct inode *inode, struct file *file)
{
    rGPJ0DAT &= ~(LED1_OFF | LED2_OFF);

    return 0;
}
static int led_01_release(struct inode *inode, struct file *file)
{
    rGPJ0DAT |= (LED1_OFF | LED2_OFF);
    return 0;
}

struct file_operations led_01_fops = {
    .open    = led_01_open,
    .release = led_01_release,
};

static int lll_open(struct inode *inode, struct file *file)
{
    rGPJ0DAT &= ~LED3_OFF;

    return 0;
}
static int lll_release(struct inode *inode, struct file *file)
{
     rGPJ0DAT |= LED3_OFF;
    return 0;
}

struct file_operations lll_fops = {
    .open    = lll_open,
    .release = lll_release,
};


int led_gpio_init(void)
{
    rGPJ0CON &= ~((0xff << 12) | (0xff << 16) | (0xff << 20)); //clear
    rGPJ0CON |= ((1 << 12) | (1 << 16) | (1 << 20));           // set as output

    rGPJ0DAT |= (LED1_OFF | LED2_OFF | LED3_OFF);     //set all leds off

    return 0;
}


int led_register(struct cdev *led, unsigned int *major, unsigned count,const char *name,struct file_operations *led_fops)
{
    int err;
    err = alloc_chrdev_region(major, 0, count, name);
    if (err)
        goto err1;
    
    cdev_init(led, led_fops);
    err = cdev_add(led, *major, count);
    if (err)
        goto err2;


    return 0;

err2:
    cdev_del(&led1);
    unregister_chrdev_region(major_led1, 2);
err1:
    return err;

}


int __init hello_init(void)
{
    int ret;


    led_gpio_init();    
    ret = led_register(&led1, &major_led1, 2,"led_01",&led_01_fops);
    if (ret)
        return ret;    
    ret = led_register(&led2, &major_led2, 1,"led_03",&lll_fops) ; 

    return ret;     


}

void __exit hello_exit(void)
{
    printk("hello exit\n");

    cdev_del(&led1);
    cdev_del(&led2);

    unregister_chrdev_region(major_led2, 1);
    unregister_chrdev_region(major_led1, 2);
}

module_init(hello_init);
module_exit(hello_exit);


MODULE_LICENSE("GPL");

測試函數

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>




int main(int argc, char const *argv[])
{
	int fd;

	if (2 != argc)
	{
		printf("usag:%s <device name>\n", argv[0]);
		printf("Eg: %s /dev/led1\n", argv[0]);
		return -1;
	}

	fd = open(argv[1], O_RDWR);
	if(0 > fd) {
		printf("open device %s fail\n", argv[1]);
		perror("open");
		return -1;
	}

	sleep(5);

	close(fd);

	return 0;
}

 

接下來將實現設備節點自動創建、在/sys目錄下創建文件夾並添加文件。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章