• «
  • 1
  • 2
  • »
  • Pages: 1/2     Go
主题 : 驱动中关于异步通知出现的一个语法错误 复制链接 | 浏览器收藏 | 打印
级别: 骑士
UID: 4234
精华: 0
发帖: 152
金钱: 1420 两
威望: 1142 点
综合积分: 304 分
注册时间: 2009-03-05
最后登录: 2012-08-18
楼主  发表于: 2009-08-25 19:35

 驱动中关于异步通知出现的一个语法错误

最近我在学一下驱动,但今天我遇到一个问题,我是用button的驱动为蓝本实现异步通知的功能,但编译的时候始终是报一个错误,我是参照一本书的例子程序改出来的,请哪位大侠帮忙看看,是哪里的问题,出现错误的地方和错误信息我都在代码对应的地方加了注释。具体代码如下:
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/hardware.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm-arm/arch-s3c2410/regs-gpio.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm-arm/arch-s3c2410/irqs.h>
#include <asm-arm/irq.h>
#include <linux/interrupt.h>
#include <asm/string.h>
#include <linux/wait.h>
#include <linux/cdev.h>
struct button_irq_desc {
int irq;
unsigned long flags;
char *name;
};
static struct button_irq_desc button_irqs [] = {
{IRQ_EINT8, IRQF_TRIGGER_FALLING, "KEY1"}, /* K1 */
{IRQ_EINT11, IRQF_TRIGGER_FALLING, "KEY2"}, /* K2 */
{IRQ_EINT13, IRQF_TRIGGER_FALLING, "KEY3"}, /* K3 */
{IRQ_EINT14, IRQF_TRIGGER_FALLING, "KEY4"}, /* K4 */
{IRQ_EINT15, IRQF_TRIGGER_FALLING, "KEY5"},
{IRQ_EINT19, IRQF_TRIGGER_FALLING, "KEY6"},
};
#define DEVICE_NAME "buttons"
#define BUTTONMINOR 0
#define MAX_BUTTON_BUF 16
#define NOKEY 0
static int buttonMajor=232;
static unsigned char buttonRead(void);
static int flag=0;
typedef struct {
unsigned int buttonStatus;
unsigned char buf[MAX_BUTTON_BUF];
unsigned int head,tail;
wait_queue_head_t wq;
struct fasync_struct *async_queue;
struct cdev cdev;
} BUTTON_DEV;

static BUTTON_DEV buttondev;
#define BUF_HEAD (buttondev.buf[buttondev.head])
#define BUF_TAIL (buttondev.buf[buttondev.tail])
#define INCBUF(x,mod) ((++(x)) & ((mod)-1))
static void delay(int n)
{
long int t;

t=n*100;
while(t > 0)
{
t--;
}
}
static irqreturn_t isr_button(int irq,void *dev_id,struct pt_regs *regs)
{
int i;

for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
if(irq==button_irqs.irq)
{
buttondev.head=INCBUF(buttondev.head,MAX_BUTTON_BUF);
BUF_HEAD=i;
flag=1;
wake_up_interruptible(&(buttondev.wq));
break;
}
}
return 0;
}

static int button_open(struct inode *inode,struct file *filp)
{
int ret,i;
filp->private_data=&buttondev;
buttondev.head=buttondev.tail=0;

for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)

{
ret=request_irq(button_irqs.irq,isr_button,IRQF_TRIGGER_FALLING,DEVICE_NAME,NULL);
if(ret)
{
printk("BUTTON_IRQ: could not register interrupt\n");
break;
}
}
if(ret)
{
for(;i>=0;i--)
free_irq(button_irqs.irq,NULL);
return ret;
}

else
return 0;
}
static int button_fasync(int fb,struct file *filp,int mode)
{
struct BUTTON_DEV *dev=filp->private_data;
return fasync_helper(fb,filp,mode,&dev->async_queue);//这里出现了错误,错误提示为:error: dereferencing pointer to
// incomplete type
}
static int button_release(struct inode *inode,struct file *filp)
{
int i;
// struct BUTTON_DEV *dev=filp->private_data;
button_fasync( - 1, filp, 0);
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
free_irq(button_irqs.irq,NULL);
}
return 0;
}

static unsigned char buttonRead(void)
{
unsigned char button_ret;
button_ret=BUF_TAIL;
buttondev.tail=INCBUF(buttondev.tail,MAX_BUTTON_BUF);
return button_ret;
}

static ssize_t button_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)
{
static unsigned char button_ret;
struct BUTTON_DEV *dev=filp->private_data;
retry:
if(buttondev.head!=buttondev.tail)
{
button_ret=buttonRead();
copy_to_user(buffer,(char *)&button_ret,sizeof(unsigned char));
printk("the button_ret is %x\n",button_ret);
return sizeof(unsigned char);
}
else
{
wait_event_interruptible(buttondev.wq,flag);
if(dev->async_queue)//这里也是一样的错误
kill_fasync(&dev->asycn_queue,SIGIO,POLL_IN);//还有这里也是

flag=0;
goto retry;
}
}

static struct file_operations button_fops= {
.owner = THIS_MODULE,
.open = button_open,
.read = button_read,
.fasync = button_fasync,
.release= button_release,

};

static int __init s3c2410_buttons_init(void)
{
int ret, err,i;
dev_t dev = MKDEV(buttonMajor, 0);
for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
set_irq_type(button_irqs.irq,IRQT_FALLING);
}
if (buttonMajor)
ret = register_chrdev_region(dev, 1, DEVICE_NAME);
else
{
ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
buttonMajor = MAJOR(dev);
}
if (ret < 0)
return ret;

cdev_init(&buttondev.cdev, &button_fops);
buttondev.cdev.owner = THIS_MODULE;
buttondev.cdev.ops = &button_fops;
err = cdev_add (&buttondev.cdev, dev, 1);
if (err)
printk(KERN_NOTICE "Error %d adding button", err);

buttondev.buttonStatus=NOKEY;
init_waitqueue_head(&(buttondev.wq));
printk(DEVICE_NAME "initialized\n");
return 0;
}

static void __exit s3c2410_buttons_exit(void)
{
cdev_del(&buttondev.cdev);
unregister_chrdev_region(MKDEV (buttonMajor, 0), 1);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mike Lee");
MODULE_DESCRIPTION ("The buttons char device driver");

module_init(s3c2410_buttons_init);
module_exit(s3c2410_buttons_exit);
Just do it
级别: 侠客
UID: 2754
精华: 4
发帖: 66
金钱: 2435 两
威望: 873 点
综合积分: 212 分
注册时间: 2008-12-07
最后登录: 2016-04-13
1楼  发表于: 2009-08-25 20:27
由于内核版本变化了,所有内核API以及数据结构也发生了变化,在发帖之前请指明你的内核版本,参照我的一个帖子
http://blog.chinaunix.net/u2/69999/showart.php?id=1986143
级别: 骑士
UID: 4234
精华: 0
发帖: 152
金钱: 1420 两
威望: 1142 点
综合积分: 304 分
注册时间: 2009-03-05
最后登录: 2012-08-18
2楼  发表于: 2009-08-26 10:30
谢谢师兄,我先看看你的帖子,我的内核版本是2.6.22.6
级别: 骑士
UID: 4234
精华: 0
发帖: 152
金钱: 1420 两
威望: 1142 点
综合积分: 304 分
注册时间: 2009-03-05
最后登录: 2012-08-18
3楼  发表于: 2009-08-26 21:52

 回 1楼(jeefjiang) 的帖子

这位师兄,你的程序我看了,但还是有个地方没有明白
你在minibtb_open中用的
          struct button_dev  *dev; /* device information */
    dev = container_of(inode->i_cdev, struct button_dev,button_cdev);
    filp->private_data = dev; /* for other methods */
这几句我不是很明白,我的理解是filp->private_data 并不是指向自己定义的button_dev结构体,而是该结构体变量static struct button_dev btn_dev,这样才和minibtn_fasync函数、minibtn_poll函数以及minibtn_read函数中button_dev *dev = filp->private_data保持一致,我的理解是在这里将
filp->private_data看错一个全局的中间变量,来实现设备结构体变量的传递,不知道我理解的是不是对,所以我对你的用法不是很理解,能帮忙解释下吗?
级别: 新手上路
UID: 2193
精华: 0
发帖: 15
金钱: 140 两
威望: 44 点
综合积分: 30 分
注册时间: 2008-11-01
最后登录: 2012-03-19
4楼  发表于: 2009-08-26 22:30
仔细看自己的数据结构
typedef struct {
unsigned int buttonStatus;
unsigned char buf[MAX_BUTTON_BUF];
unsigned int head,tail;
wait_queue_head_t wq;
struct fasync_struct *async_queue;
struct cdev cdev;
} BUTTON_DEV

struct fasync_struct *async_queue;这个已经是指针了,你还对它取地址?得到什么东西?直接dev->async_queue就行了。。
级别: 骑士
UID: 4234
精华: 0
发帖: 152
金钱: 1420 两
威望: 1142 点
综合积分: 304 分
注册时间: 2009-03-05
最后登录: 2012-08-18
5楼  发表于: 2009-08-26 22:37

 回 4楼(mini2440) 的帖子

谢谢师兄的回复,我会再去好好理解下这个东西,不过我还是有2个疑问:第一:fasync_helper函数原型中的第三个参数是前是两个*,这样我是不是要在这加取地址?
第二:如果我在fasync_helper上用错了,但if(dev->async_queue)和kill_fasync(&dev->asycn_queue,SIGIO,POLL_IN);不应该错啊,其实这两个错误是一样的,但还是报同一个错误,不理解!
级别: 新手上路
UID: 2193
精华: 0
发帖: 15
金钱: 140 两
威望: 44 点
综合积分: 30 分
注册时间: 2008-11-01
最后登录: 2012-03-19
6楼  发表于: 2009-08-26 22:51
如果是2个*那么就需要加取地址符号。。那么你看看内核离得的API原型是什么样的。
级别: 新手上路
UID: 2193
精华: 0
发帖: 15
金钱: 140 两
威望: 44 点
综合积分: 30 分
注册时间: 2008-11-01
最后登录: 2012-03-19
7楼  发表于: 2009-08-27 12:51
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>

#define button_major 0
#define button_minor 0
typedef struct{
    struct cdev cdev;
    struct fasync_struct *async_queue;
}button_dev;
dev_t devno=0;
button_dev *button;
struct button_irq_desc {
    int irq;
    int pin;
    int pin_setting;
    int number;
    char *name;    
};

#if !defined (CONFIG_QQ2440_BUTTONS)
static struct button_irq_desc button_irqs [] = {
    {IRQ_EINT8 , S3C2410_GPG0 ,  S3C2410_GPG0_EINT8  , 0, "KEY0"},
    {IRQ_EINT11, S3C2410_GPG3 ,  S3C2410_GPG3_EINT11 , 1, "KEY1"},
    {IRQ_EINT13, S3C2410_GPG5 ,  S3C2410_GPG5_EINT13 , 2, "KEY2"},
    {IRQ_EINT15, S3C2410_GPG7 ,  S3C2410_GPG7_EINT15 , 3, "KEY3"},
    {IRQ_EINT14, S3C2410_GPG6 ,  S3C2410_GPG6_EINT14 , 4, "KEY4"},
    {IRQ_EINT19, S3C2410_GPG11,  S3C2410_GPG11_EINT19, 5, "KEY5"},
};
#else /* means QQ */
static struct button_irq_desc button_irqs [] = {
    {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 0, "KEY0"},
    {IRQ_EINT11, S3C2410_GPG3,  S3C2410_GPG3_EINT11,  1, "KEY1"},
    {IRQ_EINT2,  S3C2410_GPF2,  S3C2410_GPF2_EINT2,   2, "KEY2"},
    {IRQ_EINT0,  S3C2410_GPF0,  S3C2410_GPF0_EINT0,   3, "KEY3"},
    {       -1,            -1,                 -1,    4, "KEY4"},
    {       -1,            -1,                 -1,    5, "KEY5"},
};
#endif
static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};

//static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

//static volatile int ev_press = 0;


static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
    struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
    int down;

    // udelay(0);
    down = !s3c2410_gpio_getpin(button_irqs->pin);

    if (down != (key_values[button_irqs->number] & 1)) { // Changed

    key_values[button_irqs->number] = '0' + down;
    if(button->async_queue)
        kill_fasync(&button->async_queue,SIGIO,POLL_IN);
        //ev_press = 1;
       // wake_up_interruptible(&button_waitq);
    }
    
    return IRQ_RETVAL(IRQ_HANDLED);
}


static int s3c24xx_buttons_open(struct inode *inode, struct file *filp)
{
    int i;
    int err;
    button_dev *dev; /* device information */
    dev = container_of(inode->i_cdev, button_dev, cdev);
    filp->private_data = dev; /* for other methods */
    for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
    if (button_irqs.irq < 0) {
        continue;
    }
        err = request_irq(button_irqs.irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,
                          button_irqs.name, (void *)&button_irqs);
        if (err)
            break;
    }

    if (err) {
        i--;
        for (; i >= 0; i--) {
        if (button_irqs.irq < 0) {
        continue;
        }
        disable_irq(button_irqs.irq);
            free_irq(button_irqs.irq, (void *)&button_irqs);
        }
        return -EBUSY;
    }

//   ev_press = 1;
    
    return 0;
}
static int s3c24xx_buttons_fasync(int fd,struct file *filp,int mode)
{
    button_dev *dev=filp->private_data;
    return fasync_helper(fd,filp,mode,&dev->async_queue);
}

static int s3c24xx_buttons_close(struct inode *inode, struct file *filp)
{
    int i;
    
    for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
    if (button_irqs.irq < 0) {
        continue;
    }
    free_irq(button_irqs.irq, (void *)&button_irqs);
    }
    s3c24xx_buttons_fasync(-1,filp,0);
    return 0;
}


static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
    unsigned long err;
/*
    if (!ev_press) {
    if (filp->f_flags & O_NONBLOCK)
        return -EAGAIN;
    else
        wait_event_interruptible(button_waitq, ev_press);
    }
    
    ev_press = 0;
*/
    err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));

    return err ? -EFAULT : min(sizeof(key_values), count);
}

static struct file_operations dev_fops = {
    .owner   =   THIS_MODULE,
    .open    =   s3c24xx_buttons_open,
    .release =   s3c24xx_buttons_close,
    .read    =   s3c24xx_buttons_read,
    .fasync  =   s3c24xx_buttons_fasync,
};



static int __init dev_init(void)
{
    int ret,err;
    ret=alloc_chrdev_region(&devno,button_minor,1,"buttons");
    //button_major=MAJOR(devno);
    if(ret<0)
    {
        printk(KERN_ALERT "BUTTON device num ERROR\n");
        return ret;
    }
    button=kmalloc(sizeof(button_dev),GFP_KERNEL);
    if(!button)
    {        
        printk(KERN_ALERT "BUTTON MALLOC ERROR\n");
        return 1;
    }
    cdev_init(&button->cdev,&dev_fops);
    button->cdev.owner=THIS_MODULE;
    err=cdev_add(&button->cdev,devno,1);
    if(err)
        printk(KERN_ALERT "cdev add ERROR\n");
    return ret;
}

static void __exit dev_exit(void)
{
    unregister_chrdev_region(devno,1);
    kfree(button);
    cdev_del(&button->cdev);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");

这个是我拿友善的驱动改的可以用异步通知的,你看看吧。
级别: 骑士
UID: 4234
精华: 0
发帖: 152
金钱: 1420 两
威望: 1142 点
综合积分: 304 分
注册时间: 2009-03-05
最后登录: 2012-08-18
8楼  发表于: 2009-08-29 09:12
我找到问题所在了,主要还是语法的一个错误,typedef 的定义搞错了,我把结构体定义中前面的typedef 去掉,并在static button_dev *button;前面加个struct就可以了,谢谢各位师兄的帮助。不过目前我的还没有完全实现,因为虽然驱动已经编译成功了,但测试程序运行起来还是有错误,我自己再看看,如果找不到问题,还要找师兄们帮忙!小崔在这里先谢谢大家了!
级别: 骑士
UID: 4234
精华: 0
发帖: 152
金钱: 1420 两
威望: 1142 点
综合积分: 304 分
注册时间: 2009-03-05
最后登录: 2012-08-18
9楼  发表于: 2009-08-29 09:16
我现在已经逐步的用button的驱动对队列,定时器进行了编译理解,下面还想对轮询,信号量,自旋锁等进行进一步的理解,感觉学习还是在实践中比较实在,以前这些都看过书的,好像是理解了,但没有实践,用起来完全不行,所以说学习嵌入式还要实践中学习
  • «
  • 1
  • 2
  • »
  • Pages: 1/2     Go