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; }
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; }