使用proc来写GPIO驱动

| 2009年3月31日

这是写的一个gpio的驱动,测试完,提好的。

#include <linux/kernel.h>                                                                                                                                                                                                                                                                                                
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/leds-gpio.h>
#include <asm/io.h>


#define MODULE_NAME "led"
#define MAX_LEN 8


void __iomem *base = NULL;

struct led_stat {
	char name[MAX_LEN + 1];
	char value[MAX_LEN + 1];
	char stat[MAX_LEN];
};

static struct proc_dir_entry *led_dir, *led_file;
struct led_stat led_data;

static int
proc_read_led (char *page, char **stat,
		off_t off, int count, int *eof, void *data)
{
	int len;
	struct led_stat *p_data = (struct led_stat *) data;
	p_data->stat[0] = inb((void *)(base + 4));
	len = sprintf(page, "%02x", p_data->stat[0]);
	return len;
}

static int
proc_write_led (struct file *file,const char *buffer,
		unsigned long count,void *data)
{
	int len;
	char ch;
	struct led_stat *p_data = (struct led_stat *)data;
	if (count < MAX_LEN)
		len = count;
	else
		len = MAX_LEN;
       
	if(copy_from_user(p_data->stat, buffer, len))
		return -EFAULT;
	ch = buffer[0];
	printk("buff 0:%02x buff 1 :%02x\n ch :%02x \n", buffer[0], buffer[1], ch);
	if ((ch <= 0x39) && (ch >= 0x30))
		ch = ch - 0x30;
	else if ((ch <= 0x46) && (ch >= 0x41))
		ch = ch - 0x37;
	else if ((ch <= 0x66) && (ch >= 0x61))
		ch = ch - 0x57;
	else
		ch = 0x0f;
	ch = ch << 4;
	printk("buff kernel:%s ch :%02x\n", buffer, ch);

	outb(ch, (void *)(base + 4));
	return len;
}

static int __init led_proc_init(void)
{
	int rv = 0;

	led_dir = proc_mkdir(MODULE_NAME,NULL);
	if(led_dir == NULL){
		rv = -ENOMEM;
		goto out;
	}
	led_dir->owner = THIS_MODULE;
	led_file = create_proc_entry("led",0666,led_dir);
	if(led_file == NULL){
		rv = -ENOMEM;
		goto no_led;
	}
	strcpy(led_data.name,"led");
	strcpy(led_data.value,"led");
	memset(led_data.stat, '\0', sizeof(led_data.stat));
	led_file->data = &led_data;
	led_file->read_proc = proc_read_led;
	led_file->write_proc = proc_write_led;
	led_file->owner = THIS_MODULE;

	 printk(KERN_INFO "%s initialised\n",MODULE_NAME);
	 return 0;
no_led:
	 remove_proc_entry("led",led_dir);
	 remove_proc_entry(MODULE_NAME,NULL);
out:
	 return rv;
}
static void __exit led_proc_exit(void)
{
	remove_proc_entry("led",led_dir);
	remove_proc_entry(MODULE_NAME,NULL);
}

static int __init led_io_init(void)
{
	base = S3C24XX_GPIO_BASE(S3C2410_GPF4);
	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
	outb(0x00, (void *)(base + 4));
       
	return 0;
}

static void __exit led_io_exit(void)
{
	outb(0xff, (void *)(base + 4));
       
}

static int __init led_init(void)
{
	led_io_init();
	led_proc_init();
       
	return 0;
}

static void __exit led_exit(void)
{
       
	led_proc_exit();
	led_io_exit();

	printk(KERN_INFO "%s removed\n",MODULE_NAME);
       
	return;
}

module_init(led_init);
module_exit(led_exit);

MODULE_AUTHOR("Helight.Xu");
MODULE_LICENSE("Dual BSD/GPL"); 
看完本文有收获?请分享给更多人

关注「黑光技术」,关注大数据+微服务