Beispiel #1
0
//            _progressDialog->setError("Unexpected data after preset write");
//            _machine->postEvent(new DataXfer_NACKEvent());
//        }
//    }
//}
//-------------------------------------------------------------------------
void DcXferMachine::xferTimeout()
{
    _watchdog.stop();

    if( _progressDialog->cancled() )
    {
        DCLOG() << (_isWriteMachine ? "Write Preset" : "Read Preset") << " cancled";
        _machine->postEvent( new DataXfer_CancledEvent() );
    }
    else
    {
        DCLOG() << (_isWriteMachine ? "Write Preset" : "Read Preset") << " Transfer Timeout";
        if( --_retryCount < 0 )
        {
            DCLOG() << "No more retries, notify user";
            _progressDialog->setError( "Unable to communicate with the device." );
            _machine->postEvent( new DataXfer_TimeoutEvent() );
        }
        else
        {
            QThread::msleep( 100 );
            if( !_midiOut->isSafeMode() )
            {
                DCLOG() << "Throttling back MIDI out data rate";
                _midiOut->setSafeMode();
                _progressDialog->setIoHealth( 1 );
            }

            _midiOut->dataOutThrottled( _activeCmd );

            // Restart watchdog
            _watchdog.start( _timeout );
        }
    }
}
//-------------------------------------------------------------------------
bool DcBootControl::activateBank( int bankNumber )
{
    bool rtval = false;

    // Parameter Checking
    if(bankNumber != 0 && bankNumber != 1)
    {
        DCLOG() << "Invalid bank number specified";
        return false;
    }

    // Verify system state
    if(!isBootcode())
    {
        DCLOG() << "not in boot code, can't activate a bank";
        return false;
    }

    // Do it
    if(0 == bankNumber)
    {
        QRtAutoTrigger mtrigger(DCBC_ACTIVATE_BANK0_SUCCESS,_pMidiIn);
        _pMidiOut->dataOut(DCBC_ACTIVATE_BANK0);
        if(mtrigger.wait(1000))
        {
            mtrigger.setPattern(DCBC_DEACTIVATE_BANK1_SUCCESS);
            _pMidiOut->dataOut(DCBC_DEACTIVATE_BANK1);
            if(mtrigger.wait(1000))
            {
                rtval = true;
            }
        }
    }
    else
    {
        QRtAutoTrigger mtrigger(DCBC_ACTIVATE_BANK1_SUCCESS,_pMidiIn);
        _pMidiOut->dataOut(DCBC_ACTIVATE_BANK1);
        if(mtrigger.wait(1000))
        {
            mtrigger.setPattern(DCBC_DEACTIVATE_BANK0_SUCCESS);
            _pMidiOut->dataOut(DCBC_DEACTIVATE_BANK0);
            if(mtrigger.wait(1000))
            {
                rtval = true;
            }
        }

    }

    return rtval;
}
Beispiel #3
0
bool DcBootControl::identify(DcMidiDevIdent* id /*=0 */)
{
    bool rtval = false;
    DcAutoTrigger autotc(_blindMode ? "F0 7E .. 06" :  "F0 7E .. 06 02 00 01 55",_pMidiIn );
    _pMidiOut->dataOut( "F0 7E 7F 06 01 F7" );

    // Wait for the response data, or timeout after 300ms
    if( autotc.wait( 3000 ) )
    {
        if( id )
        {
            DcMidiData md;
            if( autotc.dequeue( md ) )
            {
                if( _blindMode && _pDevDetails && !_pDevDetails->isEmpty())
                {
                    
                    DcMidiDevIdent* dcid = static_cast<DcMidiDevIdent*>(_pDevDetails);
                    if( dcid )
                    {
                        *id = *dcid;
                        DCLOG() << "BootControl 'blind mode' Id Result: " << id->toString() << "\n";
                        rtval = true;
                    }
                    else
                    {
                        DCLOG() << "BootControl 'blind mode' FAIL\n";
                    }
                }
                else
                {
                    id->fromIdentData( md );
                    DCLOG() << "BootControl Id Result: " << id->toString() << "\n";
                    rtval = true;
                }
            }
        }
        else
        {
            rtval = true;
        }
    }
    else
    {
        _lastErrorMsg << "Timeout waiting for identity response in BootControl";
    }
    
    
    return rtval;
}
bool DcBootControl::writeFirmwareUpdateMsg(QRtMidiData& msg,int timeOutMs /*= 2000*/)
{
    bool rtval = false;
    QRtAutoTrigger autotc(kFUResponcePattern,_pMidiIn);

    // Magic number 8 is the response control flags, a 3 will
    // deliver status.
    msg[8] = 0x03;

    _pMidiOut->dataOutSplit(msg,_maxDataOut,_delayBetweenDataOut);

    QRtMidiData md;


    // Wait for the response data, or timeout after 300ms
    if(autotc.wait(timeOutMs))
    {
        if(autotc.dequeue(md))
        {
            if(md == kFUGood)
            {
                rtval =  true;
            }
            else if(md == kFUBad)
            {
                DCLOG() << "kFUBad";
                _lastErrorMsg << "Device reject firmware command - BAD packet.";
            }
            else if(md == kFUFailed)
            {
                DCLOG() << "kFUFailed";
                _lastErrorMsg << "Device failed firmware command.";
            }
            else
            {
                DCLOG() << "Unknown response: " << md.toString(' ') << "\n";
                _lastErrorMsg << "Firmware write generated an unknown response from the device.";
            }
        }
    }
    else
    {
        DCLOG() << "Timeout waiting on " << msg.toString(' ') << "\n";
        _lastErrorMsg << "Firmware update failure - timeout after write command.\n" << msg.toString(' ').mid(15,38);
    }

    return rtval;
}
//-------------------------------------------------------------------------
bool DcBootControl::identify(QRtMidiDevIdent* id /*=0 */)
{
    bool rtval = false;
    QRtAutoTrigger autotc("F0 7E .. 06 02 00 01 55",_pMidiIn);

    _pMidiOut->dataOut("F0 7E 7F 06 01 F7");

    // Wait for the response data, or timeout after 300ms
    if(autotc.wait(3000))
    {
        if(id)
        {
            QRtMidiData md;
            if(autotc.dequeue(md))
            {
                id->fromIdentData(md);
                DCLOG() << id->toString() << "\n";
                rtval = true;
            }
        }
        else
        {
            rtval = true;
        }
    }
    else
    {
        _lastErrorMsg << "Timeout waiting for identity response";
    }

    return rtval;
}
Beispiel #6
0
//-------------------------------------------------------------------------
bool DcXferMachine::verifyPresetData( const DcMidiData &data, IoProgressDialog* progDialog, const DcDeviceDetails* devinfo )
{
    // Verify Data transfer:
    bool rtval = false;

    // Verify: data must end with a EOX (F7)
    if( data.at(data.length()-1) != 0xF7 )
    {
        // Incomplete data response
        DCLOG() << "Data transfer IN - incomplete preset received, never say EOX";
        progDialog->setError("Received incomplete preset data");
    }
    else 
    {
        if( data.length() != devinfo->PresetSize )
        {
            DCLOG() << "Data transfer IN - packet size mismatch: expected " << devinfo->PresetSize << " got " << data.length();
            DCLOG() << "Bad Packet: " << data.toString();

            if(devinfo->PresetSize > data.length())
            {
                progDialog->setError("The preset data received is corrupt and too small");
            }
            else
            {
                progDialog->setError("The preset data received is too large");
            }
        }
        else 
        {
            // Verify the checksum
            int sum = data.sumOfSection(devinfo->PresetStartOfDataOffset,devinfo->PresetDataLength);
            int dataVal = data.at(devinfo->PresetChkSumOffset);
            if(sum != dataVal)
            {
                DCLOG() << "The preset data received is corrupt, checksum Error.";
                DCLOG() << data.toString();
            }
            else
            {
                rtval = true;                      
            }
        }
    }
    return rtval;
}
//-------------------------------------------------------------------------
QRtMidiData DcBootControl::makePrivateResetCmd()
{
    QRtMidiDevIdent id;
    QRtMidiData priRst;

    // Verify we can ID the connected device
    if(false == identify(&id))
    {
        DCLOG() << "No response from identity request";
    }
    else
    {
        // Build private reset command using device product ID.
        priRst.setData(kPrivateResetPartial,id.getFamilyByte(),id.getProductByte());
    }

    return priRst;
}
Beispiel #8
0
//-------------------------------------------------------------------------
void DcXferMachine::replySlotForDataIn( const DcMidiData &data )
{
    // Expect to see sysex coming from the currently attached device.
    // This check will prevent other legal messages from blowing up
    // the transfer - like controller messages, etc...
    if(data.contains(_devDetails->SOXHdr))
    {
        if(data == _activeCmd)
        {
            // If the data coming back is the same as what was sent, 
            // it was echoed back to us, just ignore as it was probably due
            // to a device with MIDI "soft" THRU (midi-merge)
            return;
        } 

        // cancel the watchdog timer
        _watchdog.stop();

        // Check for a Negative Acknowledgment of the data in request
        if( data.match(_devDetails->PresetRd_NAK,true) )
        {
            DCLOG() << "Preset read NAK detected, notify user and bail";
            _progressDialog->setError("Device Rejected Command");
            _machine->postEvent(new DataXfer_NACKEvent());
        }
        else if( data.match(_devDetails->PresetRd_ACK) )
        {
            DcMidiData recompinded;

            if(gUseAltPresetSize)
            {
                int chnksz   = data.get14bit(9+2);
                recompinded = data.mid(0,9);
                recompinded[6] = 0x62;
                recompinded.append(DcMidiData(data.mid(9+6,chnksz)));
                recompinded.append(DcMidiData("18191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132337F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F"));
                recompinded.append(DcMidiData(data.mid(9+6+chnksz)));
            }
            else
            {
                        recompinded = data;
            }


            if( verifyPresetData(recompinded,_progressDialog,_devDetails) == true )
            {    
                _progressDialog->inc();
                _midiDataList.append(recompinded);
                _machine->postEvent(new DataXfer_ACKEvent());
            }
            else
            {
                _machine->postEvent(new DataXfer_NACKEvent()); 
            }
        }
        else
        {
            DCLOG() << "Unexpected data received after preset read";
            DCLOG() << data.toString();
            _progressDialog->setError("Unexpected data received after requesting the preset.");
            _machine->postEvent(new DataXfer_NACKEvent());
        }
    }
}
Beispiel #9
0
//-------------------------------------------------------------------------
void DcXferMachine::replySlotForDataOut( const DcMidiData &data )
{
    // Expect to see sysex coming from the currently attached device.
    // This check will prevent other legal messages from blowing up
    // out preset transfer - like controller messages
    if(data.contains(_devDetails->SOXHdr))
    {
        bool NAK = data.match(_devDetails->PresetWr_NAK);
        bool ACK = data.match(_devDetails->PresetWr_ACK);
        
        // If it's not an ACK or NAK, then just ignore the response data
        if(!(NAK || ACK))
        {
            // Check for a strymon MIDITH
            if(data == _activeCmd)
            {
                return;
            }
            
            // This is an unexpected Sysex message, it has a valid strymon HDR, 
            // but the payload was unexpected.
            DCLOG() << "Ignoring unexpected/invalid Strymon Sysex message";
            DCLOG() << "    Sent: " << _activeCmd.toString();
            DCLOG() << "Received: " << data.toString();
            return;
        }

        // This is the response we were looking for, cancel the transfer timeout watchdog
        _watchdog.stop();
        
        // Check for write preset Negative Acknowledgment
        if(NAK)
        {
            if(--_retryCount < 0)
            {
                DCLOG() << "NAK - retries exhausted - notify user and bail";
                _progressDialog->setError("Device Rejected Write Command");
                _machine->postEvent(new DataXfer_NACKEvent());
            }
            else
            {
                // Retry the Write Command
                QThread::msleep(100);

                // Will this be the last try?  Also, if midiOut is not in 'safe mode'
                // throttle back the output rate to work around troubled MIDI host adapters.
                if(!_midiOut->isSafeMode())
                {
                    DCLOG() << "Throttling back MIDI output rate";
                    _midiOut->setSafeMode();
                    _progressDialog->setIoHealth( 1 );
                }

                DCLOG() << "NAK - retry count at " << _retryCount;
                _midiOut->dataOutThrottled(_activeCmd);

                // Restart watchdog
                _watchdog.start(_timeout);
            }
        }
        else if(ACK)
        {
            _progressDialog->inc();
            _progressDialog->setError("");
            QApplication::processEvents();

            if( _retryCount < _numRetries )
            {
               DCLOG() << QString("Success after %1 retries").arg(_numRetries - _retryCount);
            }

            _writeSuccessList.append(_activeCmd);
            _machine->postEvent(new DataXfer_ACKEvent());
        }
        else
        {
            // Getting here means an unexpected message was received.
            DCLOG() << "Unexpected data received after preset write";
            DCLOG() << "    Sent: " << _activeCmd.toString();
            DCLOG() << "Received: " << data.toString();

            _progressDialog->setError("Unexpected data after preset write");
            _machine->postEvent(new DataXfer_NACKEvent());
        }
    }
}
Beispiel #10
0
//-------------------------------------------------------------------------
bool DcBootControl::enableBootcode( )
{
    QRtMidiData md;

    QRtMidiData responceData;

    // The device is in boot mode if it responses to the Echo command.
    if(isBootcode())
    {
        return true;
    }

    QRtMidiData priRst = makePrivateResetCmd();
    if(0 == priRst.length())
        return false;

    QRtMidiTrigger tc(RESPONCE_ENABLE_RECOVERY_ANY);
    QRtAutoTrigger autoch(&tc,_pMidiIn);

    // Issue a private reset
    _pMidiOut->dataOut(priRst);

    QThread::msleep(100);

    // Issue "enable recovery" no more than 300ms after reset to keep the device in boot code.
    for (int idx = 0; idx < 40 ; idx++)
    {
        _pMidiOut->dataOut(CMD_ENABLE_RECOVERY);
        QThread::msleep(20);
        if(tc.dequeue(responceData))
        {
            break;
        }
    }

    bool rtval = false;
    if(responceData.match(RESPONCE_ENABLE_RECOVERY_ACK))
    {
        // Verify device is in boot code
        if(!isBootcode())
        {
            DCLOG() << "Failed to verify device is in boot code";
        }
        else
        {
            DCLOG() << "Device is running boot code";
            rtval = true;
        }

    }
    else if(responceData.match(RESPONCE_ENABLE_RECOVERY_REJECTED))
    {
        DCLOG() << "The device has rejected the enable recovery command";
    }
    else if(responceData.match(RESPONCE_ENABLE_RECOVERY_FAILED))
    {
        DCLOG() << "Device has failed the enabled recovery command";
    }
    else
    {
        DCLOG() << "Timeout entering boot code";
    }
    return rtval;
}
Beispiel #11
0
bool DcBootControl::enableBootcode( )
{
    DcMidiData md;
   
    DcMidiData responceData;

    // The device is in boot mode if it responses to the Echo command.
    if(isBootcode())
    {
        return true;
    }
    
    DcMidiData priRst = makePrivateResetCmd();
    if(0 == priRst.length())
    {
        return false;
    }


    DcMidiTrigger tc( _blindMode ? "F0 00 01 55" : RESPONCE_ENABLE_RECOVERY_ANY );
    DcAutoTrigger autoch(&tc,_pMidiIn);
    
    if( _blindMode )
    {
        DCLOG() << "Attempting to enable boot code in blind mode";
    }
    
    // Issue a private reset
    _pMidiOut->dataOut(priRst);

    QThread::msleep(100);
    
    // Issue "enable recovery" no more than 300ms after reset to keep the device in boot code.
    for (int idx = 0; idx < 40 ; idx++)
    {
    	_pMidiOut->dataOut(CMD_ENABLE_RECOVERY);
        QThread::msleep(20);
        if(tc.dequeue(responceData))
        {
            break;
        }
    }

    
    bool rtval = false;
    if(_blindMode )
    {
        DCLOG() << "Device is running 'blind mode' boot code";
        rtval = true;
    }
    else
    {
        
        if( responceData.match( RESPONCE_ENABLE_RECOVERY_ACK ) )
        {
            // Verify device is in boot code
            if( !isBootcode() )
            {
                DCLOG() << "Failed to verify device is in boot code";
                // Just send a reset in case status was lost
                _pMidiOut->dataOut( "F0 00 01 55 42 01 F7" );
            }
            else
            {
                DCLOG() << "Device is running boot code";
                rtval = true;
            }
        }
        else if( responceData.match( RESPONCE_ENABLE_RECOVERY_REJECTED ) )
        {
            DCLOG() << "The device has rejected the enable recovery command";
        }
        else if( responceData.match( RESPONCE_ENABLE_RECOVERY_FAILED ) )
        {
            DCLOG() << "Device has failed the enabled recovery command";
        }
        else
        {
            // Never saw the requested responce from the device
            // Who knows what's going on now - incase the device is in boot-mode
            // Send a reset command.
            _pMidiOut->dataOut( "F0 00 01 55 42 01 F7" );

            DCLOG() << "Timeout entering boot code";
        }
    }
    return rtval;
}
Beispiel #12
0
bool DcBootControl::writeFirmwareUpdateMsg(DcMidiData& msg,int timeOutMs /*= 2000*/)
{
    bool rtval = false;

    DcAutoTrigger autotc( _blindMode ? "F0 00 01 55" : kFUResponcePattern ,_pMidiIn );

    
    // Magic number 8 is the response control flags, a 3 will deliver status.
    msg[8] = 0x03;
//     if(_blindMode )
//     {
//         DCLOG() << "SEND: " << msg.toString(' ');
//     }
     _pMidiOut->dataOut(msg);

    DcMidiData md;

    // Wait for the response data, or timeout after 300ms
    if(autotc.wait(timeOutMs))
    {
        if(autotc.dequeue(md))
        {

          if(_blindMode )
            {
                if(md.match("F0 00 01 55 42 00") )
                {
                    md = kFUGood;
                }
                else if(md.match("F0 00 01 55 42 01") )
                {
                    DCLOG() << "RECVD: " << md.toString(' ');
                    md = kFUBad;
                }
                else if(md.match("F0 00 01 55 42 02"))
                {
                    DCLOG() << "RECVD: " << md.toString(' ');
                    md = kFUFailed;
                }
            }

            if( md == kFUGood )
            {
                rtval = true;
            }
            else if( md == kFUBad )
            {
                DCLOG() << "kFUBad";
                _lastErrorMsg << "Device reject firmware command - BAD packet.";
            }
            else if( md == kFUFailed )
            {
                DCLOG() << "kFUFailed";
                _lastErrorMsg << "Device failed firmware command.";
            }
            else
            {
                DCLOG() << "Unknown response: " << md.toString( ' ' ) << "\n";
                _lastErrorMsg << "Firmware write generated an unknown response from the device.";
            }
        }
    }
    else
    {
        DCLOG() << "Timeout waiting on " << msg.toString(' ') << "\n";
        _lastErrorMsg << "Firmware update failure - timeout after write command.\n" << msg.toString(' ').mid(15,38);
    }

    return rtval;
}