zoukankan      html  css  js  c++  java
  • Qt触摸屏、键盘的驱动[转]

    Qt触摸屏、键盘的驱动

    1.Qt触摸屏的加入:

    EP9315开发板可以用触摸屏作为Qt的鼠标输入,这时候你需要修改$REAL_QTDIR/tmake/lib/qws/linux-arm-g++目录下的tmake.conf文件。好了,打开这个文件,看到TMAKE_CXXFLAGS变量了吗?在后面增加一项-DQT_QWS_CUSTOM,当然这个变量需要你打入qt-2.3.7-patch-crus1.4.3.bz2补丁才有效果,这个补丁是curris logic公司专门为Qt-2.3.7作的补丁。

    2.Qt键盘的加入:

    首先编写驱动程序,在驱动程序中主要实现read,poll,interrupt,其中read主要针对非阻塞方法进行处理,实现poll方法,以满足应用程序对select,FD_SET……一套函数的调用。定义等待队列static DECLARE_WAIT_QUEUE_HEAD(queue);在中断中调用wake_up_interruptible(&queue);唤醒等待队列,在poll中调用poll_wait(filp, &queue, wait);等待中断的唤醒。

        注意事项,编译驱动的交叉编译器要和编译内核的交叉编译器一致。

    #include <asm/system.h>

    #include <linux/config.h>

    #include <linux/types.h>

    #include <linux/major.h>

    #include <linux/string.h>

    #include <linux/fcntl.h>

    #include <linux/slab.h>

    #include <linux/timer.h>

    #include <linux/module.h>

    #include <linux/init.h>

    #include <linux/ioport.h>

    #include <linux/poll.h>

    #include <linux/fs.h>

    #include <linux/sched.h>

    #include <asm/io.h>

    #include <asm/memory.h>

    #include <asm/uaccess.h>

    #include <asm/segment.h>

    #include <asm/arch/hardware.h>

    #include <asm/arch/io.h>

    #include <asm/arch/irqs.h>

    #include <asm/arch/regmap.h>

    #include <asm/irq.h>

    #define SKB_NAME "/dev/skbdriver"

    int __init skb_init(void);

    void __exit skb_exit(void);

    void gpio_init(void);

    static unsigned int skb_poll(struct file *filp, poll_table *wait);

    static void skb_interrupt(int irq, void *dev_id, struct pt_regs *regs);

    static ssize_t skb_read(struct file *filp, char *buf, size_t count, loff_t *l);

    static int skb_open(struct inode *inode, struct file *filp);

    static int skb_release(struct inode *inode, struct file *filp);

    //static wait_queue_head_t queue;

    static DECLARE_WAIT_QUEUE_HEAD(queue);

    static unsigned char portdata[2];

    void gpio_init(void){

        unsigned long temp;

    //disable interrupt

    // temp = readl(VIC1INTENABLE)&0xf7ffffff;

    // writel(temp,VIC1INTENABLE);

        disable_irq(IRQ_GPIO);

    //select irq mode  

        temp = readl(VIC1INTSELECT)&0xf7ffffff;

        writel(temp,VIC1INTSELECT);

    //setup EGPIO(A(3-7),B(0,2))

    //direction register

        temp = readl(GPIO_PADDR)&0x07;

        writel(temp,GPIO_PADDR);

        temp = readl(GPIO_PBDDR)&0xfa;

        writel(temp,GPIO_PBDDR);

    //interrupt enable register

        temp = readl(GPIO_AINTEN)|~0x07;

        writel(temp,GPIO_AINTEN);

        temp = readl(GPIO_BINTEN)|~0xfa;

            writel(temp,GPIO_BINTEN);

    //inttype1 register

        temp = readl(GPIO_AINTTYPE1)|~0x07;

        writel(temp,GPIO_AINTTYPE1);

        temp = readl(GPIO_AINTTYPE2)|~0xfa;

            writel(temp,GPIO_AINTTYPE2);

        temp = readl(GPIO_BINTTYPE1)&0x07;

            writel(temp,GPIO_BINTTYPE1);

        temp = readl(GPIO_BINTTYPE2)&0xfa;

            writel(temp,GPIO_BINTTYPE2);

    //EOI register

        temp = readl(GPIO_AEOI)|~0x07;

        writel(temp,GPIO_AEOI);

            temp = readl(GPIO_BEOI)|~0xfa;

            writel(temp,GPIO_BEOI);

    //debounce register

        temp = readl(GPIO_ADB)|~0x07;

        writel(temp,GPIO_ADB);

            temp = readl(GPIO_BDB)|~0xfa;

            writel(temp,GPIO_BDB);

    //enable interrupt

    //        temp = readl(VIC1INTENABLE)|~0xf7ffffff;

    //       writel(temp,VIC1INTENABLE);

       

    // init_waitqueue_head(&queue);

        portdata[0]=0xf8;

        portdata[1]=0x05;

        enable_irq(IRQ_GPIO);

           

    }

    static unsigned int skb_poll(struct file *filp, poll_table *wait)

    {

    // printk("before poll_wait ");

            poll_wait(filp, &queue, wait);

    // printk("in skb_poll ");

            if (((portdata[0]&0xf8)!=0xf8)||((portdata[1]&0x05)!=0x05))

        {

    //      printk("faint ");

                    return POLLIN | POLLRDNORM;

        }

            return 0;

    }

    static void skb_interrupt(int irq, void *dev_id, struct pt_regs *regs)

    {

        unsigned long temp;

        disable_irq(IRQ_GPIO);

            temp = readl(GPIO_AEOI)|~0x07;

            writel(temp,GPIO_AEOI);

            temp = readl(GPIO_BEOI)|~0xfa;

            writel(temp,GPIO_BEOI);

       

        portdata[0]=readl(GPIO_PADR);

        portdata[1]=readl(GPIO_PBDR);

    // printk("%x %x ",portdata[0],portdata[1]);

       

        wake_up_interruptible(&queue);

        enable_irq(IRQ_GPIO);

    }

    static ssize_t skb_read(struct file *filp, char *buf, size_t count, loff_t *l)

    {

        unsigned char data[2];

        ssize_t retval;

        data[0]=portdata[0];

        data[1]=portdata[1];

           

        if(((data[0]&0xf8)==0xf8)&&((data[1]&0x05)==0x05))

        {

            if (filp->f_flags & O_NONBLOCK)

            {

                            retval = -EAGAIN;

            }

        }

       

       

        if(copy_to_user(buf, &data, sizeof(data)))

            return -EFAULT;

    // printk("in skb_read ");

        portdata[0]=0xf8;

        portdata[1]=0x05;

                                                                                   

            return (sizeof(data));

    }

    static int skb_open(struct inode *inode, struct file *filp)

    {

    // printk("in open ");

            MOD_INC_USE_COUNT;

            return 0;

    }

    static int skb_release(struct inode *inode, struct file *filp)

    {

    // printk("in release ");

            MOD_DEC_USE_COUNT;

            return 0;

    }

    struct file_operations skb_fops = {

            read:           skb_read,

        poll:       skb_poll,

            open:           skb_open,

            release:        skb_release,

    };

    int __init skb_init(void){

        int rc;

        int ret;

        rc = register_chrdev(144,SKB_NAME, &skb_fops);

        if(rc<0){

          printk(KERN_INFO"LINBUS: Can't get Major ");

          return rc;

        }

             printk("<1>*****************rc is %d ",rc) ;

        if ((ret = request_irq(IRQ_GPIO,skb_interrupt,SA_INTERRUPT, SKB_NAME, NULL)))

            {

                    printk("skb_init: failed to register IRQ ");

                    free_irq(IRQ_GPIO, NULL);

                    return ret;

            }

       

        gpio_init();

        return 0;

    }

    void __exit skb_exit(void)

    {

            free_irq(IRQ_GPIO, NULL);

    //        devfs_unregister_chrdev(TS_MAJOR, TS_NAME);

    //        printk("ads7843 touch screen driver removed ");

    }

    module_init(skb_init);

    module_exit(skb_exit);

    然后修改/root/Qt_arm/qt-2.3.7-emb/src/kernel/qkeyboard_qws.cpp程序,主要参考QWSTtyKeyboardHandler的实现方法,其中QSocketNotifier的实现类似于FD_SET,也可能就是对FD_SET的封装。最后在QWSKeyboardHandler *QWSServer::newKeyboardHandler( const QString &spec )函数中将所实现的类实例化else if ( type == "SKB" ) {

            handler = new QWSSKBKeyboardHandler(device);

    //modified by bugqiao begin

    class QWSSKBKeyboardHandler : public QWSPC101KeyboardHandler

    {

        Q_OBJECT

    public:

        QWSSKBKeyboardHandler(const QString& device);     virtual ~QWSSKBKeyboardHandler();

                                                                                   

    private slots:

        void readKeyboardData();

                                                                                    

    private:

        int fd;

    };

    //modified by bugqiao end

    /* SKB driver */

    //modified by bugqiao begin

    QWSSKBKeyboardHandler::QWSSKBKeyboardHandler(const QString& device)

    {

            fd = open(device.isEmpty()?"/dev/skbdriver":device.latin1(),O_RDONLY|O_NONBLOCK, 0);

            qDebug("fd = %d ",fd);

            if ( fd >= 0 ) {

                    QSocketNotifier *notifier;

                    notifier = new QSocketNotifier( fd, QSocketNotifier::Read, this );

            connect( notifier, SIGNAL(activated(int)),this,

                   SLOT(readKeyboardData()) );

        }

    }

                                                                                                      

    QWSSKBKeyboardHandler::~QWSSKBKeyboardHandler()

    {

        close(fd);

    }

                                                                                                       

    void QWSSKBKeyboardHandler::readKeyboardData()

    {

        unsigned char portdata[2];

        int n = read(fd, &portdata, sizeof(portdata) );

        int tmp;

            qDebug("n=%d portdata[0]=%x portdata[1]=%x ",n,portdata[0],portdata[1]);

        if ( n != 2 )

            return;

        if((tmp=portdata[0]&0x08)==0) {

            qDebug("up ");

            processKeyEvent( 0, Qt::Key_Up, 0, 1, false );

        } else if((tmp=portdata[0]&0x10)==0) {

            qDebug("right ");

          processKeyEvent( 0, Qt::Key_Right, 0, 1, false );

        } else if((tmp=portdata[0]&0x20)==0) {

            qDebug("down ");

            processKeyEvent( 0, Qt::Key_Down, 0, 1, false );

        } else if((tmp=portdata[0]&0x40)==0) {

            qDebug("left ");

            processKeyEvent( 0, Qt::Key_Left, 0, 1, false );

        } else if((tmp=portdata[0]&0x80)==0) {

            qDebug("esc ");

            processKeyEvent( 0, Qt::Key_Escape, 0, 1, false );

        } else if((tmp=portdata[1]&0x01)==0) {

            qDebug("return ");

            processKeyEvent( 0, Qt::Key_Return, 0, 1, false );

        }

                                                                                                      

    }

    //modified by bugqiao end

    最后在编写的脚本文件中增加export QWS_KEYBOARD=SKB:/dev/skbdriver

    这是别人的总结,在这里参考一下

  • 相关阅读:
    设计模式的分类
    设计模式工厂方法模式
    设计模式的定义
    帕斯卡命名法
    C#编写程序找一找一个二维数组中的鞍点(即该位置上的元素值在行中最大,在该 列上最小。有可能数组没有鞍点)。要求:1.二维数组的大小、数组元素的值在运行时输入;2.程序有友好的提示信息。
    设计模式抽象工厂模式
    设计模式七大原则
    理解C#中的接口
    Linux下如何查看CPU信息, 包括位数和多核信息
    关于结构体内存对齐
  • 原文地址:https://www.cnblogs.com/ganrui/p/3711200.html
Copyright © 2011-2022 走看看