//! 2.2.6.1 Write Value to Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_DECLSPEC
DiReturnT DiRegisterWrite ( DiUInt32T        dnRegNumber,
                            DiRegisterValueT drvValue ) {
   LOGGING;
   U32c  value(drvValue);
   USBDM_ErrorCode rc = BDM_RC_OK;

   log.print("DiRegisterWrite(0x%X(%d) <= 0x%08X)\n", dnRegNumber, dnRegNumber, (uint32_t)value);

   CHECK_ERROR_STATE();

   if (dnRegNumber > S12Z_RegCCR) {
      return setErrorState(DI_ERR_PARAM, ("Illegal register identifier"));
   }
   rc = USBDM_WriteReg(dnRegNumber,  value);
   if ((dnRegNumber == S12Z_RegPC) && !pcWritten) {
      log.print("Saving initial PC write = 0x%08X)\n", (uint32_t)value);
      pcWritten    = true;
      pcResetValue = value;
   }
   if (rc != BDM_RC_OK) {
      log.error("0x%X Failed, reason= %s\n",
           dnRegNumber, USBDM_GetErrorString(rc));
      return setErrorState(DI_ERR_NONFATAL, rc);
   }
   return setErrorState(DI_OK);
}
/*
 * Class:     net.sourceforge.usbdm.jni.usbdm
 * Method:    usbdm_getErrorString
 * Signature: (I)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL
Java_net_sourceforge_usbdm_jni_Usbdm_usbdmGetErrorString(JNIEnv *env, jclass, jint errorNum) {

   const char *message = USBDM_GetErrorString((USBDM_ErrorCode(errorNum)));

   return env->NewStringUTF(message);
}
static USBDM_ErrorCode callBack(const char *msg, GdbMessageLevel level, USBDM_ErrorCode rc) {
   if (level >= M_ERROR) {
      displayDialogue(USBDM_GetErrorString(rc), msg, wxOK|wxICON_ERROR);
      serverError = rc;
   }
   return rc;
}
//! 2.2.6.2 Read Value from Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_API
DiReturnT DiRegisterRead ( DiUInt32T         dnRegNumber,
                           pDiRegisterValueT drvValue ) {
    unsigned long dataValue = 0xDEADBEEF;
    DSC_Registers_t regNum = mapReg(dnRegNumber);
    USBDM_ErrorCode rc = BDM_RC_OK;

//   Logging::print("DiRegisterRead(reg# 0x%X(%d))\n", regNum, regNum);
//   Logging::print("DiRegisterRead(%s)\n", DSC_GetRegisterName(regNum));

    CHECK_ERROR_STATE();

    if (regNum == DSC_UnknownReg) {
        dataValue = dnRegNumber;
//      rc = BDM_RC_OK;
        rc = BDM_RC_ILLEGAL_PARAMS;
    }
    else {
        rc = DSC_ReadRegister(regNum, &dataValue);
    }
    if (rc != BDM_RC_OK) {
        Logging::print("DiRegisterRead(0x%X,%s) Failed, reason= %s\n",
                       dnRegNumber, DSC_GetRegisterName(regNum), USBDM_GetErrorString(rc));
        return setErrorState(DI_ERR_NONFATAL, rc);
    }
    *drvValue = (U32c)dataValue;
    Logging::print("DiRegisterRead(0x%X,%s) => %lX\n", dnRegNumber, DSC_GetRegisterName(regNum), dataValue);
    return setErrorState(DI_OK);
}
//! 2.2.6.1 Write Value to Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_API
DiReturnT DiRegisterWrite ( DiUInt32T        dnRegNumber,
                            DiRegisterValueT drvValue ) {
    LOGGING;
    U32c            regValue(drvValue);
    DSC_Registers_t regNum = mapReg(dnRegNumber);
    USBDM_ErrorCode rc = BDM_RC_OK;

    Logging::print("DiRegisterWrite(0x%lX,%s) => %lX\n", (unsigned long)dnRegNumber, DSC_GetRegisterName(regNum), (unsigned long)regValue);

    CHECK_ERROR_STATE();

    if ((regNum == DSC_RegPC) && !pcWritten) {
        pcWritten    = true;
        pcResetValue = regValue;
    }
    if (regNum == DSC_UnknownReg) {
//      rc = BDM_RC_OK;
        rc = BDM_RC_ILLEGAL_PARAMS;
    }
    else {
        rc = DSC_WriteRegister(regNum, (uint32_t)regValue);
    }
    if (rc != BDM_RC_OK) {
        Logging::print("DiRegisterWrite(0x%X,%s) Failed, reason= %s\n",
                       dnRegNumber, DSC_GetRegisterName(regNum), USBDM_GetErrorString(rc));
        return setErrorState(DI_ERR_NONFATAL, rc);
    }
    return setErrorState(DI_OK);
}
//! 2.2.6.2 Read Value from Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_DECLSPEC
DiReturnT DiRegisterRead ( DiUInt32T         dnRegNumber,
                           pDiRegisterValueT drvValue ) {
   LOGGING;
   unsigned long     dataValue = 0xDEADBEEF;
   DSC_Registers_t regNum = mapReg(dnRegNumber);
   USBDM_ErrorCode   rc        = BDM_RC_OK;
   log.print("0x%X(%d)\n", dnRegNumber, dnRegNumber);
//   log.print("DiRegisterRead(%s)\n", DSC_GetRegisterName(regNum));

   CHECK_ERROR_STATE();

   if (regNum == DSC_UnknownReg) {
      dataValue = dnRegNumber;
//      rc = BDM_RC_OK;
      rc = BDM_RC_ILLEGAL_PARAMS;
   }
   else {
      rc = bdmInterface->readReg(regNum, &dataValue);
   }
   if (rc != BDM_RC_OK) {
      log.print("DiRegisterRead(0x%X,%s) Failed, reason= %s\n",
            dnRegNumber, getDSCRegName(regNum), USBDM_GetErrorString(rc));
      return setErrorState(DI_ERR_NONFATAL, rc);
   }
   *drvValue = (U32c)dataValue;
   log.print("(0x%X,%s) => %8lX\n", dnRegNumber, getDSCRegName(regNum), dataValue);
   return setErrorState(DI_OK);
}
//! Check error code from USBDM API function
//!
//! @param rc - error code to access
//!
//! An error message is printed with line # and the program exited if
//! rc indicates any error
//!
void check(USBDM_ErrorCode rc, const char *file = NULL, unsigned lineNum = 0) {
   if (rc == BDM_RC_OK) {
      fprintf(stderr, "OK,     [%s:#%4d]\n", file, lineNum);
      return;
   }
   fprintf(stderr, "Failed, [%s:#%4d] Reason= %s\n", file, lineNum,  USBDM_GetErrorString(rc));
   USBDM_Close();
   USBDM_Exit();
   exit(rc);
}
/*!  Report error message
 *
 *   @param msg   Message to display
 *   @param rc    Error code
 */
USBDM_ErrorCode GdbServerWindow::reportError(const char *msg, GdbMessageLevel level, USBDM_ErrorCode rc) {

   if ((rc != BDM_RC_OK) || (level >= getLoggingLevel())) {
      statusTextControl->AppendText(wxString(msg, wxConvUTF8));
      if (level == M_FATAL) {
         setDeferredFail();
      }
   }
   if (level&M_DIALOGUE) {
      Iconize(false); // restore the window if minimized
      SetFocus();     // focus on my window
      Raise();        // bring window to front
      Show(true);     // show the window
      wxMessageBox(
         wxString(msg, wxConvUTF8),                      /* message */
         wxString("Message", wxConvUTF8),                /* caption */
         wxOK|wxICON_ERROR,                              /* style   */
         this                                            /* parent  */
         );
   }
   if (rc != BDM_RC_OK) {
      statusTextControl->AppendText(wxString(USBDM_GetErrorString(rc), wxConvUTF8));
      statusTextControl->AppendText(_("\n"));

      Iconize(false); // restore the window if minimized
      SetFocus();     // focus on my window
      Raise();        // bring window to front
      Show(true);     // show the window
      wxMessageBox(
         wxString(USBDM_GetErrorString(rc), wxConvUTF8), /* message */
         wxString(msg, wxConvUTF8),                      /* caption */
         wxOK|wxICON_ERROR,                              /* style   */
         this                                            /* parent  */
         );
   }
   return rc;
}
//! Clock register write with retry
//!
//! @param addr : clock register address
//! @param data : byte to write
//!
//! @return BDM_RC_OK => success
//!
//! @note writes are retried after a re-connect to cope
//!  with a possible clock speed change.
//!
USBDM_ErrorCode writeClockRegister(uint32_t addr, uint8_t data) {
   LOGGING_Q;
   USBDM_ErrorCode rc;

   rc = USBDM_WriteMemory(1,1,addr,&data);
   if (rc != BDM_RC_OK) {
      Logging::print("Failed write 0x%04X <= 0x%02X) - retrying\n", addr, data);
      rc = USBDM_Connect();
      if (rc == BDM_RC_OK) {
         rc = USBDM_WriteMemory(1,1,addr,&data);
         if (rc != BDM_RC_OK) {
         }
      }
   }
   if (rc != BDM_RC_OK) {
      Logging::print("Failed write 0x%04X <= 0x%02X), rc = %s\n", addr, data, USBDM_GetErrorString(rc));
   }
   return rc;
}
//! 2.2.6.1 Write Value to Register
//!
//! @param dnRegNumber
//! @param drvValue
//!
USBDM_GDI_DECLSPEC
DiReturnT DiRegisterWrite ( DiUInt32T        dnRegNumber,
                            DiRegisterValueT drvValue ) {
   LOGGING;
   U32c            value(drvValue);
   USBDM_ErrorCode rc  = BDM_RC_OK;

   log.print("(0x%X(%d) <= 0x%08X)\n", dnRegNumber, dnRegNumber, (uint32_t)value);

   CHECK_ERROR_STATE();

   if (dnRegNumber>cfv1regID_FIRST_DEBUG_regID_BYTE) {
      switch (dnRegNumber) {
         case cfv1regID_xcsr_byte :
            rc = USBDM_WriteControlReg(value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "XCSR.byte", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         case cfv1regID_csr2_byte :
            rc = USBDM_WriteDReg(CFV1_DRegCSR2byte,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "CSR2.byte", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         case cfv1regID_csr3_byte :
            rc = USBDM_WriteDReg(CFV1_DRegCSR3byte,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "CSR3.byte", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         default                  :
            log.print("DiRegisterWrite(Illegal Reg# 0x%X(%d)\n", dnRegNumber, dnRegNumber);
            rc = BDM_RC_ILLEGAL_PARAMS;
            break;
      }
   }
   else if (dnRegNumber>cfv1regID_FIRST_DEBUG_REG) {
      int regNum = dnRegNumber-cfv1regID_FIRST_DEBUG_REG;
      rc = USBDM_WriteDReg(regNum,value);
      if (rc != BDM_RC_OK) {
         log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
               getCFV1DebugRegName(regNum), dnRegNumber, USBDM_GetErrorString(rc));
         return setErrorState(DI_ERR_NONFATAL, rc);
      }
   }
   else if (dnRegNumber > cfv1regID_FIRST_CONTROL_REG) {
      int regNum = dnRegNumber-cfv1regID_FIRST_CONTROL_REG;
      rc = USBDM_WriteCReg(regNum,value);
      if (rc != BDM_RC_OK) {
         log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
               getCFV1ControlRegName(regNum), dnRegNumber, USBDM_GetErrorString(rc));
         return setErrorState(DI_ERR_NONFATAL, rc);
      }
   }
   else {
      switch (dnRegNumber) {
         case cfv1regID_pc : /*  PC */
            if (!pcWritten) {
               log.print("Saving initial PC write = 0x%08X)\n", (uint32_t)value);
               pcWritten    = true;
               pcResetValue = value;
            }
            rc = USBDM_WriteCReg(CFV1_CRegPC,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "PC", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         case cfv1regID_sr :
            rc = USBDM_WriteCReg(CFV1_CRegSR,value);
            if (rc != BDM_RC_OK) {
               log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                     "SR", dnRegNumber, USBDM_GetErrorString(rc));
               return setErrorState(DI_ERR_NONFATAL, rc);
            }
            break;
         default : // D0-7, A0-7
            if (dnRegNumber>15) {
               log.print("DiRegisterWrite(Illegal Reg# 0x%X(%d)\n", dnRegNumber, dnRegNumber);
               rc = BDM_RC_ILLEGAL_PARAMS;
            }
            else {
               rc = USBDM_WriteReg(dnRegNumber,value);
               if (rc != BDM_RC_OK) {
                  log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n",
                        getCFV1RegName(dnRegNumber), dnRegNumber, USBDM_GetErrorString(rc));
                  return setErrorState(DI_ERR_NONFATAL, rc);
               }
            }
            break;
      }
   }
   if (rc != BDM_RC_OK) {
      log.error("0x%X Failed, reason= %s\n",
           dnRegNumber, USBDM_GetErrorString(rc));
      return setErrorState(DI_ERR_NONFATAL, rc);
   }
   return setErrorState(DI_OK);
}
//
// main
//
int main(int argc, char **argv) {
#ifdef __unix__
   // Load wxWindows Stub (for pop-up dialogues)
   (void)dlopen(WXSTUB_DLL_NAME, RTLD_NOW|RTLD_NODELETE);
#endif

#ifdef LOG
   char buff[1000];
   if (getUserDataDir(buff, sizeof(buff)) != 0) {
      strcpy(buff, "c:");
   }
   strcat(buff, "/gdbServer.log");
   FILE *errorLog = fopen(buff, "wt");
   Logging::setLogFileHandle(errorLog);
#endif
   Logging::setLoggingLevel(100);
   LOGGING;

#ifdef LOG
   Logging::print("Args = ");
   for (int index=0; index<argc; index++) {
      Logging::printq("%s ", argv[index]);
   }
   Logging::printq("\n");
#endif
   if (signal(SIGINT, signalHandler) == SIG_IGN) {
      (void)signal(SIGINT, SIG_IGN);
   }

   shared = SharedPtr(new Shared(TARGET_TYPE));

   USBDM_ErrorCode rc = doArgs(argc, argv);
   if (rc != BDM_RC_OK) {
      Logging::print("Error %s\n", USBDM_GetErrorString(rc));
      exit (-1);
   }
   Logging::print("After doArgs\n");

   rc = shared->initBdm();
   if (rc != BDM_RC_OK) {
      Logging::print("Error %s\n", USBDM_GetErrorString(rc));
      exit (-1);
   }
   Logging::print("After shared->initBdm()\n");
   //   setDefaultWindowParent(FindEclipseWindowHwnd());

   GdbInOutPipe  *gdbInOut  = GdbInOutPipe::getGdbInOut();
   Logging::print("After GdbInOutPipe::getGdbInOut()\n");

   // Redirect stdout to stderr
   dup2(2,1);

   if (gdbInOut == NULL) {
      Logging::print("Error gdbInOut() creation failed\n");
      exit (-1);
   }
   Logging::print("After gdbInOut()\n");

   // Now do the actual processing of GDB messages
   gdbHandlerInit(gdbInOut, *shared->getCurrentDevice(), callBack);
   gdbLoop(gdbInOut);

   gdbInOut->finish();
   delete gdbInOut;

   return 0;
}
//! \brief Does Bulk Erase of Target Flash.
//!
//! @return error code, see \ref FlashError_t
//!
//! @note The target is not reset so current security state persists after erase.
//!
USBDM_ErrorCode HCS12Unsecure::bulkEraseMemory() {
   const uint8_t allOnes        = 0xFF;
   const uint8_t allZeroes      = 0x00;
   uint8_t dummyFlashAddress[]  = {0xFF, 0xFE};
   uint8_t dummyEepromAddress[] = {0x0C, 0x00};
   uint8_t dummyFlashData[]     = {0xFF, 0xFF};
   int timeout;
   uint8_t statValue;
   USBDM_ErrorCode rc;

   print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target...\n");

   // Erase chip
   //=============================

   // Set up flash & eeprom
   rc = initialiseTargetFlash();
   if (rc != BDM_RC_OK) {
      print("HCS12Unsecure::bulkEraseMemory(): initialiseTargetFlash() failed, reason=%s\n",
            USBDM_GetErrorString(rc));
      return rc;
   }

   print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target Flash...\n");
   // Apply Bulk Erase operation to all Flash banks
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFPROTAddress(),   &allOnes);
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(),   &HCS12_clearFlashErrors);
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes);
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(),   &HCS12_clearFlashErrors);
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &HCS12_FTSTMOD_WRALL);
   USBDM_WriteMemory(2, 2, HCS12DeviceData::getFADDRAddress(),   dummyFlashAddress);
   USBDM_WriteMemory(2, 2, HCS12DeviceData::getFDATAAddress(),   dummyFlashData);
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFCMDAddress(),    &mMassErase);
   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(),   &startFlashCommand);

   // Wait for flash command to complete
   timeout = 10;
   do {
      // Mass erase should take ~100ms
      wxMilliSleep(100);
      if (USBDM_ReadMemory(1,1,HCS12DeviceData::getFSTATAddress(),&statValue) != BDM_RC_OK)
         return BDM_RC_FAIL;
      if (timeout-- == 0)
         return BDM_RC_FAIL;
   } while ((statValue & 0xC0) != 0xC0);

   USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes);

   if (hasEEPROM) {
      print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target EEPROM...\n");
      // Apply Bulk Erase operation to EEPROM
      USBDM_WriteMemory(1, 1, HCS12DeviceData::getEPROTAddress(),   &allOnes);
      USBDM_WriteMemory(1, 1, HCS12DeviceData::getESTATAddress(),   &HCS12_clearFlashErrors);
      USBDM_WriteMemory(2, 2, HCS12DeviceData::getEADDRAddress(),   dummyEepromAddress);
      USBDM_WriteMemory(2, 2, HCS12DeviceData::getEDATAAddress(),   dummyFlashData);
      USBDM_WriteMemory(1, 1, HCS12DeviceData::getECMDAddress(),    &mMassErase);
      USBDM_WriteMemory(1, 1, HCS12DeviceData::getESTATAddress(),   &startFlashCommand);

      // Wait for flash command to complete
      timeout = 10;
      do {
         // Mass erase should take ~100ms
         wxMilliSleep(100);
         if (USBDM_ReadMemory(1,1,HCS12DeviceData::getESTATAddress(),&statValue) != BDM_RC_OK)
            return BDM_RC_FAIL;
         if (timeout-- == 0)
            return BDM_RC_FAIL;
      } while ((statValue & 0xC0) != 0xC0);
   }
   USBDM_TargetReset((TargetMode_t)(RESET_HARDWARE|RESET_SPECIAL));

   unsigned long usbdmStatus;
   USBDM_ReadStatusReg(&usbdmStatus);

   if ((usbdmStatus & HC12_BDMSTS_UNSEC) != 0) {
      print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target memory...Complete\n");
      return BDM_RC_OK;
   }
   else {
      print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target memory...Failed!\n");
      return BDM_RC_FAIL;
   }
}
//!  2.2.8.6 Get DI Execution/Exit Status
//!
//! @param pdesExitStatus
//!
//! @return \n
//!     DI_OK              => OK \n
//!     DI_ERR_FATAL       => Error see \ref currentErrorString
//!
USBDM_GDI_API
DiReturnT DiExecGetStatus ( pDiExitStatusT pdesExitStatus ) {
    LOGGING;
    USBDM_ErrorCode BDMrc;
    static DiExitCauseT lastStatus = DI_WAIT_USER;
    static int pollCount = 0;
    OnceStatus_t onceStatus;
//   Logging::print("DiExecGetStatus()\n");

    // Defaults
    pdesExitStatus->dscCause = DI_WAIT_UNKNOWN;
    pdesExitStatus->dwBpId   = 0x1000400; // bkpt ID?
    pdesExitStatus->szReason = (DiStringT)"unknown state";

// Removed as prevents CW retry strategy
//   CHECK_ERROR_STATE();

    // Update status or autoconnect (includes status update)
//   if (bdmOptions.autoReconnect)
//      DIrc = targetConnect();
//   else
//      DIrc = getBDMStatus(&USBDMStatus);

//   if (DIrc != DI_OK) {
//      Logging::print("DiExecGetStatus()=> connect()/getStatus() failed\n");
//      return DIrc;
//   }

    pdesExitStatus->szReason = (DiStringT)getBDMStatusName(&USBDMStatus);

    BDMrc = DSC_GetStatus(&onceStatus);
    if (BDMrc != BDM_RC_OK) {
        Logging::print("DiExecGetStatus() - Failed, BDMrc=%s\n", USBDM_GetErrorString(BDMrc));
        return setErrorState(DI_ERR_NONFATAL, BDMrc);
    }

    switch (onceStatus) {
    case stopMode:
    case debugMode:
    case unknownMode:
    default:
        // Halted - in debug halted mode
        pdesExitStatus->dscCause = DI_WAIT_UNKNOWN; // for DSC
        pdesExitStatus->szReason = (DiStringT)"Debug Halted";
        if ((lastStatus != pdesExitStatus->dscCause) || (pollCount++>20)) {
            pollCount = 0;
            Logging::print("DiExecGetStatus() - %s\n", DSC_GetOnceStatusName(onceStatus));
            Logging::print("DiExecGetStatus() status change => DI_WAIT_MISCELLANEOUS, (%s)\n",
                           pdesExitStatus->szReason);
        }
        break;
    case executeMode :
    case externalAccessMode:
        // Processor executing
        pdesExitStatus->dscCause = DI_WAIT_RUNNING;
        pdesExitStatus->szReason = (DiStringT)"Running";
        if ((lastStatus != pdesExitStatus->dscCause) || (pollCount++>20)) {
            pollCount = 0;
            Logging::print("DiExecGetStatus() - %s\n", DSC_GetOnceStatusName(onceStatus));
            Logging::print("DiExecGetStatus() status change => DI_WAIT_RUNNING, (%s)\n",
                           pdesExitStatus->szReason);
        }
        break;
    }
    lastStatus = pdesExitStatus->dscCause;
    return setErrorState(DI_OK);
}
/*!
 *  Handler for Socket events (after connection)
 *
 *  - Only expects:
 *    - wxSOCKET_INPUT - New data
 *    - wxSOCKET_LOST  - Connection dropped
 *
 *  @param event Event to handle
 */
void GdbServerWindow::OnSocketEvent(wxSocketEvent& event) {

   if (event.GetSocket() != clientSocket) {
      statusTextControl->AppendText(_("Event from unknown socket\n"));
      return;
   }
   // Now we process the event
   switch(event.GetSocketEvent()) {
      case wxSOCKET_INPUT: {
         if (clientSocket != NULL) {
            clientSocket->SetNotify(wxSOCKET_LOST_FLAG);
         }
         if (deferredOpen) {
            // Open on first access after socket creation
            deferredOpen = false;

            USBDM_ErrorCode rc = shared->initBdm();
            if (rc != BDM_RC_OK) {
               reportError("BDM Open failed, reason: ", M_FATAL, rc);
               statusTextControl->AppendText(_("BDM Open failed\n"));
               Logging::print("GdbServerWindow::OnSocketEvent() - BDM Open failed\n");
               dropConnection();
               return;
            }

            gdbInOut = new GdbInOutWx(clientSocket, statusTextControl);
            GdbCallback cb = GdbMessageWrapper::getCallBack(this);

            rc = gdbHandlerInit(gdbInOut, *shared->getCurrentDevice(), cb);
            if (rc != BDM_RC_OK) {
               reportError("GDB Handler initialisation failed, reason: ", M_FATAL, rc);
               Logging::print("GdbServerWindow::OnSocketEvent() - GDB Handler initialisation failed\n");
               dropConnection();
               return;
            }
            statusTextControl->AppendText(_("BDM Open OK\n"));
         }
         // Triggers read of socket
         const GdbPacket *packet;
         USBDM_ErrorCode rc = BDM_RC_OK;
         do {
            // Process packets from GDB until idle
            packet = gdbInOut->getGdbPacket();
            if (packet != NULL) {
               rc = doGdbCommand(packet);
               if (rc != BDM_RC_OK) {
                  statusTextControl->AppendText(wxString(USBDM_GetErrorString(rc),wxConvUTF8));
               }
            }
         } while ((packet != NULL) && (rc == BDM_RC_OK) && !deferredFail);

         if (deferredFail) {
            // A fatal error was reported - drop connection
            Logging::print("GdbServerWindow::OnSocketEvent() - deferredFail\n");
            dropConnection();
         }
         else {
            // Poll target immediately (also adjusts polling rate)
            pollTarget();
         }
         if (clientSocket != NULL) {
            clientSocket->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
         }
         break;
      }
      case wxSOCKET_LOST: {
         serverState = listening;
         Logging::print("GdbServerWindow::OnSocketEvent() - wxSOCKET_LOST\n");
         dropConnection();
         break;
      }
      default:
         statusTextControl->AppendText(_("Unexpected event on socket!\n"));
         break;
   }
   UpdateStatusBar();
}