?? led_struct_driver.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 + -