Chinaunix首页 | 论坛 | 博客
  • 博客访问: 416954
  • 博文数量: 380
  • 博客积分: 75
  • 博客等级: 民兵
  • 技术积分: 1925
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-05 15:35
文章分类

全部博文(380)

文章存档

2014年(1)

2013年(2)

2012年(19)

2011年(358)

我的朋友

分类:

2011-09-05 18:31:50

文件:beep.rar
大小:21KB
下载:下载
尽管在2.6的内核版本已经支持udev,可以很方便的使用,并且使用也很舒服。但是使用udev,在启动过程中扫描/sys/class目录并生成设备节点的时间稍微有点长,在一些系统中是无法忍受的,所以没办法只好放弃udev,回到静态设备节点的时代,以加快启动速度。

2.6内核中,引入了cdev概念,使用cdev的驱动与传统的2.4的字符驱动又不一样,下面给出一个使用cdev和静态设备节点的驱动范例。

beepdrv.c

/* beepdrv.c
    beep driver. GUANGZHOU ZHIYUAN

   Copyright (c) 2009 GUANGZHOU ZHIYUAN ELECTRONICS CO.LTD
   By Chenxibing
*/


#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/cdev.h>

#include <asm/arch/hardware.h>
#include <asm/uaccess.h>
#include <asm/arch/irq.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>

#include <mach/hardware.h>
#include <mach/platform.h>

#include <asm/arch/lpc32xx_gpio.h>

#include "beepdrv.h"

#define DEV_NAME    "beep"
struct cdev *beep_cdev;
#define BEEP_MAJOR 231
#define BEEP_MINOR 0
int beep_major = BEEP_MAJOR;
int beep_minor = BEEP_MINOR;

module_param(beep_major, int, 0);
module_param(beep_minor, int, 0);

#define GPIO_IOBASE io_p2v(GPIO_BASE)

static struct semaphore beep_sem;

static int beep_open(struct inode *inode, struct file *filp)
{
    __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF

    try_module_get(THIS_MODULE);
    printk( KERN_INFO DEV_NAME " opened!\n");
    return 0;
}

static int beep_release(struct inode *inode, struct file *filp)
{
    __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF

    module_put(THIS_MODULE);
    printk(KERN_INFO DEV_NAME " released!\n");
    return 0;
}

static int beep_ioctl(struct inode *inode, struct file *filp,
                        unsigned int cmd, unsigned long arg)
{
     int level;

    if (_IOC_TYPE(cmd) != BEEP_IOC_MAGIC) {
        return -ENOTTY;
    }

    if (_IOC_NR(cmd) >= BEEP_IOC_MAXNR) {
        return -ENOTTY;
    }

//    printk("arg=0x%x\n", arg);



    switch (cmd) {
    case SET_BEEP_ON:
        __raw_writel(_BIT(5), GPIO_P3_OUTP_CLR(GPIO_IOBASE));//CLR GPIO_05

        udelay(10);
        break;
        
    case SET_BEEP_OFF:
        __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05

        udelay(10);
        break;

    default:
        __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05

        break;
    }

    return 0;
}

static struct file_operations beep_fops = {
    .owner = THIS_MODULE,
    .ioctl     = beep_ioctl,
    .open = beep_open,
    .release = beep_release,
};

static void beep_setup_cdev(struct cdev *dev)
{
    int err, devno = MKDEV(beep_major, beep_minor);
            
    cdev_init(dev, &beep_fops);
    dev->owner = THIS_MODULE;
    dev->ops = &beep_fops;
    err = cdev_add (dev, devno, 1);
    /* Fail gracefully if need be */
    if (err)
        printk(KERN_NOTICE "Error %d adding gpio.\n", err);
}

static int __init beep_init(void)
{
    int result;
    printk(DEV_NAME " init starting......\n");

    __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF


    dev_t dev = 0;// MKDEV(gpio_major, 0);

    /*
     * Register your major, and accept a dynamic number.
     */

    if (beep_major)
        result = register_chrdev_region(beep_minor, 1, DEV_NAME);
    else {
        result = alloc_chrdev_region(&dev, 0, 1, DEV_NAME);
        beep_major = MAJOR(dev);
    }
    if (result < 0)
        return result;
 
    beep_cdev = cdev_alloc();
    if (!beep_cdev) {
        result = -ENOMEM;
        goto fail; /* Make this more graceful */
    }
    beep_setup_cdev(&beep_cdev);
    printk(DEV_NAME " registered OK.\n");
    return 0;
fail:
    cdev_del(&beep_cdev);
    unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1);
// beep_exit();

        return result;
}

static int __exit beep_exit(void)
{
    cdev_del(&beep_cdev);
    unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1);
    printk(DEV_NAME " unregistered.\n");
}


module_init(beep_init);
module_exit(beep_exit);

MODULE_AUTHOR("Abing ");
MODULE_DESCRIPTION("ZHIYUAN tp-beep Driver");
MODULE_LICENSE("GPL");


beepdrv.h

#ifndef __BEEPDRV_H
#define __BEEPDRV_H
#include <linux/ioctl.h>

#define BEEP_IOC_MAGIC     'b'

#define SET_BEEP_ON     _IO(BEEP_IOC_MAGIC, 0)
#define SET_BEEP_OFF    _IO(BEEP_IOC_MAGIC, 1)

#define BEEP_IOC_MAXNR    2

#endif //__BEEPDRV_H


阅读(358) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~