现在的位置: 首页 > 综合 > 正文

ERROR: “parport_release” [drivers/char/led.ko] undefined!

2013年08月30日 ⁄ 综合 ⁄ 共 3314字 ⁄ 字号 评论关闭

          接触Linux 、 Android两年了!学会了好多!但是没有精通的!对自己的实力没有自信!所以最近专心研究Linux的驱动!练习练习!以前看过很多书!但是看过就忘记了!知道个大概!应该包含哪些头文件都不知道!刚开始先抄抄代码、仔细理解理解!一动手才发现!看到的和你用手打出来那差距不是一般的大!打出来和自己写出来那差距更是天上地下!一下代码出自《精通Linux设备驱动程序开发》,在pandaboard开发板上面测试;内核版本是:Kernel 3.0.31;

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/parport.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>

#define DEVICE_NAME "led"

static dev_t dev_number;        //Allotted device number
static struct class *led_class; //Class to which this device belongs 
struct cdev led_cdev;       //Associated cdev
struct pardevice *pdev;     //Parallel port device

//LED OPEN
int led_open(struct inode *inode, struct file *filp)
{
    return 0;
}

//write to the led
ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
    char kbuf;
    if(copy_from_user(&kbuf, buf, 1))
    {
        return -EFAULT;
    }

    //Claim the port
    parport_claim_or_block(pdev);

    //Write to the device
    parport_write_data(pdev->port, kbuf);

    //Release the port
    parport_release(pdev);

    return count;
}

//Release the device
int led_release(struct inode *inode, struct file *file)
{
    return 0;
}

static struct file_operations led_fops = {
    .owner  = THIS_MODULE,
    .open   = led_open,
    .write  = led_write,
    .release =led_release,
};

static int led_preempt(void *handle)
{
    return 1;
}

//Parport attach method
static void led_attach(struct Parport *port)
{
    /* Register the parallel LED device with parport */
    pdev = parport_register_device(port, DEVICE_NAME, led_preempt, NULL, NULL, 0, NULL);
    if(pdev == NULL)
    {
        printk("Bad register\n");
    }
}

//Parport detach method
static void led_detach(struct parport *port)
{
    printk(".............led_detach................\n");
}

//Parport driver operation
static struct parport_driver led_driver = {
    .name   = "led",
    .attach = led_attach,
    .detach = led_detach,
};

int __init led_init(void)
{
    if(alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME) < 0)
    {
        printk(KERN_DEBUG "Can't register device\n");
        return -1;
    }

    //Create the led class
    led_class = class_create(THIS_MODULE, DEVICE_NAME);
    if(IS_ERR(led_class)){
        printk("Bad class create\n");
    }

    //Connect the file operation with the cdev
    cdev_init(&led_cdev, &led_fops);
    led_cdev.owner = THIS_MODULE;

    //Connect the major/minor number to the cdev
    if(cdev_add(&led_cdev, dev_number, 1)){
        printk("Bad cdev add\n");
        return 1;
    }

     device_create(led_class, NULL, dev_number, NULL, DEVICE_NAME);

    //Register this driver with parport
    if(parport_register_driver(&led_driver))
    {
        printk(KERN_ERR "Bad parport Register \n");
        return -EIO;
    }

    printk("LED Driver Initialized.\n");
    return 0;
}

void __exit led_cleanup(void)
{
    unregister_chrdev_region(dev_number, 1);
    device_destroy(led_class, dev_number);
    class_destroy(led_class);
    return;
}

module_init(led_init);
module_exit(led_cleanup);

MODULE_LICENSE("GPL");

 

Note:

(1)linux内核2.6早期版本的class_device_create()函数在后期的版本中改为了device_create();我用的内核是:kernel 3.0.31;

     => include/linux/device.h

          => struct class {

          => #define class_create(owner, name)

          => extern struct device *device_create(struct class *cls, struct device *parent,
        dev_t devt, void *drvdata,
        const char *fmt, ...)
        __attribute__((format(printf, 5, 6)));

 

    =>  include/linux/cdev.h

          

/*
 *字符设备驱动程序是由一个cdev结构描述的;
 */
struct cdev {
	struct kobject kobj;
	struct module *owner;

	/*指向设备驱动程序"文件操作表"的指针*/
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;						/*设备号*/
	unsigned int count;				/*设备号的大小*/
};

//把内核字符设备和文件操作绑定在一起
void cdev_init(struct cdev *, const struct file_operations *);

//把内核字符设备和设备号绑定在一起
int cdev_add(struct cdev *, dev_t, unsigned);

(2)

       

 

测试结果:

           (1)

                  

          (2)

                  

            (3)

                  

 

抱歉!评论已关闭.