QList<KeyData> QCrmlParser::parseBit(quint32 repoUid, quint32 keyInt)
{
    QList <KeyData> rv;
    QStringList mandatoryAttributes;
    mandatoryAttributes << QLatin1String("ref");
    if (!checkMandatoryAttributes(mandatoryAttributes)) {
        rv.clear();
        return rv;
    }

    QString keyPath = attributes().value(QLatin1String("ref")).toString();
    if (!keyPath.startsWith(QLatin1Char('/')))
        keyPath.prepend(QLatin1Char('/'));

    int bitIndex = 0;
    while(!atEnd()) {
        readNext();
        if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
            setError(ParseError, QXmlStreamReader::errorString());
            rv.clear();
            return rv;
        }

        if (isEndElement() && name() == "bit")
            break;
        if(isStartElement()) {
            parseUnknownElement();
            if (error() != NoError) {
                rv.clear();
                return rv;
            }
        } else if (isCharacters()) {
            bool ok;
            QString txt = text().toString();
            if (txt.simplified().isEmpty())
                continue;
            bitIndex = txt.toInt(&ok);
            if (!ok || bitIndex <= 0) {
                //Note: binary keys have no maximum bit index
                setError(ParseError, QObject::tr("bit element has invalid text value on line %1")
                        .arg(QString::number(lineNumber())));
                rv.clear();
                return rv;
            }
        }
    }

    if (!isEndElement() && name() !="bit") {
        setError(ParseError, QObject::tr("bit element does not have end tag at line: %1")
                            .arg(QString::number(lineNumber())));
        rv.clear();
        return rv;
    }

    quint64 uid = repoUid;
    uid = uid << 32;
    uid += keyInt;
    rv.append(KeyData(keyPath,uid, m_target, bitIndex));
    return rv;
}
Beispiel #2
0
struct KeyData Keyboard::pollDevice(nfds_t nfds) {
	/*
	 * poll() checks the device for any activities and blocks the loop,
	 * either until an event has occured, or the timeout has been reached.
	 * This leads to a very efficient polling mechanism.
	 */
	poll(fds, nfds, TIMEOUT);

	// check, if device has been disconnected
	if (fds->revents & POLLHUP || fds->revents & POLLERR) {
		disconnect();

		return KeyData();
	}

	struct KeyData keyData = getInput();

	return keyData;
}
QList<KeyData> QCrmlParser::parseKeyRange(quint32 repoUid)
{
    QList<KeyData> rv;

    //if keyRange has no ref attribute it must
    //only be used for creating access control
    //policies which we do not need to worry about
    if (attributes().value(QLatin1String("ref")).isNull())
        return rv;

    QStringList mandatoryAttributes;
    mandatoryAttributes << QLatin1String("firstInt") << QLatin1String("lastInt");
    if (!checkMandatoryAttributes(mandatoryAttributes))
        return rv;

    bool ok = false;
    QString pathPrefix;
    pathPrefix = attributes().value(QLatin1String("ref")).toString();
    if (!pathPrefix.startsWith(QLatin1Char('/')))
        pathPrefix.prepend(QLatin1Char('/'));

    if (!attributes().value(QLatin1String("countInt")).isNull()) {
        quint32 countInt =
            uidStringToUInt32(attributes().value(QLatin1String("countInt")).toString(), &ok);
        if (!ok) {
            setError(ParseError, QObject::tr("keyRange element has invalid countInt attribute on line %1")
                    .arg(QString::number(lineNumber())));
            rv.clear();
            return rv;
        }

        rv.append(KeyData(pathPrefix,(quint64)countInt + (((quint64)repoUid) << 32), m_target));
    }

    if (!pathPrefix.endsWith(QLatin1Char('/')))
        pathPrefix.append(QLatin1Char('/'));

    quint32 firstInt =
        uidStringToUInt32(attributes().value(QLatin1String("firstInt")).toString(), &ok);
    if (!ok) {
        setError(ParseError, QObject::tr("keyRange element has invalid firstInt attribute on line %1")
                .arg(QString::number(lineNumber())));
        rv.clear();
        return rv;
    }

    quint32 lastInt =
        uidStringToUInt32(attributes().value(QLatin1String("lastInt")).toString(),&ok);
    if (!ok) {
        setError(ParseError, QObject::tr("keyRange element has invalid lastInt attribute on line %1")
                .arg(QString::number(lineNumber())));
        rv.clear();
        return rv;
    }

    quint32 maxNum =0;
    quint32 indexBits = 0;
    quint32 firstIndex = 0;
    if (attributes().value(QLatin1String("indexBits")).isNull()) {
        //keyRange doesn't map to sequence setting

        maxNum = lastInt - firstInt + 1;
        for (quint32 i=0; i < maxNum; i++) {
            rv.append(KeyData(pathPrefix + QString::number(i),
                                (quint64)firstInt + (((quint64)repoUid) << 32) + i,
                                m_target));
        }

        while (!atEnd()) {
            readNext();
            if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
                setError(ParseError, QXmlStreamReader::errorString());
                rv.clear();
                return rv;
            }

            if (isEndElement())
                break;

            if (isStartElement())
                parseUnknownElement();
        }
    } else {
        //keyRanges does  map to sequence setting
        indexBits =
            uidStringToUInt32(attributes().value(QLatin1String("indexBits")).toString(), &ok);
        if (!ok) {
            setError(ParseError, QObject::tr("keyRange elment has invalid indexBits attribute on line %1")
                    .arg(QString::number(lineNumber())));
            rv.clear();
            return rv;
        }

        if (!attributes().value(QLatin1String("firstIndex")).isNull()) {
            QString firstIndexStr = attributes().value(QLatin1String("firstIndex")).toString();
            firstIndex = firstIndexStr.toUInt(&ok, 10);
            if (!ok) {
                setError(ParseError, QObject::tr("keyRange element has invalid firstIndex attribute on line %1")
                        .arg(QString::number(lineNumber())));
                rv.clear();
                return rv;
            }
        }

        int indexBitsLSB =0;
        quint32 bitmask = 1;
        while ( (bitmask & indexBits) == 0) {
            bitmask = bitmask << 1;
            bitmask +=1;
            indexBitsLSB+=1;
        }

        maxNum =( ((lastInt - firstInt) & indexBits) >> indexBitsLSB) + 1 - firstIndex;

        int indexBitsMSB=31;
        bitmask = 0x80000000;
        while ((bitmask & indexBits) == 0) {
            bitmask = bitmask >> 1;
            bitmask += 0x80000000;
            indexBitsMSB -=1;
        }
        bitmask = bitmask << 1;
        quint32 settingIdentifier = lastInt & bitmask;

        QList<KeyData> subSettings;

        while (!atEnd()) {
            readNext();
            if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
                setError(ParseError, QXmlStreamReader::errorString());
                rv.clear();
                return rv;
            }

            if (isEndElement())
                break;

            if (isStartElement()) {
                if (name() == "key") {
                    subSettings.append(parseKey(repoUid));

                    if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
                        rv.clear();
                        return rv;
                    }
                } else {
                    parseUnknownElement();
                }
            }

        }

        for(quint32 i = 0; i < maxNum; i++) {
            for(int j = 0; j < subSettings.count(); j++) {
                rv.append(KeyData(pathPrefix + QString::number(i) + subSettings.at(j).path(),
                                 subSettings.at(j).uid() + settingIdentifier + ((firstIndex + 1*i)  << indexBitsLSB),
                                 m_target, subSettings.at(j).bitIndex()));
            }
        }
    }

    return rv;
}
QList<KeyData> QCrmlParser::parseKey(quint32 repoUid)
{
    QList<KeyData> rv;
    QStringList mandatoryAttributes;
    mandatoryAttributes << QLatin1String("int");
    if (!checkMandatoryAttributes(mandatoryAttributes))
        return rv;

    QXmlStreamAttributes attribs = attributes();
    QString keyIntStr = attribs.value(QLatin1String("int")).toString();
    bool ok =false;
    quint32 keyInt = uidStringToUInt32(keyIntStr, &ok);
    if (!ok) {
        setError(ParseError,QObject::tr("key element has invalid int attribute on line %1").
                arg(QString::number(lineNumber())));
        return rv;
    }

    if (attribs.value(QLatin1String("ref")).isNull()) {
        //no ref attribute so this must be
        //a bitmask key
        while (!atEnd()) {
            readNext();
            if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
                 setError(ParseError, QXmlStreamReader::errorString());
                 rv.clear();
                 return rv;
            }
            if (isEndElement())
                break;

            if (isStartElement()) {
                if (name() == "bit") {
                    rv.append(parseBit(repoUid, keyInt));
                } else {
                    parseUnknownElement();
                }
            }
        }
    } else {
        QString keyRef = attribs.value(QLatin1String("ref")).toString();
        if (keyRef.isEmpty()) {
            setError(ParseError, QObject::tr("ref attribute of key element is empty on line %1")
                    .arg(QString::number(lineNumber())));
            rv.clear();
            return rv;
        }

        while (!atEnd()) {
            readNext();
            if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
                setError(ParseError, QXmlStreamReader::errorString());
                rv.clear();
                return rv;
            }
            if (isEndElement() && name() == "key") {
                break;
            }

            if (isStartElement()) {
                if (name() == "key" || name() == "keyRange") {
                    setError(ParseError, QObject::tr("key and/or keyRange element has "
                                "been nested in a key element on line %1").arg(QString::number(lineNumber())));
                    rv.clear();
                    return rv;
                } else {
                    parseUnknownElement();
                }
            }
        }

        QString keyPath(keyRef);
        if (!keyPath.startsWith(QLatin1Char('/')))
            keyPath.prepend(QLatin1Char('/'));
        quint64 uid = repoUid;
        uid = uid << 32;
        uid += keyInt;
        rv.append(KeyData(keyPath, uid,m_target));
    }
    return rv;
}