ByteString VsbDevice::doQuery(uint8_t cmdId, ByteString data)
{
    ByteString cmdBuf(18, 0);
    cmdBuf[0] = cmdId;
    std::copy(data.begin(), data.end(), cmdBuf.begin()+2);
    sendFeatureReport(VSB_REPORTID, cmdBuf);
    bool dataOk = false;
    ByteString resp;
    for(int i = 0; i < NUM_READ_TRIES; ++i)
    {
        try
        {
            resp = getFeatureReport(VSB_REPORTID);
        }
        catch(HidDeviceError err)
        {
            if(i < NUM_READ_TRIES-1)
                continue;
            throw VsbError(std::string("HID subsystem error: ") + err.what());
        }
        if(resp.size() < 2)
            continue; //Probably shouldn't ever happen, but let's not crash if it does
        if(!resp[0])
            continue; //This also shouldn't happen...
        //FIXME: Implement a proper exception class to use here
        if(resp[0] != cmdId)
            throw std::runtime_error(boost::str(boost::format("Got the wrong command ID back! (%d)") % (int)resp[1]));
        if(resp[1] == VSB_RESP_BUSY)
        {
            //TODO: Insert a small time delay
            continue;
        }
        else if(resp[1] == VSB_RESP_NULL)
            throw VsbError("Null response code?");
        else if(resp[1] == VSB_RESP_BADCMD)
            throw VsbError("Device reported bad command ID");
        else if(resp[1] == VSB_RESP_BADCS)
            throw VsbError("Device reported stored configuration is corrupt/invalid");
        else if(resp[1] == VSB_RESP_BADIDX)
            throw VsbError("Device reported bad keyseq page number");
        else if(resp[1] == VSB_RESP_ERR)
            throw VsbError("Device reported general error");
        else if(resp[1] == VSB_RESP_OK)
        {
            dataOk = true;
            break;
        }
        else
            throw VsbError("Got invalid response code");
    }
    if(!dataOk)
        throw VsbError("Device failed to respond in time");
    return ByteString(resp, 2);
}
示例#2
0
// Analyse an incoming message so that it can be checked against SXE policies.
QString QCopRequestAnalyzer::analyze( QByteArray *msgQueue )
{
    dataSize = 0;
    moreData = false;

    QBuffer cmdBuf( msgQueue );
    cmdBuf.open( QIODevice::ReadOnly | QIODevice::Unbuffered );

    // Bail out if we don't have enough bytes for a complete packet.
    int size = read_int( &cmdBuf );
    if ( size < (int)sizeof(qint32) ) {
        moreData = true;
        return QString();
    }
    if ( size < QCopX11Client::minPacketSize )
        size = QCopX11Client::minPacketSize;
    if ( size > ( msgQueue->size() - cmdBuf.pos() + sizeof(qint32) ) ) {
        moreData = true;
        return QString();
    }

    // Read the command code and map it to a string.
    int cmd = read_int( &cmdBuf );
    QString request;
    bool needChannel = false;
    bool needMessage = false;
    switch ( cmd ) {

        case QCopCmd_RegisterChannel:
            request = "QCopRegisterChannel/QCop/RegisterChannel/";
            needChannel = true;
            break;

        case QCopCmd_Send:
            request = "QCopSend/QCop/";
            needChannel = true;
            needMessage = true;
            break;

        case QCopCmd_DetachChannel:
            request = "QCopSend/QCop//detach()";
            break;

        case QCopCmd_RequestRegistered:
            request = "QCopSend/QCop//isRegistered()";
            break;

        default: return QString();  // Shouldn't happen in the server.
    }

    // Read the rest of the packet header.
    int chLength = read_int( &cmdBuf );
    int msgLength = read_int( &cmdBuf );
    read_int( &cmdBuf );    // forwardToLength - don't need this
    read_int( &cmdBuf );    // dataLength - don't need this

    // Add the channel and message names if necessary.
    if ( needChannel )
        request += read_string( &cmdBuf, chLength );
    if ( needMessage )
        request += "/" + read_string( &cmdBuf, msgLength );

    // Remove the packet we just processed from the queue.
    dataSize = size;

    // Return the policy string to the caller.
    return request;
}