免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 984 | 回复: 0
打印 上一主题 下一主题

qte键盘的支持 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-04-06 21:56 |只看该作者 |倒序浏览
首先编写驱动程序,在驱动程序中主要实现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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include
#include
#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\n");
        poll_wait(filp, &queue, wait);
//  printk("in skb_poll\n");
        if (((portdata[0]&0xf8)!=0xf8)||((portdata[1]&0x05)!=0x05))
    {
//      printk("faint\n");
                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\t%x\n",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\n");
    portdata[0]=0xf8;
    portdata[1]=0x05;
                                                                                
        return (sizeof(data));

}

static int skb_open(struct inode *inode, struct file *filp)
{
//  printk("in open\n");
        MOD_INC_USE_COUNT;
        return 0;
}

static int skb_release(struct inode *inode, struct file *filp)
{
//  printk("in release\n");
        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
      printk(KERN_INFO"LINBUS: Can't get Major \n");
      return rc;
    }
         printk("*****************rc is %d\n",rc) ;

    if ((ret = request_irq(IRQ_GPIO,skb_interrupt,SA_INTERRUPT, SKB_NAME, NULL)))
        {
                printk("skb_init: failed to register IRQ\n");
                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\n");
}

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\n",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\tportdata[0]=%x\tportdata[1]=%x\n",n,portdata[0],portdata[1]);
    if ( n != 2 )
        return;
    if((tmp=portdata[0]&0x08)==0) {
        qDebug("up\n");
        processKeyEvent( 0, Qt::Key_Up, 0, 1, false );
    } else if((tmp=portdata[0]&0x10)==0) {
        qDebug("right\n");
        processKeyEvent( 0, Qt::Key_Right, 0, 1, false  );
    } else if((tmp=portdata[0]&0x20)==0) {
        qDebug("down\n");
        processKeyEvent( 0, Qt::Key_Down, 0, 1, false );
    } else if((tmp=portdata[0]&0x40)==0) {
        qDebug("left\n");
        processKeyEvent( 0, Qt::Key_Left, 0, 1, false );
    } else if((tmp=portdata[0]&0x80)==0) {
        qDebug("esc\n");
        processKeyEvent( 0, Qt::Key_Escape, 0, 1, false );
    } else if((tmp=portdata[1]&0x01)==0) {
        qDebug("return\n");
        processKeyEvent( 0, Qt::Key_Return, 0, 1, false );
    }
                                                                                                   
}
//modified by bugqiao end


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



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/8800/showart_96230.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP