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

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

原文地址:https://www.cnblogs.com/ganrui/p/3711200.html