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
这是别人的总结,在这里参考一下