Qt Embedded中如何实现自己的keyboard

最近的项目是基于Qt,既然是嵌入式设备,难免就要在根据自己的平台来实现键盘的驱动部分,当然是属于Qt一层,而不是更底层的字符设备驱动。 

这里要讲的方法是在不重新编译Qt库的情况,把我们自己的键盘驱动作为一个Qt插件集成到我们的程序中。当然也可以把我们自己的键盘驱动部分直接编译到Qt库里面。 

Qt中提供的插件机制(Plugin),可以使得我们很容易根据自己的硬件实现自己的键盘代码。 

具体步骤: 

1. 首先创建一个静态插件库(当然也可以是动态库),我们这边库名叫做optkeypad。 
    a. 创建一个键盘处理类 KeypadHandler, 多继承于QObject 和 QWSKeyboardHandler, 实现一个关键的函数readKpdData(),这个函数很关键,就是用来把我们的硬件值(hardcode)转换为Qt库中定义的键值。 
    b. 创建一个插件类 KeypadDriverPlugin, 继承于QKbdDriverPlugin, 这个类主要是创建一个我们自己的键盘处理类KeypadHandler,重新实现QKbdDriverPlugin的create()和keys()函数,这是两个虚函数,我们要在自己的类中重新实现这两个函数。 
     c. 我们做成一个静态插件类,所以.pro文件如下。 
2. 那么如何使用这个插件类呢, 
    a. 在我们的应用程序中(一般在main.cpp中)添加宏 Q_IMPORT_PLUGIN(optkeypad)。optkeypad是库名,注意不包含linux中的前缀lib和扩展名.a。 
    b. 在应用程序的.pro文件中添加 QTPLUGIN += optkeypad, 并且要在链接中添加这个库  LIBS += -L(路径)  -loptkeypad 
    c. 接下来要为程序添加环境变量 QWS_KEYBOARD,   export QWS_KEYBOARD=OptimusKpdHandler:/dev/input/event1 (这个很重要) 
        注意这个OptimusKpdHandler是怎么来的, 我们的插件类KeypadDriverPlugin要根据这个名字来建立一个键盘处理类KeypadHandler,所以如果这个名字不匹配的话,处理类是不会被创建的。 
3. 接下来我们的Qt应用程序中的键值,就是KeypadHandler类的readKpdData()处理后的值。 

        .pro文件 

QT += webkit //这个必须加的,否则不少头文件找不到,因为Qt不会自动添加webkit模块
TEMPLATE = lib 
CONFIG += static \ 
        plugin \ 
        release 
TARGET = optkeypad 
HEADERS += keypadhandler.h \ 
    keypaddriverplugin.h 
SOURCES += keypadhandler.cpp \ 
    keypaddriverplugin.cpp 

QMAKE_INCDIR += ../ClockCommon 
QMAKE_LIBS += -lClockCommon 


        keypadDriverPlugin.h文件 

/*KeypadDriverPlugin 为接口类,QKbdDriverPlugin为抽象类,QWSKeyboardHandler 为handler类的父类,create,keys,及析构函数是必须的*/
class KeypadDriverPlugin : public QKbdDriverPlugin 

    Q_OBJECT 
public: 
    KeypadDriverPlugin(QObject *parent = 0); 
    ~KeypadDriverPlugin(); 

    QWSKeyboardHandler *create(const QString &driver, const QString &device); 
    QWSKeyboardHandler *create(const QString &driver); 
    QStringList keys() const; 
}; 


        类的实现文件 


KeypadDriverPlugin::KeypadDriverPlugin(QObject *parent) 

    


KeypadDriverPlugin::~KeypadDriverPlugin() 



//OptimusKpdHandler为具体的plugin名称
QStringList KeypadDriverPlugin::keys() const 

    return QStringList() << "OptimusKpdHandler"; 


// 
// The create() functions are responsible for returning an instance of 
// the keypad driver. We do this only if the driver parameter matches our key. 
// 
QWSKeyboardHandler *KeypadDriverPlugin::create(const QString &driver, const QString &device) 

    PR("KeypadDriverPlugin::create###################################: %s\n",       driver.toLocal8Bit().constData()); 
    if (driver.toLower() == "optimuskpdhandler") 
    { 
        PR("Before creating KeypadHandler\n"); 
        return new KeypadHandler(device); //创建一个handler类的实例
    } 

    return 0; 


QWSKeyboardHandler *KeypadDriverPlugin::create(const QString &driver) 

    if (driver.toLower() == "optimuskpdhandler") 
    { 
        PR("Before creating KeypadHandler"); 
        return new KeypadHandler(); 
    } 

    return 0; 



  // keypadHandler.h文件 
class KeypadHandler : public QObject, public QWSKeyboardHandler 

    Q_OBJECT 

public: 
    KeypadHandler(const QString &device = QString("/dev/input/event0")); 
    ~KeypadHandler(); 

private: 
    QSocketNotifier *m_notifier; //用于对键盘设备文件进行状态检测
    int kbdFd; //kbdFd用于保存键盘设备文件打开之后的描述符

private slots: 
    void readKpdData(); 
}; 


 // keypadHandler 类的实现文件 
struct InputData 

    unsigned int dummy1; 
    unsigned int dummy2; 
    unsigned short type; 
    unsigned short code; 
    unsigned int value; 
    unsigned int dummy3; 
    unsigned int dummy4; 
    unsigned int dummy5; 
    unsigned int dummy6; 
}; 

KeypadHandler::KeypadHandler(const QString &device) 

    setObjectName("Optimus Keypad Handler"); 
    this->kbdFd = ::open(device.toLocal8Bit().constData(), O_RDONLY, 0); 

    if (kbdFd > 0) 
    { 
        PR("%s opened as keyboard input.\n", device.toLocal8Bit().constData()); 
        g_Log.Debugf(LOG_DETAIL_TRACE, 0, L"%s opened as keyboard input.", device.toLocal8Bit().constData()); 
        this->m_notifier = new QSocketNotifier(kbdFd, QSocketNotifier::Read, this); 
        connect(this->m_notifier, SIGNAL(activated(int)), this, SLOT(readKpdData())); 
    } 
    else 
    { 
        PR("Cannot open %s for keyboard input. (%s)", 
                     device.toLocal8Bit().constData(), strerror(errno)); 
        g_Log.Errorf(LOG_DETAIL_IMPORTANT, 0, L"Cannot open %s for keyboard input. (%s)", 
                     device.toLocal8Bit().constData(), strerror(errno)); 
        return; 
    } 


KeypadHandler::~KeypadHandler() 

    if (kbdFd > 0) 
        ::close(kbdFd); 


// Key function 
void KeypadHandler::readKpdData() 

    InputData event; 

    int n = read(kbdFd, &event, sizeof(InputData)); 
    if (n != sizeof(InputData)) 
    { 
        PR("key pressed: n=%d\n", n); 
        g_Log.Debugf(LOG_DETAIL_TRACE, 0, L"key pressed: n=%d", n); 
        return; 
    } 

    PR("key pressed: type=%d, code=0x%x, value=%d, %s\n", 
                 event.type, event.code, event.value, (event.value != 0)? "(Down)" : "(Up)"); 
    g_Log.Debugf(LOG_DETAIL_TRACE, 0, L"key pressed: type=%d, code=%d, value=%d, %s", 
                 event.type, event.code, event.value, (event.value != 0)? "(Down)" : "(Up)"); 

    Qt::KeyboardModifiers modifiers = Qt::NoModifier; 
    int unicode = 0xffff; 
    int key_code = 0; 

    // 可以根据自己特定的硬件值来设定。 
    switch (event.code) 
    { 
        case 0x2: 
            key_code = Qt::Key_1; 
            unicode = '1'; 
            break; 
        case 0x110: 
            key_code = Qt::Key_Context1; 
            unicode = 0xffff; 
            break; 
        case 0x100: 
            key_code = Qt::Key_Back; 
            unicode = 0xffff; 
            break; 
        default: 

            break; 
    } 

    this->processKeyEvent(unicode, key_code, modifiers, event.value != 0, false); 


注:红色部分为本人加注,并不是作者的原文,如有错误,望修正.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值