Chinaunix首页 | 论坛 | 博客
  • 博客访问: 385908
  • 博文数量: 57
  • 博客积分: 2299
  • 博客等级: 大尉
  • 技术积分: 1109
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-27 23:12
文章分类
文章存档

2011年(4)

2010年(53)

分类: 嵌入式

2010-03-03 23:27:39

程序代码如下:
 

#include <linux/module.h>       /*EXPORT_SYMBOL_GPL ())*/
#include<linux/moduleparam.h>/*module_param(variable,type,perm); */
#include <linux/init.h>/*module_init(init_function); module_exit(cleanup_function); */
#include <linux/kdev_t.h>                            /*dev_t*/
#include <linux/fs.h>/* everything... */
#include <linux/cdev.h> /*struct cdev *cdev_alloc(void); */
#include <linux/device.h>           /*struct class*/
#include <asm/arch/regs-gpio.h>    /*S3C2410_GPB5*/
#include <asm/hardware.h> /* s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)*/
#include<linux/ioctl.h>
#include <asm/uaccess.h>  /* copy_*_user access_ok*/

#include "devleds.h"

static int leds_major, leds_minor = 0;
static struct cdev cdev; //字符设备结构

static struct class *leds_class;
dev_t dev;//设备号

static unsigned long leds_table[] = {        //led的引脚定义表

    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8
};
static unsigned int leds_cfg_table[] = {        //led引脚功能定义表

    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP,
};
static int leds_open(struct inode *inode, struct file *filp)
{
    int i;
//     for(i = 0; i < 4; i++){    //引脚初始化,由于内核在已经初始化过一次,本处不必在初始化,否则得不到结果

//s3c2410_gpio_cfgpin(leds_table[i], leds_cfg_table[i]);//arch/arm/plat-s3c24xx/gpio.c:void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)

    }
    return 0;
}
static int leds_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    int err = 0, i;
    if (_IOC_TYPE(cmd) != LEDS_IOC_MAGIC)
        return -ENOTTY;
    if (_IOC_NR(cmd) > LEDS_IOC_MAXNR)
        return -ENOTTY;
/*
    * the direction is a bitmask, and VERIFY_WRITE catches R/W
    * transfers. `Type' is user-oriented, while
    * access_ok is kernel-oriented, so the concept of "read" and
    * "write" is reversed
 */

    if (_IOC_DIR(cmd) & _IOC_READ)
        err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
    else if (_IOC_DIR(cmd) & _IOC_WRITE)
        err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
    if (err)
        return -EFAULT;
    printk(KERN_WARNING"Here\n");
    switch(cmd)
    {
        case LEDS_IOCRESET:
            for(i = 0; i < 4; i++){
                s3c2410_gpio_setpin(leds_table[i], 1);
            }
            printk(KERN_WARNING"Here\n");
            return 0;
        case LEDS_IOCSON:
            s3c2410_gpio_setpin(leds_table[arg], 0);
            return 0;
        case LEDS_IOCSOFF:
            s3c2410_gpio_setpin(leds_table[arg], 1);
            return 0;
        default:
            return -EINVAL;
    }
    return 0;
}
static struct file_operations leds_fops = {
    .owner = THIS_MODULE,
    .open =     leds_open,
    .ioctl      =     leds_ioctl
};
static int __init leds_init(void)    //模块初始化

{
    int result;
    PDEBUG("Debug Opend!\n"); 我写来测试调试是否打开了的
    
    if (leds_major) {
        dev = MKDEV(leds_major, leds_minor);
        result = register_chrdev_region(dev, 1, DEV_NAME);//此处为静态分配主设备号

    } else {
        result = alloc_chrdev_region(&dev, leds_minor, 1, DEV_NAME);//动态分配主设备号,此设备号为0

        leds_major = MAJOR(dev);//获取主设备号的宏

    }    
    if (result < 0) {
        printk(KERN_WARNING "Leds: can't get major %d\n", leds_major);
        return result;
    }else {
        printk(KERN_WARNING"Registered ok \nLeds_major = %d\n", leds_major);
    }
    
    cdev_init(&cdev, &leds_fops) ;//初始化最先定义的字符设备结构

    cdev.owner = THIS_MODULE;
    cdev.ops = &leds_fops;
    result = cdev_add(&cdev, dev, 1);//通知内核有该结构注册,注意考虑失败

    if(result < 0){
        printk(KERN_WARNING"cdev_add failed!\n");
        return result;
    }
    
    leds_class = class_create(THIS_MODULE, DEV_NAME);//creat自己的设备节点

    if(IS_ERR(leds_class))
    {
        printk(KERN_ALERT"Err:faile in leds_class!\n");
        return -1;
    }
    /*创建设备节点,名字为DEVICE_NAME ,主设备号用上面动态生成的dev*/
    class_device_create(leds_class, NULL, dev, NULL, DEV_NAME);
    printk(KERN_WARNING"Leds Module Initialed!\n");
    return 0;
}
static void __exit leds_exit(void)
{
    int devno = MKDEV(leds_major, leds_minor );
    
    unregister_chrdev_region(devno, 1);//销毁设备号

    cdev_del(&cdev);//销毁字符设备结构

    
    class_device_destroy(leds_class, devno); //销毁注册的类

    class_destroy(leds_class);
    printk(KERN_WARNING"Leds Module exit!\n");
}
module_init(leds_init);
module_exit(leds_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("CHARACTER DEVICE DRVER");
MODULE_AUTHOR();

头文件:

#ifndef _LEDS_H_
#define _LEDS_H_

#define DEV_NAME "gfy_leds"

/* Macros to help debugging */
#undef PDEBUG /* undef it, just in case */
#ifdef LEDS_DEBUG
# ifdef __KERNEL__
     /* This one if debugging is on, and kernel space */
# define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull[kernel]: " fmt, ## args)
# else /* This one for user space */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
#else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif

#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */

#define LEDS_IOC_MAGIC         'k'

#define LEDS_IOCRESET         _IO(LEDS_IOC_MAGIC, 0)
#define LEDS_IOCSON        _IOW(LEDS_IOC_MAGIC, 1, int)
#define LEDS_IOCSOFF        _IOW(LEDS_IOC_MAGIC, 2, int)
#define LEDS_IOC_MAXNR    2
#endif

测试程序在附件里!

文件: leds.tar.gz
大小: 80KB
下载: 下载
阅读(1288) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~