Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsinputlishandler.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmsinput/mmsinputlishandler.h"
00034 #include "mmsinput/mmsinputlisthread.h"
00035 #include "mmsconfig/mmsconfigdata.h"
00036 #include <cstring>
00037 #include <typeinfo>
00038 #include <sys/ioctl.h>
00039 
00040 #include <linux/input.h>
00041 
00042 
00043 #if defined(__HAVE_FBDEV__) || defined(__HAVE_KMS__)
00044 MMSInputLISHandler::MMSInputLISHandler(MMS_INPUT_DEVICE device) :
00045     devcnt(0),
00046     ie_count(0),
00047     ie_read_pos(0),
00048     ie_write_pos(0) {
00049 
00050     getDevices();
00051     for (int i = 0; i < this->devcnt; i++) {
00052         if(this->devices[i].type != MMSINPUTLISHANDLER_DEVTYPE_UNKNOWN) {
00053             MMSInputLISThread *lt = new MMSInputLISThread(this, &this->devices[i]);
00054             if (lt) {
00055                 lt->start();
00056             }
00057         }
00058     }
00059 }
00060 #else
00061 MMSInputLISHandler::MMSInputLISHandler(MMS_INPUT_DEVICE device) {
00062     throw MMSError(0,(string)typeid(this).name() + " is empty. compile FBDEV or KMS support!");
00063 }
00064 #endif
00065 
00066 MMSInputLISHandler::~MMSInputLISHandler() {
00067 }
00068 
00069 
00070 #define NUMBITS(x)          ((((x)-1)/(sizeof(long)*8))+1)
00071 #define TSTBIT(bit, array)  ((array[(bit)/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1)
00072 
00073 bool MMSInputLISHandler::checkDevice() {
00074     // point to the device
00075     MMSINPUTLISHANDLER_DEV *dev = &this->devices[this->devcnt];
00076 
00077     // open the device
00078     int  fd;
00079     if ((fd = open(dev->name.c_str(), O_RDWR)) < 0)
00080          return false;
00081 
00082     // try to grab the device
00083     if (ioctl(fd, EVIOCGRAB, 1)) {
00084         close(fd);
00085         return false;
00086     }
00087 
00088     // get description
00089     char devdesc[256];
00090     memset(devdesc, 0, sizeof(devdesc));
00091     ioctl(fd, EVIOCGNAME(sizeof(devdesc)-1), devdesc);
00092     dev->desc = devdesc;
00093     dev->type = MMSINPUTLISHANDLER_DEVTYPE_UNKNOWN;
00094 
00095     // try to find out the type of input device
00096     unsigned int  keys = 0;
00097     unsigned long ev_bit[NUMBITS(EV_MAX)];
00098     unsigned long key_bit[NUMBITS(KEY_MAX)];
00099     unsigned long abs_bit[NUMBITS(ABS_MAX)];
00100 
00101     // get event type of device
00102     ioctl(fd, EVIOCGBIT(0, sizeof(ev_bit)), ev_bit);
00103     if(TSTBIT(EV_KEY, ev_bit)) {
00104         ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bit)), key_bit);
00105         for(int i = KEY_Q; i < KEY_M; i++)
00106             if (TSTBIT(i, key_bit))
00107                 keys++;
00108         if(keys > 20 || TSTBIT(KEY_ENTER, key_bit)) {
00109             dev->type = MMSINPUTLISHANDLER_DEVTYPE_KEYBOARD;
00110         } else {
00111             for(int i = KEY_OK; i < KEY_MAX; i++) {
00112                 if(TSTBIT(i, key_bit)) {
00113                     dev->type = MMSINPUTLISHANDLER_DEVTYPE_REMOTE;
00114                     break;
00115                 }
00116             }
00117         }
00118     }
00119 
00120     /* check for touchscreen */
00121     if(dev->type == MMSINPUTLISHANDLER_DEVTYPE_UNKNOWN) {
00122         if(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof (abs_bit)), abs_bit) != -1) {
00123             if(TSTBIT(ABS_X, abs_bit) && TSTBIT(ABS_Y, abs_bit)) {
00124                 if(TSTBIT(EV_KEY, ev_bit) && (TSTBIT(BTN_LEFT, key_bit) || TSTBIT(BTN_TOUCH, key_bit))) {
00125                     dev->touch.haveBtnEvents = true;
00126                     dev->type = MMSINPUTLISHANDLER_DEVTYPE_TOUCHSCREEN;
00127                 } else if(TSTBIT(ABS_PRESSURE, abs_bit)) {
00128                     dev->touch.haveBtnEvents = false;
00129                     dev->type = MMSINPUTLISHANDLER_DEVTYPE_TOUCHSCREEN;
00130                 }
00131             }
00132         }
00133 
00134         if(dev->type == MMSINPUTLISHANDLER_DEVTYPE_TOUCHSCREEN) {
00135             struct input_absinfo abs;
00136             MMSConfigData config;
00137             MMSFBRectangle vRect = config.getVRect();
00138 
00139             /* use the graphicslayer resolution if vrect isn't set */
00140             if(vRect.w <= 0) {
00141                 vRect = config.getGraphicsLayer().rect;
00142             }
00143 
00144             dev->touch.rect     = config.getTouchRect();
00145             dev->touch.swapX    = config.getTouchSwapX();
00146             dev->touch.swapY    = config.getTouchSwapY();
00147             dev->touch.swapXY   = config.getTouchSwapXY();
00148 
00149             if(dev->touch.rect.w) {
00150                 dev->touch.xFactor = (float)vRect.w / (float)dev->touch.rect.w;
00151             } else if(ioctl(fd, EVIOCGABS(ABS_X), &abs) != -1) {
00152                 if(dev->touch.swapXY) {
00153                     dev->touch.yFactor =  (float)vRect.h / (abs.maximum - abs.minimum);
00154                 } else {
00155                     dev->touch.xFactor =  (float)vRect.w / (abs.maximum - abs.minimum);
00156                 }
00157             } else {
00158                 dev->touch.xFactor = 1.0;
00159             }
00160             if(dev->touch.rect.h) {
00161                 dev->touch.yFactor = (float)vRect.h / (float)dev->touch.rect.h;
00162             } else if(ioctl(fd, EVIOCGABS(ABS_Y), &abs) != -1) {
00163                 if(dev->touch.swapXY) {
00164                     dev->touch.xFactor = (float)vRect.w / (abs.maximum - abs.minimum);
00165                 } else {
00166                     dev->touch.yFactor = (float)vRect.h / (abs.maximum - abs.minimum);
00167                 }
00168             } else {
00169                 dev->touch.yFactor = 1.0;
00170             }
00171         }
00172     }
00173 
00174     printf("Found %s, type=%s (%s)\n",
00175                         dev->name.c_str(),
00176                         dev->type.c_str(),
00177                         dev->desc.c_str());
00178 
00179     // release device
00180     ioctl(fd, EVIOCGRAB, 0);
00181     close(fd);
00182 
00183     return true;
00184 }
00185 
00186 void MMSInputLISHandler::getDevices() {
00187     for (int i = 0; i < MMSINPUTLISHANDLER_MAX_DEVICES; i++) {
00188         this->devices[this->devcnt].name = "/dev/input/event" + iToStr(i);
00189         if (checkDevice())
00190             this->devcnt++;
00191     }
00192 }
00193 
00194 bool MMSInputLISHandler::addEvent(MMSInputEvent *inputevent) {
00195     this->lock.lock();
00196 
00197     // block if buffer is full
00198     while(this->ie_count == (MMSINPUTLISHANDLER_EVENT_BUFFER_SIZE - 1)) {
00199         usleep(10000);
00200     }
00201     // add event
00202     this->ie_buffer[this->ie_write_pos] = *inputevent;
00203 
00204     // increase event counter
00205     this->ie_count++;
00206 
00207     // increase write position
00208     this->ie_write_pos++;
00209     if(this->ie_write_pos >= MMSINPUTLISHANDLER_EVENT_BUFFER_SIZE)
00210         this->ie_write_pos = 0;
00211 
00212     this->lock.unlock();
00213     return true;
00214 }
00215 
00216 void MMSInputLISHandler::grabEvents(MMSInputEvent *inputevent) {
00217 #if defined(__HAVE_FBDEV__) || defined(__HAVE_KMS__)
00218     // block if buffer is empty
00219     while(this->ie_count == 0) {
00220         usleep(10000);
00221     }
00222 
00223     // there is at least one event in the buffer, return next event
00224     *inputevent = this->ie_buffer[this->ie_read_pos];
00225 
00226     // decrease event counter
00227     this->ie_count--;
00228 
00229     // increase read position
00230     this->ie_read_pos++;
00231     if (this->ie_read_pos >= MMSINPUTLISHANDLER_EVENT_BUFFER_SIZE)
00232         this->ie_read_pos = 0;
00233 #else
00234     throw MMSError(0,(string)typeid(this).name() + " is empty. compile FBDEV or KMS support!");
00235 #endif
00236 }
00237 

Generated by doxygen