⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 led_struct_driver.c

📁 此代码为上传的源码为ARM9 s3c2410的键盘驱动,读者可编应用程序进行测试
💻 C
字号:
#include <linux/module.h>
#include <linux/moduleparam.h>
//包含有可装载模块需要的大量符合和函数的定义;
#include <linux/init.h>
//指定初始化和清除函数;
//
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <linux/sched.h>

#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>

#include <linux/delay.h>

//定义设备名称
#define DEVICE_NAME "s3c2410_led"

void LedDisp(int led);
static void led_init(void);
//定义主次设备号
static unsigned int LedMajor=0;
static unsigned int LedMinor=0;

module_param(LedMajor,int, 0);
module_param( LedMinor,int, 0);

struct led_dev {
	unsigned int led_gpio[4]; /* gpio used for led */
	int led_status[4];       /* led stauts */
	struct semaphore sem;     /* mutual exclusion semaphore     */	struct cdev cdev;	  /* Char device structure		*/};

struct led_dev * s3c2410_led;	/* allocated in init_module */



//定义与绑定tasklet函数void led_tasklet_action(unsigned long t);DECLARE_TASKLET(led_tasklet, led_tasklet_action, 0);void led_tasklet_action(unsigned long t){	int i,j;
	printk("<1>led taskled action\n");
	for(i = 0; i < 10; i++){
		for(j = 0; j < 4; j++ ) {
			LedDisp(j);
			mdelay(100); 
		}
	}
	led_init();
}

static void led_timer_handler(unsigned long data)
{
	printk("<1>Update Led status!\n");
	led_tasklet_action(data);
}
static struct timer_list s3c2410_led_timer = {
	.function = led_timer_handler,
};
void LedDisp(int led){
	//int tmp;
	printk ("<1>led dslp led = %d\n",led);
	if(0==led){
		s3c2410_gpio_setpin(S3C2410_GPF4,1);
		s3c2410_gpio_setpin(S3C2410_GPF5,1);
		s3c2410_gpio_setpin(S3C2410_GPF6,1);
		s3c2410_gpio_setpin(S3C2410_GPF7,1);		
	}
	else if(led==1)
	{
		s3c2410_gpio_setpin(S3C2410_GPF4,0);
		s3c2410_gpio_setpin(S3C2410_GPF5,1);
		s3c2410_gpio_setpin(S3C2410_GPF6,1);
		s3c2410_gpio_setpin(S3C2410_GPF7,1);
		
	//	printk("1 GPF4DAT = 0x%lx\n", s3c2410_gpio_getpin(S3C2410_GPF4));
	}
	else if(led==2)
	{
		s3c2410_gpio_setpin(S3C2410_GPF4,1);
		s3c2410_gpio_setpin(S3C2410_GPF5,0);
		s3c2410_gpio_setpin(S3C2410_GPF6,1);
		s3c2410_gpio_setpin(S3C2410_GPF7,1);
		
	//	printk("1 GPF5DAT = 0x%lx\n", s3c2410_gpio_getpin(S3C2410_GPF5));
	}
	else if(led==3)
	{
		s3c2410_gpio_setpin(S3C2410_GPF4,1);
		s3c2410_gpio_setpin(S3C2410_GPF5,1);
		s3c2410_gpio_setpin(S3C2410_GPF6,0);
		s3c2410_gpio_setpin(S3C2410_GPF7,1);
		
	//	printk("1 GPF6DAT = 0x%lx\n", s3c2410_gpio_getpin(S3C2410_GPF6));
	}
	else if(led==4)
	{
		s3c2410_gpio_setpin(S3C2410_GPF4,1);
		s3c2410_gpio_setpin(S3C2410_GPF5,1);
		s3c2410_gpio_setpin(S3C2410_GPF6,1);
		s3c2410_gpio_setpin(S3C2410_GPF7,0);
		
	//	printk("1 GPF7DAT = 0x%lx\n", s3c2410_gpio_getpin(S3C2410_GPF7));
	}
	printk("<1>...");
}

static void led_init(void)
{
	int i;
	for (i = 0; i < 4; i++) {
		s3c2410_led->led_status[i] = 1;
		s3c2410_gpio_setpin(s3c2410_led->led_gpio[i],s3c2410_led->led_status[i]);	
	}	
}
static void UpdateLed(void)
{
	int i;
	for (i = 0; i < 4; i++) {
		s3c2410_gpio_setpin(s3c2410_led->led_gpio[i],s3c2410_led->led_status[i]);	
	}
}

static int s3c2410_led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	struct led_dev *dev ;
	
	printk("led- ioctl: param %u %lu\n", cmd, arg);

	dev = filp->private_data;
	
	switch(cmd)
	{
		case 1: 
		case 2: 
		case 3: 
		case 4: 
			led_init();
			dev->led_status[cmd -1] = arg;
			UpdateLed( );
			break;
		case 5: 
			tasklet_schedule(&led_tasklet);
			break;
		case 6:
			init_timer(&s3c2410_led_timer);
			s3c2410_led_timer.function = led_timer_handler;
			s3c2410_led_timer.expires = jiffies + HZ;
			add_timer(&s3c2410_led_timer);
		default :break;	
	}
	return 0;
}

static ssize_t s3c2410_led_write(struct file *filp, const char *buffer, size_t count, loff_t *ppos)
{

//	int led_status = 0;
	struct led_dev *dev ;
	dev = filp->private_data;
	ssize_t retval = -ENOMEM; /* value used in "goto out" statements */	
	if(down_interruptible(&s3c2410_led->sem)) 
		return -ERESTARTSYS;
	
	//copy_from_user(s3c2410_led->led_status, buffer, sizeof(s3c2410_led->led_status));
	if (copy_from_user(dev->led_status, buffer, sizeof(s3c2410_led->led_status))) {
		retval = -EFAULT;		goto out;	}	
	UpdateLed( );
	retval = sizeof(s3c2410_led->led_status);
out:	
	up(&s3c2410_led->sem);
	return retval;
}


static int s3c2410_led_open(struct inode *inode, struct file *filp)
{
/*
	unsigned m = iminor(inode);
 	if (m > 63)
 		return -EINVAL;
*/	
 	printk("<1>LED driver opened!\n");

	struct led_dev *dev; /* device information */
	dev = container_of(inode->i_cdev, struct led_dev, cdev);
	filp->private_data = dev; /* for other methods */	return 0;          // success 
//	return nonseekable_open(inode, file);
}

static int s3c2410_led_release(struct inode *inode, struct file *file)
{
 	printk("LED driver released!\n");
 	return 0;
}

static struct file_operations s3c2410_fops = {
//	owner:	THIS_MODULE,
	open:	s3c2410_led_open,
	ioctl:	s3c2410_led_ioctl,
	write:	s3c2410_led_write,
	release: s3c2410_led_release,
};

static void led_hardware_init(void)
{
	s3c2410_gpio_cfgpin(S3C2410_GPF4,S3C2410_GPF4_OUTP);
	s3c2410_gpio_pullup(S3C2410_GPF4,1);
	s3c2410_gpio_setpin(S3C2410_GPF4,1);
	s3c2410_gpio_cfgpin(S3C2410_GPF5,S3C2410_GPF5_OUTP);
	s3c2410_gpio_pullup(S3C2410_GPF5,1);
	s3c2410_gpio_setpin(S3C2410_GPF5,1);
	s3c2410_gpio_cfgpin(S3C2410_GPF6,S3C2410_GPF6_OUTP);
	s3c2410_gpio_pullup(S3C2410_GPF6,1);
	s3c2410_gpio_setpin(S3C2410_GPF6,1);
	s3c2410_gpio_cfgpin(S3C2410_GPF7,S3C2410_GPF7_OUTP);
	s3c2410_gpio_pullup(S3C2410_GPF7,1);
	s3c2410_gpio_setpin(S3C2410_GPF7,1);
}

/* 模块卸载函数 */
static void s3c2410_led_exit(void)
{
	/* Get rid of our char dev entries */
	if (s3c2410_led) {
		cdev_del(&s3c2410_led->cdev);
		kfree(s3c2410_led);
	}
	
	unregister_chrdev_region(MKDEV(LedMajor,LedMinor),1);
	//cdev_del(led_cdev);
/*
#ifdef CONFIG_DEVFS_FS
	devfs_remove(DEVICE_NAME);
#endif
*/
}

static int __init s3c2410_led_init(void)
{
	int result = 0;
/*分配设备编号*/
	dev_t dev;
	if(LedMajor)
	{
		dev=MKDEV(LedMajor,LedMinor);//创建设备编号
		result=register_chrdev_region(dev,1,DEVICE_NAME);
	} else {
		result=alloc_chrdev_region(&dev,LedMinor,1,DEVICE_NAME);
		LedMajor=MAJOR(dev);
	}
	if(result<0)
	{
		printk(KERN_WARNING"LED: cannot get major %d \n",LedMajor);
		return result;
	}

        /* 	 * allocate the devices -- we can't have them static, as the number	 * can be specified at load time	 */
	 //led_dev_struct_init( );
	s3c2410_led = kmalloc(sizeof(struct led_dev), GFP_KERNEL);
	if (!s3c2410_led) {
		result = -ENOMEM;		goto fail;  /* Make this more graceful */	}	memset(s3c2410_led, 0, sizeof(struct led_dev));

	s3c2410_led->led_gpio[0] = S3C2410_GPF4;
	s3c2410_led->led_gpio[1] = S3C2410_GPF5;
	s3c2410_led->led_gpio[2] = S3C2410_GPF6;
	s3c2410_led->led_gpio[3] = S3C2410_GPF7;
	
	int i;
	for(i = 0; i < 4; i++) {
		s3c2410_led->led_status[i]= 1;
	}
       /* Initialize  device. */	init_MUTEX(&s3c2410_led->sem);

	/* 注册字符设备 */
	//s3c2410_led->cdev = cdev_alloc();
	cdev_init(&s3c2410_led->cdev,&s3c2410_fops);
	//s3c2410_led->cdev->ops=&s3c2410_fops;
	s3c2410_led->cdev.owner=THIS_MODULE;
	result=cdev_add(&s3c2410_led->cdev,dev,1);
	if(result) {
		printk("<1>Error %d while register led device!\n",result);
		goto fail;
	}
	/*init led hardware*/
	led_hardware_init( );
/*	
#ifdef CONFIG_DEVFS_FS
	devfs_mk_cdev(MKDEV(LedMajor,LedMinor),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);
#endif
*/
	return result;
fail:
	s3c2410_led_exit();
	return result;

}

module_init(s3c2410_led_init);
module_exit(s3c2410_led_exit);
EXPORT_SYMBOL(LedDisp);MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Teacher liang");
MODULE_DESCRIPTION("s3c2410 led driver!");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -