예제 #1
0
void *
deviceLevel1WriteThread(void *pData)
{
    // Level1MsgOutList::compatibility_iterator nodeLevel1;

    CDeviceItem *pDevItem = (CDeviceItem *)pData;
    if (NULL == pDevItem) {
        syslog(LOG_CRIT,
               "deviceLevel1WriteThread quitting due to NULL DevItem object.");
        return NULL;
    }

    // Blocking send method must have been found
    if (NULL == pDevItem->m_proc_CanalBlockingSend) return NULL;

    while (!pDevItem->m_bQuit) {

        // Wait until there is something to send
        if ((-1 == vscp_sem_wait(
                     &pDevItem->m_pClientItem->m_semClientInputQueue, 500)) &&
            errno == ETIMEDOUT) {
            continue;
        }

        if (pDevItem->m_pClientItem->m_clientInputQueue.size()) {

            pthread_mutex_lock(
              &pDevItem->m_pClientItem->m_mutexClientInputQueue);
            vscpEvent *pqueueEvent =
              pDevItem->m_pClientItem->m_clientInputQueue.front();
            pDevItem->m_pClientItem->m_clientInputQueue.pop_front();
            pthread_mutex_unlock(
              &pDevItem->m_pClientItem->m_mutexClientInputQueue);

            // Trow away event if Level II and Level I interface
            if ((CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1 ==
                 pDevItem->m_pClientItem->m_type) &&
                (pqueueEvent->vscp_class > 512)) {
                vscp_deleteVSCPevent(pqueueEvent);
                continue;
            }

            canalMsg canalMsg;
            vscp_convertEventToCanal(&canalMsg, pqueueEvent);
            if (CANAL_ERROR_SUCCESS ==
                pDevItem->m_proc_CanalBlockingSend(
                  pDevItem->m_openHandle, &canalMsg, 300)) {
                vscp_deleteVSCPevent(pqueueEvent);
            } else {
                // Give it another try
                sem_post(&pDevItem->m_pCtrlObject->m_semClientOutputQueue);
            }

        } // events in queue

    } // while

    return NULL;
}
예제 #2
0
파일: vscpbtdetect.cpp 프로젝트: ajje/vscp
bool CVSCPBTDetectWrkTread::sendEvent( vscpEventEx& eventEx )
{
    vscpEvent *pEvent = new vscpEvent();
    if ( NULL != pEvent ) {

        if ( vscp_convertVSCPfromEx( pEvent, &eventEx ) ) {

            // OK send the event
            m_pObj->m_mutexReceiveQueue.Lock();
            m_pObj->m_receiveList.push_back( pEvent );
            m_pObj->m_semReceiveQueue.Post();
            m_pObj->m_mutexReceiveQueue.Unlock();

        }
        else {
            vscp_deleteVSCPevent( pEvent );
#ifndef WIN32
            syslog( LOG_ERR,
                    "%s",
                    ( const char * ) "Faild to convert event." );
#endif
            return false;
        }

    }

    return true;
}
예제 #3
0
파일: vscpbtdetect.cpp 프로젝트: ajje/vscp
extern "C" int
VSCPBlockingReceive( long handle, vscpEvent *pEvent, unsigned long timeout )
{
    int rv = 0;

    // Check pointer
    if ( NULL == pEvent ) return CANAL_ERROR_PARAMETER;

    CVSCPBTDetect *pdrvObj = theApp->getDriverObject( handle );
    if ( NULL == pdrvObj ) return CANAL_ERROR_MEMORY;

    if ( wxSEMA_TIMEOUT == pdrvObj->m_semReceiveQueue.WaitTimeout( timeout ) ) {
        return CANAL_ERROR_TIMEOUT;
    }

    pdrvObj->m_mutexReceiveQueue.Lock();
    vscpEvent *pLocalEvent = pdrvObj->m_receiveList.front();
    pdrvObj->m_receiveList.pop_front();
    pdrvObj->m_mutexReceiveQueue.Unlock();
    if ( NULL == pLocalEvent ) return CANAL_ERROR_MEMORY;

    vscp_copyVSCPEvent( pEvent, pLocalEvent );
    vscp_deleteVSCPevent( pLocalEvent );

    return CANAL_ERROR_SUCCESS;
}
extern "C" int
VSCPBlockingReceive(long handle, vscpEvent *pEvent, unsigned long timeout)
{
	int rv = 0;
 
    // Check pointer
    if ( NULL == pEvent) return CANAL_ERROR_PARAMETER;
    
	CRpiLCD *pdrvObj = theApp.getDriverObject(handle);
	if (NULL == pdrvObj) return CANAL_ERROR_MEMORY;
    
	struct timespec ts;
	ts.tv_sec = 0;
	ts.tv_nsec = timeout * 1e6;
	if ( ETIMEDOUT == sem_timedwait( &pdrvObj->m_semaphore_ReceiveQueue, &ts ) ) {
        return CANAL_ERROR_TIMEOUT;
    }
    
	pthread_mutex_lock( &pdrvObj->m_mutex_ReceiveQueue );
    vscpEvent *pLocalEvent = pdrvObj->m_receiveList.front();
    pdrvObj->m_receiveList.pop_front();
	pthread_mutex_unlock( &pdrvObj->m_mutex_ReceiveQueue );
    if ( NULL == pLocalEvent ) return CANAL_ERROR_MEMORY;
    
    vscp_copyVSCPEvent( pEvent, pLocalEvent );
    vscp_deleteVSCPevent( pLocalEvent );
	
	return CANAL_ERROR_SUCCESS;
}
extern "C" int
VSCPBlockingReceive(long handle, vscpEvent *pEvent, unsigned long timeout)
{
	int rv = 0;
 
    // Check pointer
    if ( NULL == pEvent) return CANAL_ERROR_PARAMETER;
    
	CTcpipLink *pdrvObj = theApp.getDriverObject(handle);
	if (NULL == pdrvObj) return CANAL_ERROR_MEMORY;
    
    if ( wxSEMA_TIMEOUT == pdrvObj->m_semReceiveQueue.WaitTimeout( timeout ) ) {
        return CANAL_ERROR_TIMEOUT;
    }
    
    //VSCPEVENTLIST_RECEIVE::compatibility_iterator nodeClient;

	pdrvObj->m_mutexReceiveQueue.Lock();
	//nodeClient = pdrvObj->m_receiveQueue.GetFirst();
	//vscpEvent *pLocalEvent = nodeClient->GetData();
    vscpEvent *pLocalEvent = pdrvObj->m_receiveList.front();
    pdrvObj->m_receiveList.pop_front();
	pdrvObj->m_mutexReceiveQueue.Unlock();
    if (NULL == pLocalEvent) return CANAL_ERROR_MEMORY;
    
    vscp_copyVSCPEvent( pEvent, pLocalEvent );
    //pdrvObj->m_receiveQueue.DeleteNode(nodeClient);
    vscp_deleteVSCPevent( pLocalEvent );
	
	return CANAL_ERROR_SUCCESS;
}
예제 #6
0
CClientItem::~CClientItem()
{
    CLIENTEVENTLIST::iterator iter;

    for ( iter = m_clientInputQueue.begin(); 
            iter != m_clientInputQueue.end(); ++iter ) {
        vscpEvent *pEvent = *iter;
        vscp_deleteVSCPevent( pEvent );
    }

    m_clientInputQueue.Clear();

}
예제 #7
0
void *deviceCanalWriteThread::Entry()
{

    CanalMsgOutList::compatibility_iterator nodeCanal;

    // Must be a valid main object pointer
    if (NULL == m_pMainThreadObj) return NULL;

    // Blocking send method must have been found
    if (NULL == m_pMainThreadObj->m_pDeviceItem->m_proc_CanalBlockingSend) return NULL;

    while (!TestDestroy() && !m_bQuit) {

        // Wait until there is something to send
        if (wxSEMA_TIMEOUT ==
            m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_semClientInputQueue.WaitTimeout(500)) {
            continue;
        }

        CLIENTEVENTLIST::compatibility_iterator nodeClient;

        if (m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetCount()) {

            m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Lock();
            nodeClient = m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetFirst();
            vscpEvent *pqueueEvent = nodeClient->GetData();
            m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Unlock();

            canalMsg canalMsg;
            vscp_convertEventToCanal(&canalMsg, pqueueEvent);
            if (CANAL_ERROR_SUCCESS ==
                m_pMainThreadObj->m_pDeviceItem->m_proc_CanalBlockingSend( m_pMainThreadObj->m_pDeviceItem->m_openHandle,
                                                                            &canalMsg, 300)) {
                // Remove the node
                vscp_deleteVSCPevent(pqueueEvent);
                m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient);
            }
            else {
                // Give it another try
                m_pMainThreadObj->m_pCtrlObject->m_semClientOutputQueue.Post();
            }

        } // events in queue

    } // while

    return NULL;
}
예제 #8
0
void *deviceLevel2ReceiveThread::Entry()
{
    vscpEvent *pEvent;

    // Must be a valid main object pointer
    if (NULL == m_pMainThreadObj) return NULL;

    int rv;
    while (!TestDestroy() && !m_bQuit) {

        pEvent = new vscpEvent;
        if (NULL == pEvent) continue;
        rv = m_pMainThreadObj->m_pDeviceItem->m_proc_VSCPBlockingReceive(
                    m_pMainThreadObj->m_pDeviceItem->m_openHandle, pEvent, 500);

        if ((CANAL_ERROR_SUCCESS != rv) || (NULL == pEvent)) {
            delete pEvent;
            continue;
        }

        // Identify ourselves
        pEvent->obid = m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientID;

        // If timestamp is zero we set it here
        if ( 0 == pEvent->timestamp ) {
            pEvent->timestamp = vscp_makeTimeStamp();
        }

        // If no GUID is set,
        //      - Set driver GUID if define
        //      - Set interface GUID if no driver GUID defined.

        uint8_t ifguid[16];

        // Save nickname
        uint8_t nickname_msb = pEvent->GUID[14];
        uint8_t nickname_lsb = pEvent->GUID[15];

        // Set if to use
        memcpy( ifguid, pEvent->GUID, 16 );
        ifguid[14] = 0;
        ifguid[15] = 0;

        // If if is set to zero use interface id
        if ( vscp_isGUIDEmpty( ifguid ) ) {

            // Set driver GUID if set
            if ( !m_pMainThreadObj->m_pDeviceItem->m_interface_guid.isNULL() ) {
                m_pMainThreadObj->m_pDeviceItem->m_interface_guid.writeGUID( pEvent->GUID );
            }
            else {
                // If no driver GUID set use interface GUID
                m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_guid.writeGUID( pEvent->GUID );
            }

            // Preserve nickname
            pEvent->GUID[14] = nickname_msb;
            pEvent->GUID[15] = nickname_lsb;

        }

        // There must be room in the receive queue (even if rom (or whisky) has been better)
        if (m_pMainThreadObj->m_pCtrlObject->m_maxItemsInClientReceiveQueue >
                m_pMainThreadObj->m_pCtrlObject->m_clientOutputQueue.GetCount()) {

            m_pMainThreadObj->m_pCtrlObject->m_mutexClientOutputQueue.Lock();
            m_pMainThreadObj->m_pCtrlObject->m_clientOutputQueue.Append(pEvent);
            m_pMainThreadObj->m_pCtrlObject->m_semClientOutputQueue.Post();
            m_pMainThreadObj->m_pCtrlObject->m_mutexClientOutputQueue.Unlock();

        }
        else {
            if (NULL == pEvent) vscp_deleteVSCPevent(pEvent);
        }

    }

    return NULL;
}
예제 #9
0
void *deviceThread::Entry()
{
    // Must have a valid pointer to the device item
    if (NULL == m_pDeviceItem) return NULL;

    // Must have a valid pointer to the control object
    if (NULL == m_pCtrlObject) return NULL;

    // We need to create a clientobject and add this object to the list
    m_pDeviceItem->m_pClientItem = new CClientItem;
    if (NULL == m_pDeviceItem->m_pClientItem) {
        return NULL;
    }

    // This is now an active Client
    m_pDeviceItem->m_pClientItem->m_bOpen = true;
    if ( VSCP_DRIVER_LEVEL2 == m_pDeviceItem->m_driverLevel ) {
        m_pDeviceItem->m_pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL2;
    }
    else {
        m_pDeviceItem->m_pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1;
    }
    m_pDeviceItem->m_pClientItem->m_strDeviceName = m_pDeviceItem->m_strName;
    m_pDeviceItem->m_pClientItem->m_strDeviceName += _(" Started at ");
    wxDateTime now = wxDateTime::Now();
    m_pDeviceItem->m_pClientItem->m_strDeviceName += now.FormatISODate();
    m_pDeviceItem->m_pClientItem->m_strDeviceName += _(" ");
    m_pDeviceItem->m_pClientItem->m_strDeviceName += now.FormatISOTime();

    m_pCtrlObject->logMsg(m_pDeviceItem->m_pClientItem->m_strDeviceName + _("\n"),
                            DAEMON_LOGMSG_DEBUG);

    // Add the client to the Client List
    m_pCtrlObject->m_wxClientMutex.Lock();
    m_pCtrlObject->addClient(m_pDeviceItem->m_pClientItem);
    m_pCtrlObject->m_wxClientMutex.Unlock();

    // Load dynamic library
    if (!m_wxdll.Load(m_pDeviceItem->m_strPath, wxDL_LAZY)) {
        m_pCtrlObject->logMsg(_("Unable to load dynamic library.\n") );
        return NULL;
    }

    if (VSCP_DRIVER_LEVEL1 == m_pDeviceItem->m_driverLevel) {

        // Now find methods in library

        {
            wxString str;
            str = _("Loading level I driver: ");
            str += m_pDeviceItem->m_strName;
            str += _("\n");
            m_pCtrlObject->logMsg(str);
            wxLogDebug(str);
        }

        // * * * * CANAL OPEN * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalOpen =
            (LPFNDLL_CANALOPEN) m_wxdll.GetSymbol(_T("CanalOpen")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalOpen.\n") );
            return NULL;
        }

        // * * * * CANAL CLOSE * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalClose =
            (LPFNDLL_CANALCLOSE) m_wxdll.GetSymbol(_T("CanalClose")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalClose.\n") );
            return NULL;
        }

        // * * * * CANAL GETLEVEL * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetLevel =
            (LPFNDLL_CANALGETLEVEL) m_wxdll.GetSymbol(_T("CanalGetLevel")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetLevel.\n") );
            return NULL;
        }

        // * * * * CANAL SEND * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalSend =
            (LPFNDLL_CANALSEND) m_wxdll.GetSymbol(_T("CanalSend")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSend.\n") );
            return NULL;
        }

        // * * * * CANAL DATA AVAILABLE * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalDataAvailable =
            (LPFNDLL_CANALDATAAVAILABLE) m_wxdll.GetSymbol(_T("CanalDataAvailable")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalDataAvailable.\n") );
            return NULL;
        }


        // * * * * CANAL RECEIVE * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalReceive =
            (LPFNDLL_CANALRECEIVE) m_wxdll.GetSymbol(_T("CanalReceive")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalReceive.\n") );
            return NULL;
        }

        // * * * * CANAL GET STATUS * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetStatus =
            (LPFNDLL_CANALGETSTATUS) m_wxdll.GetSymbol(_T("CanalGetStatus")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetStatus.\n") );
            return NULL;
        }

        // * * * * CANAL GET STATISTICS * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetStatistics =
            (LPFNDLL_CANALGETSTATISTICS) m_wxdll.GetSymbol(_T("CanalGetStatistics")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetStatistics.\n") );
            return NULL;
        }

        // * * * * CANAL SET FILTER * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalSetFilter =
            (LPFNDLL_CANALSETFILTER) m_wxdll.GetSymbol(_T("CanalSetFilter")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSetFilter.\n") );
            return NULL;
        }

        // * * * * CANAL SET MASK * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalSetMask =
            (LPFNDLL_CANALSETMASK) m_wxdll.GetSymbol(_T("CanalSetMask")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSetMask.\n") );
            return NULL;
        }

        // * * * * CANAL GET VERSION * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetVersion =
            (LPFNDLL_CANALGETVERSION) m_wxdll.GetSymbol(_T("CanalGetVersion")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetVersion.\n") );
            return NULL;
        }

        // * * * * CANAL GET DLL VERSION * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetDllVersion =
            (LPFNDLL_CANALGETDLLVERSION) m_wxdll.GetSymbol(_T("CanalGetDllVersion")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetDllVersion.\n") );
            return NULL;
        }

        // * * * * CANAL GET VENDOR STRING * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetVendorString =
            (LPFNDLL_CANALGETVENDORSTRING) m_wxdll.GetSymbol(_T("CanalGetVendorString")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetVendorString.\n") );
            return NULL;
        }


        // ******************************
        //     Generation 2 Methods
        // ******************************


        // * * * * CANAL BLOCKING SEND * * * *
        m_pDeviceItem->m_proc_CanalBlockingSend = NULL;
        if (m_wxdll.HasSymbol(_T("CanalBlockingSend"))) {
            if (NULL == (m_pDeviceItem->m_proc_CanalBlockingSend =
                (LPFNDLL_CANALBLOCKINGSEND) m_wxdll.GetSymbol(_T("CanalBlockingSend")))) {
                m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalBlockingSend. Probably Generation 1 driver.\n") );
                m_pDeviceItem->m_proc_CanalBlockingSend = NULL;
            }
        }
        else {
            m_pCtrlObject->logMsg(_T("CanalBlockingSend not available. \n\tNon blocking operations set.\n") );
        }

        // * * * * CANAL BLOCKING RECEIVE * * * *
        m_pDeviceItem->m_proc_CanalBlockingReceive = NULL;
        if (m_wxdll.HasSymbol(_T("CanalBlockingReceive"))) {
            if (NULL == (m_pDeviceItem->m_proc_CanalBlockingReceive =
                (LPFNDLL_CANALBLOCKINGRECEIVE) m_wxdll.GetSymbol(_T("CanalBlockingReceive")))) {
                m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalBlockingReceive. Probably Generation 1 driver.\n") );
                m_pDeviceItem->m_proc_CanalBlockingReceive = NULL;
            }
        }
        else {
            m_pCtrlObject->logMsg(_T("CanalBlockingReceive not available. \n\tNon blocking operations set.\n"));
        }

        // * * * * CANAL GET DRIVER INFO * * * *
        m_pDeviceItem->m_proc_CanalGetdriverInfo = NULL;
        if (m_wxdll.HasSymbol(_T("CanalGetDriverInfo"))) {
            if (NULL == (m_pDeviceItem->m_proc_CanalGetdriverInfo =
                (LPFNDLL_CANALGETDRIVERINFO) m_wxdll.GetSymbol(_T("CanalGetDriverInfo")))) {
                m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetDriverInfo. Probably Generation 1 driver.\n") );
                m_pDeviceItem->m_proc_CanalGetdriverInfo = NULL;
            }
        }

        // Open the device
        m_pDeviceItem->m_openHandle =
            m_pDeviceItem->m_proc_CanalOpen((const char *) m_pDeviceItem->m_strParameter.mb_str(wxConvUTF8),
                                                m_pDeviceItem->m_DeviceFlags);

        // Check if the driver opened properly
        if (m_pDeviceItem->m_openHandle <= 0) {
            wxString errMsg = _T("Failed to open driver. Will not use it! \n\t[ ")
                + m_pDeviceItem->m_strName + _T(" ]\n");
            m_pCtrlObject->logMsg( errMsg );
            return NULL;
        }
        else {
            wxString wxstr =
                wxString::Format(_("Driver %s opended.\n"),
                                    (const char *)m_pDeviceItem->m_strName.mbc_str() );
            m_pCtrlObject->logMsg( wxstr );
        }

        // Get Driver Level
        m_pDeviceItem->m_driverLevel =
                m_pDeviceItem->m_proc_CanalGetLevel(m_pDeviceItem->m_openHandle);


        //  * * * Level I Driver * * *

        // Check if blocking driver is available
        if (NULL != m_pDeviceItem->m_proc_CanalBlockingReceive) {

            // * * * * Blocking version * * * *

            /////////////////////////////////////////////////////////////////////////////
            // Device write worker thread
            /////////////////////////////////////////////////////////////////////////////
            m_pwriteThread = new deviceCanalWriteThread;

            if (m_pwriteThread) {
                m_pwriteThread->m_pMainThreadObj = this;
                wxThreadError err;
                if (wxTHREAD_NO_ERROR == (err = m_pwriteThread->Create())) {
                    m_pwriteThread->SetPriority(WXTHREAD_MAX_PRIORITY);
                    if (wxTHREAD_NO_ERROR != (err = m_pwriteThread->Run())) {
                        m_pCtrlObject->logMsg(_("Unable to run device write worker thread.\n") );
                    }
                }
                else {
                    m_pCtrlObject->logMsg(_("Unable to create device write worker thread.\n") );
                }
            }
            else {
                m_pCtrlObject->logMsg(_("Unable to allocate memory for device write worker thread.\n") );
            }

            /////////////////////////////////////////////////////////////////////////////
            // Device read worker thread
            /////////////////////////////////////////////////////////////////////////////
            m_preceiveThread = new deviceCanalReceiveThread;

            if (m_preceiveThread) {
                m_preceiveThread->m_pMainThreadObj = this;
                wxThreadError err;
                if (wxTHREAD_NO_ERROR == (err = m_preceiveThread->Create())) {
                    m_preceiveThread->SetPriority(WXTHREAD_MAX_PRIORITY);
                    if (wxTHREAD_NO_ERROR != (err = m_preceiveThread->Run())) {
                        m_pCtrlObject->logMsg(_("Unable to run device receive worker thread.\n") );
                    }
                }
                else {
                    m_pCtrlObject->logMsg(_("Unable to create device receive worker thread.\n") );
                }
            }
            else {
                m_pCtrlObject->logMsg(_("Unable to allocate memory for device receive worker thread.\n") );
            }

            // Just sit and wait until the end of the world as we know it...
            while (!m_pDeviceItem->m_bQuit) {
                wxSleep(1);
            }

            m_preceiveThread->m_bQuit = true;
            m_pwriteThread->m_bQuit = true;
            m_preceiveThread->Wait();
            m_pwriteThread->Wait();
        }
        else {

            // * * * * Non blocking version * * * *

            bool bActivity;
            while (!TestDestroy() && !m_pDeviceItem->m_bQuit) {

                bActivity = false;
                /////////////////////////////////////////////////////////////////////////////
                //                           Receive from device						   //
                /////////////////////////////////////////////////////////////////////////////
                canalMsg msg;
                if (m_pDeviceItem->m_proc_CanalDataAvailable(m_pDeviceItem->m_openHandle)) {

                    if (CANAL_ERROR_SUCCESS ==
                        m_pDeviceItem->m_proc_CanalReceive(m_pDeviceItem->m_openHandle, &msg)) {

                        bActivity = true;

                        // There must be room in the receive queue
                        if (m_pCtrlObject->m_maxItemsInClientReceiveQueue >
                            m_pCtrlObject->m_clientOutputQueue.GetCount()) {

                            vscpEvent *pvscpEvent = new vscpEvent;
                            if (NULL != pvscpEvent) {

                                // Convert CANAL message to VSCP event
                                vscp_convertCanalToEvent( pvscpEvent,
                                                            &msg,
                                                            m_pDeviceItem->m_pClientItem->m_guid.m_id );

                                pvscpEvent->obid = m_pDeviceItem->m_pClientItem->m_clientID;

                                m_pCtrlObject->m_mutexClientOutputQueue.Lock();
                                m_pCtrlObject->m_clientOutputQueue.Append(pvscpEvent);
                                m_pCtrlObject->m_semClientOutputQueue.Post();
                                m_pCtrlObject->m_mutexClientOutputQueue.Unlock();

                            }
                        }
                    }
                } // data available


                // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                //             Send messages (if any) in the outqueue
                // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

                // Check if there is something to send
                if (m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetCount()) {

                    bActivity = true;

                    CLIENTEVENTLIST::compatibility_iterator nodeClient;

                    m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Lock();
                    nodeClient = m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetFirst();
                    vscpEvent *pqueueEvent = nodeClient->GetData();
                    m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Unlock();

                    canalMsg canalMsg;
                    vscp_convertEventToCanal(&canalMsg, pqueueEvent);
                    if (CANAL_ERROR_SUCCESS ==
                        m_pDeviceItem->m_proc_CanalSend(m_pDeviceItem->m_openHandle, &canalMsg)) {
                        // Remove the node
                        delete pqueueEvent;
                        m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient);
                    }
                    else {
                        // Another try
                        //m_pCtrlObject->m_semClientOutputQueue.Post();
                        vscp_deleteVSCPevent(pqueueEvent);
                        m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient);
                    }

                } // events

                if (!bActivity) {
                    ::wxMilliSleep(100);
                }

                bActivity = false;

            } // while working - non blocking

        } // if blocking/non blocking


        // Close CANAL channel
        m_pDeviceItem->m_proc_CanalClose(m_pDeviceItem->m_openHandle);

        // Library is unloaded in destructor

        // Remove messages in the client queues
        m_pCtrlObject->m_wxClientMutex.Lock();
        m_pCtrlObject->removeClient(m_pDeviceItem->m_pClientItem);
        m_pCtrlObject->m_wxClientMutex.Unlock();

        if (NULL != m_preceiveThread) {
            m_preceiveThread->Wait();
            delete m_preceiveThread;
        }

        if (NULL != m_pwriteThread) {
            m_pwriteThread->Wait();
            delete m_pwriteThread;
        }

    }
    else if (VSCP_DRIVER_LEVEL2 == m_pDeviceItem->m_driverLevel) {

        // Now find methods in library
        {
            wxString str;
            str = _("Loading level II driver: <");
            str += m_pDeviceItem->m_strName;
            str += _(">");
            str += _("\n");
            m_pCtrlObject->logMsg(str);
        }

        // * * * * VSCP OPEN * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPOpen =
            (LPFNDLL_VSCPOPEN) m_wxdll.GetSymbol(_T("VSCPOpen")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPOpen.\n"));
            return NULL;
        }

        // * * * * VSCP CLOSE * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPClose =
            (LPFNDLL_VSCPCLOSE) m_wxdll.GetSymbol(_T("VSCPClose")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPClose.\n"));
            return NULL;
        }

        // * * * * VSCP BLOCKINGSEND * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPBlockingSend =
            (LPFNDLL_VSCPBLOCKINGSEND) m_wxdll.GetSymbol(_T("VSCPBlockingSend")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPBlockingSend.\n"));
            return NULL;
        }

        // * * * * VSCP BLOCKINGRECEIVE * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPBlockingReceive =
            (LPFNDLL_VSCPBLOCKINGRECEIVE) m_wxdll.GetSymbol(_T("VSCPBlockingReceive")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPBlockingReceive.\n"));
            return NULL;
        }

        // * * * * VSCP GETLEVEL * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPGetLevel =
            (LPFNDLL_VSCPGETLEVEL) m_wxdll.GetSymbol(_T("VSCPGetLevel")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetLevel.\n"));
            return NULL;
        }

        // * * * * VSCP GET DLL VERSION * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPGetDllVersion =
            (LPFNDLL_VSCPGETDLLVERSION) m_wxdll.GetSymbol(_T("VSCPGetDllVersion")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetDllVersion.\n"));
            return NULL;
        }

        // * * * * VSCP GET VENDOR STRING * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPGetVendorString =
            (LPFNDLL_VSCPGETVENDORSTRING) m_wxdll.GetSymbol(_T("VSCPGetVendorString")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetVendorString.\n"));
            return NULL;
        }

        // * * * * VSCP GET DRIVER INFO * * * *
        if (NULL == (m_pDeviceItem->m_proc_CanalGetdriverInfo =
            (LPFNDLL_VSCPGETVENDORSTRING) m_wxdll.GetSymbol(_T("VSCPGetDriverInfo")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetDriverInfo.\n"));
            return NULL;
        }

        // * * * * VSCP GET WEB PAGE TEMPLATE * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPGetWebPageTemplate =
            (LPFNDLL_VSCPGETWEBPAGETEMPLATE) m_wxdll.GetSymbol(_T("VSCPGetWebPageTemplate")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetWebPageTemplate.\n"));
            return NULL;
        }

        // * * * * VSCP GET WEB PAGE INFO * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPGetWebPageInfo =
            (LPFNDLL_VSCPGETWEBPAGEINFO) m_wxdll.GetSymbol(_T("VSCPGetWebPageInfo")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetWebPageInfo.\n"));
            return NULL;
        }

        // * * * * VSCP WEB PAGE UPDATE * * * *
        if (NULL == (m_pDeviceItem->m_proc_VSCPWebPageupdate =
            (LPFNDLL_VSCPWEBPAGEUPDATE) m_wxdll.GetSymbol(_T("VSCPWebPageupdate")))) {
            // Free the library
            m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPWebPageupdate.\n"));
            return NULL;
        }

        m_pCtrlObject->logMsg(_("Discovered all methods\n"));

        // Username, password, host and port can be set in configuration file. Read in them here
        // if they are.
        wxString strHost(_("127.0.0.1:9598"));

        wxStringTokenizer tkz(m_pDeviceItem->m_strParameter, _(";"));
        if (tkz.HasMoreTokens()) {

            CVSCPVariable *pVar;

            // Get prefix
            wxString prefix = tkz.GetNextToken();

            // Check if username is specified in the configuration file
            pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_username"));
            if (NULL != pVar) {
                wxString str;
                if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) {
                    pVar->getValue( str );
                    m_pCtrlObject->m_driverUsername = str;
                }
            }

            // Check if password is specified in the configuration file
            pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_password"));
            if (NULL != pVar) {
                wxString str;
                if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) {
                    pVar->getValue( str );
                    m_pCtrlObject->m_driverPassword = str;
                }
            }

            // Check if host is specified in the configuration file
            pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_host"));
            if (NULL != pVar) {
                wxString str;
                if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) {
                    pVar->getValue( str );
                    strHost = str;
                }
            }

        }

        // Open up the driver
        m_pDeviceItem->m_openHandle =
            m_pDeviceItem->m_proc_VSCPOpen( m_pCtrlObject->m_driverUsername.mbc_str(),
                                                ( const char * )m_pCtrlObject->m_driverPassword.mbc_str(),
                                                ( const char * )strHost.mbc_str(),
                                                0,
                                                ( const char * )m_pDeviceItem->m_strName.mbc_str(),
                                                ( const char * )m_pDeviceItem->m_strParameter.mbc_str() );

        if ( 0 == m_pDeviceItem->m_openHandle ) {
            // Free the library
            m_pCtrlObject->logMsg( _T( "Unable to open the library.\n" ) );
            return NULL;
        }

        /////////////////////////////////////////////////////////////////////////////
        // Device write worker thread
        /////////////////////////////////////////////////////////////////////////////

        m_pwriteLevel2Thread = new deviceLevel2WriteThread;

        if (m_pwriteLevel2Thread) {
            m_pwriteLevel2Thread->m_pMainThreadObj = this;
            wxThreadError err;
            if (wxTHREAD_NO_ERROR == (err = m_pwriteLevel2Thread->Create())) {
                m_pwriteLevel2Thread->SetPriority(WXTHREAD_MAX_PRIORITY);
                if (wxTHREAD_NO_ERROR != (err = m_pwriteLevel2Thread->Run())) {
                    m_pCtrlObject->logMsg(_("Unable to run device write worker thread."));
                }
            }
            else {
                m_pCtrlObject->logMsg(_("Unable to create device write worker thread."));
            }
        }
        else {
            m_pCtrlObject->logMsg(_("Unable to allocate memory for device write worker thread."));
        }

        /////////////////////////////////////////////////////////////////////////////
        // Device read worker thread
        /////////////////////////////////////////////////////////////////////////////

        m_preceiveLevel2Thread = new deviceLevel2ReceiveThread;

        if (m_preceiveLevel2Thread) {
            m_preceiveLevel2Thread->m_pMainThreadObj = this;
            wxThreadError err;
            if (wxTHREAD_NO_ERROR == (err = m_preceiveLevel2Thread->Create())) {
                m_preceiveLevel2Thread->SetPriority(WXTHREAD_MAX_PRIORITY);
                if (wxTHREAD_NO_ERROR != (err = m_preceiveLevel2Thread->Run())) {
                    m_pCtrlObject->logMsg(_("Unable to run device receive worker thread."));
                }
            }
            else {
                m_pCtrlObject->logMsg(_("Unable to create device receive worker thread.") );
            }
        }
        else {
            m_pCtrlObject->logMsg(_("Unable to allocate memory for device receive worker thread.") );
        }

        // Just sit and wait until the end of the world as we know it...
        while (!TestDestroy() && !m_pDeviceItem->m_bQuit) {
            wxSleep(200);
        }

        m_preceiveLevel2Thread->m_bQuit = true;
        m_pwriteLevel2Thread->m_bQuit = true;

        // Close channel
        m_pDeviceItem->m_proc_VSCPClose(m_pDeviceItem->m_openHandle);

        // Library is unloaded in destructor

        // Remove messages in the client queues
        m_pCtrlObject->m_wxClientMutex.Lock();
        m_pCtrlObject->removeClient(m_pDeviceItem->m_pClientItem);
        m_pCtrlObject->m_wxClientMutex.Unlock();

        if (NULL != m_preceiveLevel2Thread) {
            m_preceiveLevel2Thread->Wait();
            delete m_preceiveLevel2Thread;
        }

        if (NULL != m_pwriteLevel2Thread) {
            m_pwriteLevel2Thread->Wait();
            delete m_pwriteLevel2Thread;
        }

    }




    //
    // =====================================================================================
    //




    return NULL;
}
예제 #10
0
static void ev_handler( struct ns_connection *nc, int ev, void *p )
{
    struct ns_mqtt_message *msg = ( struct ns_mqtt_message * )p;
    Cmqttobj *pmqttobj = ( Cmqttobj *)nc->mgr->user_data;

    switch ( ev ) {

        case NS_CONNECT:
            ns_set_protocol_mqtt( nc );
            ns_send_mqtt_handshake( nc, "vscpd" );
            break;

        case NS_MQTT_CONNACK:
            if ( msg->connack_ret_code != NS_MQTT_CONNACK_ACCEPTED ) {
                printf( "Got mqtt connection error: %d\n", msg->connack_ret_code );
                pmqttobj->m_bQuit = true;
                return;
            }
            
            pmqttobj->m_bConnected = true;

            if ( pmqttobj->m_bSubscribe ) {
                ns_mqtt_subscribe( nc, pmqttobj->m_topic_list, 1, 42 );
            }
            else {
                ;
            }
            break;

        case NS_MQTT_PUBACK:
            printf( "Message publishing acknowledged (msg_id: %d)\n", msg->message_id );
            break;

        case NS_MQTT_SUBACK:
            printf( "Subscription acknowledged, forwarding to '/test'\n" );
            break;

        case NS_MQTT_PUBLISH:
        {
            printf( "Got incoming message %s: %.*s\n", msg->topic, ( int )msg->payload.len, msg->payload.p );
            vscpEventEx eventEx;

            if ( !strcmp( msg->topic, pmqttobj->m_topic.ToAscii() ) ) {

                wxString str = wxString::FromAscii( ( const char * )msg->payload.p );
                if ( vscp_setVscpEventExFromString( &eventEx, str ) ) {

                    vscpEvent *pEvent = new vscpEvent;
                    if ( NULL != pEvent ) {

                        pEvent->sizeData = 0;
                        pEvent->pdata = NULL;

                        if ( vscp_doLevel2FilterEx( &eventEx, &pmqttobj->m_vscpfilter ) ) {

                            if ( vscp_convertVSCPfromEx( pEvent, &eventEx ) ) {
                                pmqttobj->m_mutexReceiveQueue.Lock();
                                pmqttobj->m_receiveList.push_back( pEvent );
                                pmqttobj->m_semReceiveQueue.Post();
                                pmqttobj->m_mutexReceiveQueue.Unlock();
                            }
                            else {

                            }
                        }
                        else {
                            vscp_deleteVSCPevent( pEvent );
                        }
                    }
                }
            }
        }
        break;

        case NS_CLOSE:
            printf( "Connection closed\n" );
            pmqttobj->m_bConnected = false;
            pmqttobj->m_bQuit = true;
    }

}
예제 #11
0
void *
deviceThread(void *pData)
{
    const char *dlsym_error;

    CDeviceItem *pDevItem = (CDeviceItem *)pData;
    if (NULL == pDevItem) {
        syslog(LOG_CRIT, "No device item defined. Aborting device thread!");
        return NULL;
    }

    // Must have a valid pointer to the control object
    CControlObject *pCtrlObj = pDevItem->m_pCtrlObject;
    if (NULL == pCtrlObj) {
        syslog(LOG_CRIT, "No control object defined. Aborting device thread!");
        return NULL;
    }

    // We need to create a clientobject and add this object to the list
    CClientItem *pClientItem = pDevItem->m_pClientItem = new CClientItem;
    if (NULL == pClientItem) {
        return NULL;
    }

    // This is now an active Client
    pClientItem->m_bOpen = true;
    if (VSCP_DRIVER_LEVEL1 == pDevItem->m_driverLevel) {
        pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1;
    } else if (VSCP_DRIVER_LEVEL2 == pDevItem->m_driverLevel) {
        pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL2;
    } else if (VSCP_DRIVER_LEVEL3 == pDevItem->m_driverLevel) {
        pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL3;
    }

    char datebuf[80];
    time_t now = time(NULL);
    vscp_getTimeString(datebuf, sizeof(datebuf), &now);
    pClientItem->m_strDeviceName = pDevItem->m_strName;
    pClientItem->m_strDeviceName += "|Started at ";
    pClientItem->m_strDeviceName += datebuf;

    syslog(LOG_DEBUG,
           "Devicethread: Starting %s",
           pClientItem->m_strDeviceName.c_str());

    // Add the client to the Client List
    pthread_mutex_lock(&pCtrlObj->m_clientList.m_mutexItemList);
    if (!pCtrlObj->addClient(pClientItem,
                             pDevItem->m_interface_guid.getClientID())) {
        // Failed to add client
        delete pDevItem->m_pClientItem;
        pDevItem->m_pClientItem = NULL;

        pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList);
        syslog(LOG_ERR,
               "Devicethread: Failed to add client. Terminating thread.");
        return NULL;
    }
    pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList);

    // Client now have GUID set to server GUID + channel id
    // If device has a non NULL GUID replace the client GUID preserving
    // the channel id with that GUID
    if (!pClientItem->m_guid.isNULL()) {
        memcpy(
          pClientItem->m_guid.m_id, pDevItem->m_interface_guid.getGUID(), 12);
    }

    void *hdll;
    if (VSCP_DRIVER_LEVEL3 != pDevItem->m_driverLevel) {
        // Load dynamic library
        hdll = dlopen(pDevItem->m_strPath.c_str(), RTLD_LAZY);
        if (!hdll) {
            syslog(LOG_ERR,
                   "Devicethread: Unable to load dynamic library. path = %s",
                   pDevItem->m_strPath.c_str());
            return NULL;
        }
    } else { // Level III driver

        //  Startup Level III driver
        std::string executable = pDevItem->m_strPath;

        pid_t pid = fork();
        if (pid == -1) {
            syslog(LOG_ERR,
                   "Failed to start level III driver %s (fork).",
                   pDevItem->m_strName.c_str());
        } else if (pid == 0) {

            // we're in child

            // Set process group to child process' pid.  Then killing -pid
            // of the parent will kill the process and all of its children.
            setsid();

            // Arguments:    TODO
            //      user
            //      password
            //      config parameters...
            // execvp( *argv, const_cast<char**>(argv) );

            // Wait on child
            int status;
            waitpid(pid, &status, 0);
        }
    }

    if (VSCP_DRIVER_LEVEL1 == pDevItem->m_driverLevel) {

        // Now find methods in library
        syslog(
          LOG_INFO, "Loading level I driver: %s", pDevItem->m_strName.c_str());

        // * * * * CANAL OPEN * * * *
        pDevItem->m_proc_CanalOpen =
          (LPFNDLL_CANALOPEN)dlsym(hdll, "CanalOpen");
        const char *dlsym_error = dlerror();
        dlsym_error             = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_DEBUG,
                   "%s : Unable to get dl entry for CanalOpen.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * CANAL CLOSE * * * *
        pDevItem->m_proc_CanalClose =
          (LPFNDLL_CANALCLOSE)dlsym(hdll, "CanalClose");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalClose.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL GETLEVEL * * * *
        pDevItem->m_proc_CanalGetLevel =
          (LPFNDLL_CANALGETLEVEL)dlsym(hdll, "CanalGetLevel");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetLevel.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL SEND * * * *
        pDevItem->m_proc_CanalSend =
          (LPFNDLL_CANALSEND)dlsym(hdll, "CanalSend");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalSend.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL DATA AVAILABLE * * * *
        pDevItem->m_proc_CanalDataAvailable =
          (LPFNDLL_CANALDATAAVAILABLE)dlsym(hdll, "CanalDataAvailable");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalDataAvailable.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL RECEIVE * * * *
        pDevItem->m_proc_CanalReceive =
          (LPFNDLL_CANALRECEIVE)dlsym(hdll, "CanalReceive");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalReceive.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL GET STATUS * * * *
        pDevItem->m_proc_CanalGetStatus =
          (LPFNDLL_CANALGETSTATUS)dlsym(hdll, "CanalGetStatus");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetStatus.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL GET STATISTICS * * * *
        pDevItem->m_proc_CanalGetStatistics =
          (LPFNDLL_CANALGETSTATISTICS)dlsym(hdll, "CanalGetStatistics");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetStatistics.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL SET FILTER * * * *
        pDevItem->m_proc_CanalSetFilter =
          (LPFNDLL_CANALSETFILTER)dlsym(hdll, "CanalSetFilter");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalSetFilter.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL SET MASK * * * *
        pDevItem->m_proc_CanalSetMask =
          (LPFNDLL_CANALSETMASK)dlsym(hdll, "CanalSetMask");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalSetMask.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL GET VERSION * * * *
        pDevItem->m_proc_CanalGetVersion =
          (LPFNDLL_CANALGETVERSION)dlsym(hdll, "CanalGetVersion");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetVersion.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL GET DLL VERSION * * * *
        pDevItem->m_proc_CanalGetDllVersion =
          (LPFNDLL_CANALGETDLLVERSION)dlsym(hdll, "CanalGetDllVersion");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetDllVersion.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // * * * * CANAL GET VENDOR STRING * * * *
        pDevItem->m_proc_CanalGetVendorString =
          (LPFNDLL_CANALGETVENDORSTRING)dlsym(hdll, "CanalGetVendorString");
        dlsym_error = dlerror();
        if (dlsym_error) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetVendorString.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        // ******************************
        //     Generation 2 Methods
        // ******************************

        // * * * * CANAL BLOCKING SEND * * * *
        pDevItem->m_proc_CanalBlockingSend =
          (LPFNDLL_CANALBLOCKINGSEND)dlsym(hdll, "CanalBlockingSend");
        dlsym_error = dlerror();
        if (dlsym_error) {
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalBlockingSend. Probably "
                   "Generation 1 driver.",
                   pDevItem->m_strName.c_str());
            pDevItem->m_proc_CanalBlockingSend = NULL;
        }

        // * * * * CANAL BLOCKING RECEIVE * * * *
        pDevItem->m_proc_CanalBlockingReceive =
          (LPFNDLL_CANALBLOCKINGRECEIVE)dlsym(hdll, "CanalBlockingReceive");
        dlsym_error = dlerror();
        if (dlsym_error) {
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalBlockingReceive. "
                   "Probably Generation 1 driver.",
                   pDevItem->m_strName.c_str());
            pDevItem->m_proc_CanalBlockingReceive = NULL;
        }

        // * * * * CANAL GET DRIVER INFO * * * *
        pDevItem->m_proc_CanalGetdriverInfo =
          (LPFNDLL_CANALGETDRIVERINFO)dlsym(hdll, "CanalGetDriverInfo");
        dlsym_error = dlerror();
        if (dlsym_error) {
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for CanalGetDriverInfo. "
                   "Probably Generation 1 driver.",
                   pDevItem->m_strName.c_str());
            pDevItem->m_proc_CanalGetdriverInfo = NULL;
        }

        // Open the device
        pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen(
          (const char *)pDevItem->m_strParameter.c_str(),
          pDevItem->m_DeviceFlags);

        // Check if the driver opened properly
        if (pDevItem->m_openHandle <= 0) {
            syslog(LOG_ERR,
                   "Failed to open driver. Will not use it! [%s] ",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL;
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level I Driver open.",
                   pDevItem->m_strName.c_str());
        }

        // Get Driver Level
        pDevItem->m_driverLevel =
          pDevItem->m_proc_CanalGetLevel(pDevItem->m_openHandle);

        //  * * * Level I Driver * * *

        // Check if blocking driver is available
        if (NULL != pDevItem->m_proc_CanalBlockingReceive) {

            // * * * * Blocking version * * * *

            if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
                syslog(LOG_DEBUG,
                       "%s: [Device tread] Level I blocking version.",
                       pDevItem->m_strName.c_str());
            }

            /////////////////////////////////////////////////////////////////////////////
            //                      Device write worker thread
            /////////////////////////////////////////////////////////////////////////////

            if (pthread_create(&pDevItem->m_level1WriteThread,
                               NULL,
                               deviceLevel1WriteThread,
                               pDevItem)) {
                syslog(LOG_CRIT,
                       "%s: Unable to run the device write worker thread.",
                       pDevItem->m_strName.c_str());
                // pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen();
                dlclose(hdll);
                return NULL;
            }

            /////////////////////////////////////////////////////////////////////////////
            // Device read worker thread
            /////////////////////////////////////////////////////////////////////////////
            if (pthread_create(&pDevItem->m_level1ReceiveThread,
                               NULL,
                               deviceLevel1ReceiveThread,
                               pDevItem)) {
                syslog(LOG_CRIT,
                       "%s: Unable to run the device read worker thread.",
                       pDevItem->m_strName.c_str());
                pDevItem->m_bQuit = true;
                pthread_join(pDevItem->m_level1WriteThread, NULL);
                // pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen();
                dlclose(hdll);
                return NULL;
            }

            // Just sit and wait until the end of the world as we know it...
            while (!pDevItem->m_bQuit) {
                sleep(1);
            }

            // Signal worker threads to quit
            pDevItem->m_bQuit = true;

            if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
                syslog(LOG_DEBUG,
                       "%s: [Device tread] Level I work loop ended.",
                       pDevItem->m_strName.c_str());
            }

            // Wait for workerthreads to abort
            pthread_join(pDevItem->m_level1WriteThread, NULL);
            pthread_join(pDevItem->m_level1ReceiveThread, NULL);
        } else {

            // * * * * Non blocking version * * * *

            if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
                syslog(LOG_DEBUG,
                       "%s: [Device tread] Level I NON Blocking version.",
                       pDevItem->m_strName.c_str());
            }

            bool bActivity;
            while (pDevItem->m_bQuit) {

                bActivity = false;
                /////////////////////////////////////////////////////////////////////////////
                //                           Receive from device
                /////////////////////////////////////////////////////////////////////////////
                canalMsg msg;
                if (pDevItem->m_proc_CanalDataAvailable(
                      pDevItem->m_openHandle)) {

                    if (CANAL_ERROR_SUCCESS ==
                        pDevItem->m_proc_CanalReceive(pDevItem->m_openHandle,
                                                      &msg)) {

                        bActivity = true;

                        // There must be room in the receive queue
                        if (pCtrlObj->m_maxItemsInClientReceiveQueue >
                            pCtrlObj->m_clientOutputQueue.size()) {

                            vscpEvent *pvscpEvent = new vscpEvent;
                            if (NULL != pvscpEvent) {

                                // Set driver GUID if set
                                /*if ( pDevItem->m_interface_guid.isNULL() ) {
                                    pDevItem->m_interface_guid.writeGUID(
                                pvscpEvent->GUID );
                                }
                                else {
                                    // If no driver GUID set use interface GUID
                                    pItem->m_guid.writeGUID( pvscpEvent->GUID );
                                }*/

                                // Convert CANAL message to VSCP event
                                vscp_convertCanalToEvent(
                                  pvscpEvent, &msg, pClientItem->m_guid.m_id);

                                pvscpEvent->obid = pClientItem->m_clientID;

                                pthread_mutex_lock(
                                  &pCtrlObj->m_mutexClientOutputQueue);
                                pCtrlObj->m_clientOutputQueue.push_back(
                                  pvscpEvent);
                                sem_post(&pCtrlObj->m_semClientOutputQueue);
                                pthread_mutex_unlock(
                                  &pCtrlObj->m_mutexClientOutputQueue);
                            }
                        }
                    }
                } // data available

                // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                //          Send messages (if any) in the output queue
                // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

                // Check if there is something to send
                if (pClientItem->m_clientInputQueue.size()) {

                    bActivity = true;

                    std::deque<vscpEvent *>::iterator it;

                    pthread_mutex_lock(&pClientItem->m_mutexClientInputQueue);
                    vscpEvent *pqueueEvent =
                      pClientItem->m_clientInputQueue.front();
                    pthread_mutex_lock(&pClientItem->m_mutexClientInputQueue);

                    // Trow away Level II event on Level I interface
                    if ((CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1 ==
                         pClientItem->m_type) &&
                        (pqueueEvent->vscp_class > 512)) {
                        // Remove the event and the node
                        pClientItem->m_clientInputQueue.pop_front();
                        syslog(LOG_ERR,
                               "Level II event on Level I queue thrown away. "
                               "class=%d, type=%d",
                               pqueueEvent->vscp_class,
                               pqueueEvent->vscp_type);
                        vscp_deleteVSCPevent(pqueueEvent);
                        continue;
                    }

                    canalMsg canalMsg;
                    vscp_convertEventToCanal(&canalMsg, pqueueEvent);
                    if (CANAL_ERROR_SUCCESS ==
                        pDevItem->m_proc_CanalSend(pDevItem->m_openHandle,
                                                   &canalMsg)) {
                        // Remove the event and the node
                        pClientItem->m_clientInputQueue.pop_front();
                        delete pqueueEvent;
                    } else {
                        // Another try
                        // pCtrlObj->m_semClientOutputQueue.Post();
                        // vscp_deleteVSCPevent(pqueueEvent);  TODO ????
                    }

                } // events

                if (!bActivity) {
                    usleep(100000); // 100 ms
                }

                bActivity = false;

            } // while working - non blocking

        } // if blocking/non blocking

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level I Work loop ended.",
                   pDevItem->m_strName.c_str());
        }

        // Close CANAL channel
        pDevItem->m_proc_CanalClose(pDevItem->m_openHandle);

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level I Closed.",
                   pDevItem->m_strName.c_str());
        }

    level1_driver_exit:

        pDevItem->m_bQuit = true;
        pthread_join(pDevItem->m_level1WriteThread, NULL);
        pthread_join(pDevItem->m_level1ReceiveThread, NULL);

        dlclose(hdll);

    } else if (VSCP_DRIVER_LEVEL2 == pDevItem->m_driverLevel) {

        // Now find methods in library
        syslog(LOG_INFO,
               "Loading level II driver: <%s>",
               pDevItem->m_strName.c_str());

        // * * * * VSCP OPEN * * * *
        if (NULL == (pDevItem->m_proc_VSCPOpen =
                       (LPFNDLL_VSCPOPEN)dlsym(hdll, "VSCPOpen"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPOpen.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP CLOSE * * * *
        if (NULL == (pDevItem->m_proc_VSCPClose =
                       (LPFNDLL_VSCPCLOSE)dlsym(hdll, "VSCPClose"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPClose.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP BLOCKINGSEND * * * *
        if (NULL ==
            (pDevItem->m_proc_VSCPBlockingSend =
               (LPFNDLL_VSCPBLOCKINGSEND)dlsym(hdll, "VSCPBlockingSend"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPBlockingSend.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP BLOCKINGRECEIVE * * * *
        if (NULL == (pDevItem->m_proc_VSCPBlockingReceive =
                       (LPFNDLL_VSCPBLOCKINGRECEIVE)dlsym(
                         hdll, "VSCPBlockingReceive"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPBlockingReceive.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP GETLEVEL * * * *
        if (NULL == (pDevItem->m_proc_VSCPGetLevel =
                       (LPFNDLL_VSCPGETLEVEL)dlsym(hdll, "VSCPGetLevel"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPGetLevel.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP GET DLL VERSION * * * *
        if (NULL ==
            (pDevItem->m_proc_VSCPGetDllVersion =
               (LPFNDLL_VSCPGETDLLVERSION)dlsym(hdll, "VSCPGetDllVersion"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPGetDllVersion.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP GET VENDOR STRING * * * *
        if (NULL == (pDevItem->m_proc_VSCPGetVendorString =
                       (LPFNDLL_VSCPGETVENDORSTRING)dlsym(
                         hdll, "VSCPGetVendorString"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPGetVendorString.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP GET DRIVER INFO * * * *
        if (NULL ==
            (pDevItem->m_proc_CanalGetdriverInfo =
               (LPFNDLL_VSCPGETVENDORSTRING)dlsym(hdll, "VSCPGetDriverInfo"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPGetDriverInfo.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP GET WEB PAGE TEMPLATE * * * *
        if (NULL == (pDevItem->m_proc_VSCPGetWebPageTemplate =
                       (LPFNDLL_VSCPGETWEBPAGETEMPLATE)dlsym(
                         hdll, "VSCPGetWebPageTemplate"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPGetWebPageTemplate.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP GET WEB PAGE INFO * * * *
        if (NULL ==
            (pDevItem->m_proc_VSCPGetWebPageInfo =
               (LPFNDLL_VSCPGETWEBPAGEINFO)dlsym(hdll, "VSCPGetWebPageInfo"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPGetWebPageInfo.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        // * * * * VSCP WEB PAGE UPDATE * * * *
        if (NULL ==
            (pDevItem->m_proc_VSCPWebPageupdate =
               (LPFNDLL_VSCPWEBPAGEUPDATE)dlsym(hdll, "VSCPWebPageupdate"))) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: Unable to get dl entry for VSCPWebPageupdate.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: Discovered all methods\n",
                   pDevItem->m_strName.c_str());
        }

        // Username, password, host and port can be set in configuration file.
        // Read in them here if they are.
        std::string strHost("127.0.0.1");
        short port = 9598;

        std::deque<std::string> tokens;
        vscp_split(tokens, pDevItem->m_strParameter, ";");
        if (false == tokens.empty()) {

            CVariable variable;

            // Get prefix
            std::string prefix = tokens.front();
            tokens.pop_front();

            // Check if username is specified in the configuration file
            CUserItem *pAdminUser =
              pDevItem->m_pCtrlObject->m_userList.getUser(USER_ID_ADMIN);
            if (pCtrlObj->m_variables.find(
                  pDevItem->m_strName + "_username", pAdminUser, variable)) {
                std::string str;
                if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) {
                    str                        = variable.getValue();
                    pCtrlObj->m_driverUsername = str;
                }
            }

            // Check if password is specified in the configuration file
            if (pCtrlObj->m_variables.find(
                  pDevItem->m_strName + "_password", pAdminUser, variable)) {
                std::string str;
                if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) {
                    str                        = variable.getValue();
                    pCtrlObj->m_driverPassword = str;
                }
            }

            // Check if host is specified in the configuration file
            if (pCtrlObj->m_variables.find(
                  pDevItem->m_strName + "_host", pAdminUser, variable)) {
                std::string str;
                if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) {
                    str     = variable.getValue();
                    strHost = str;
                }
            }

            // Check if host is specified in the configuration file
            if (pCtrlObj->m_variables.find(
                  pDevItem->m_strName + "_port", pAdminUser, variable)) {
                std::string str;
                if (VSCP_DAEMON_VARIABLE_CODE_INTEGER == variable.getType()) {
                    str  = variable.getValue();
                    port = vscp_readStringValue(str);
                }
            }
        }

        // Open up the driver
        pDevItem->m_openHandle = pDevItem->m_proc_VSCPOpen(
          pCtrlObj->m_driverUsername.c_str(),
          (const char *)pCtrlObj->m_driverPassword.c_str(),
          (const char *)strHost.c_str(),
          port,
          (const char *)pDevItem->m_strName.c_str(),
          (const char *)pDevItem->m_strParameter.c_str());

        if (0 == pDevItem->m_openHandle) {
            // Free the library
            syslog(LOG_ERR,
                   "%s: [Device tread] Unable to open VSCP "
                   "driver (check username/password/path/"
                   "rights). Possible additional info from driver "
                   "in syslog.",
                   pDevItem->m_strName.c_str());
            return NULL;
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II Open.",
                   pDevItem->m_strName.c_str());
        }

        /////////////////////////////////////////////////////////////////////////////
        // Device write worker thread
        /////////////////////////////////////////////////////////////////////////////

        if (pthread_create(&pDevItem->m_level2WriteThread,
                           NULL,
                           deviceLevel2WriteThread,
                           pDevItem)) {
            syslog(LOG_CRIT,
                   "%s: Unable to run the device Level II write worker thread.",
                   pDevItem->m_strName.c_str());
            dlclose(hdll);
            return NULL; // TODO close dll
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II Write thread created.",
                   pDevItem->m_strName.c_str());
        }

        /////////////////////////////////////////////////////////////////////////////
        // Device read worker thread
        /////////////////////////////////////////////////////////////////////////////

        if (pthread_create(&pDevItem->m_level2ReceiveThread,
                           NULL,
                           deviceLevel2ReceiveThread,
                           pDevItem)) {
            syslog(LOG_CRIT,
                   "%s: Unable to run the device Level II read worker thread.",
                   pDevItem->m_strName.c_str());
            pDevItem->m_bQuit = true;
            pthread_join(pDevItem->m_level2WriteThread, NULL);
            dlclose(hdll);
            return NULL; // TODO close dll, kill other thread
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II Write thread created.",
                   pDevItem->m_strName.c_str());
        }

        // Just sit and wait until the end of the world as we know it...
        while (!pDevItem->m_bQuit) {
            sleep(1);
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II Closing.",
                   pDevItem->m_strName.c_str());
        }

        // Close channel
        pDevItem->m_proc_VSCPClose(pDevItem->m_openHandle);

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II Closed.",
                   pDevItem->m_strName.c_str());
        }

    level2_driver_exit:

        pDevItem->m_bQuit = true;
        pthread_join(pDevItem->m_level2WriteThread, NULL);
        pthread_join(pDevItem->m_level2ReceiveThread, NULL);

        // Unload dll
        dlclose(hdll);

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II Done waiting for threads.",
                   pDevItem->m_strName.c_str());
        }

    } else if (VSCP_DRIVER_LEVEL3 == pDevItem->m_driverLevel) {

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level III Start server loop.",
                   pDevItem->m_strName.c_str());
        }

        // Just sit and wait until the end of the world as we know it...
        while (!pDevItem->m_bQuit) {
            sleep(1);
        }

        if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) {
            syslog(LOG_DEBUG,
                   "%s: [Device tread] Level II End server loop.",
                   pDevItem->m_strName.c_str());
        }
    }

    // Remove messages in the client queues
    pthread_mutex_lock(&pCtrlObj->m_clientList.m_mutexItemList);
    pCtrlObj->removeClient(pClientItem);
    pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList);

    return NULL;
}
예제 #12
0
void *
CWrkWriteThread::Entry()
{
	pcap_t *fp;
	char errbuf[ PCAP_ERRBUF_SIZE ];
	uint8_t packet[ 512 ];

	// First log on to the host and get configuration 
	// variables
/*
	if (m_srv.doCmdOpen(m_pObj->m_host,
			m_pObj->m_port,
			m_pObj->m_username,
			m_pObj->m_password) <= 0) {
		return NULL;
	}

	// Find the channel id
	uint32_t ChannelID;
	m_srv.doCmdGetChannelID(&ChannelID);

	// We want to use our own Ethernet based  GUID for this interface
	wxString strGUID;
	m_pObj->m_localGUIDrx.toString(strGUID);
	m_srv.doCmdSetGUID((const char *) strGUID.ToAscii());
*/
    
	// Open the adapter 
	if ((fp = pcap_open_live(m_pObj->m_interface.ToAscii(), // name of the device
			65536, // portion of the packet to capture. It doesn't matter in this case 
			1, // promiscuous mode (nonzero means promiscuous)
			1000, // read timeout
			errbuf // error buffer
			)) == NULL) {
		//fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
		return NULL;
	}


	// Enter receive loop to start to log events
	//m_srv.doCmdEnterReceiveLoop();

	int rv;
	vscpEvent event;
	while (!TestDestroy() && !m_pObj->m_bQuit) {
        
        if ( wxSEMA_TIMEOUT == m_pObj->m_semSendQueue.WaitTimeout(300)) continue;
        
        // Check if there is event(s) to send
        if ( m_pObj->m_sendList.size() ) {

            // Yes there are data to send
            m_pObj->m_mutexSendQueue.Lock();
            vscpEvent *pEvent = m_pObj->m_sendList.front();
            m_pObj->m_sendList.pop_front();
            m_pObj->m_mutexSendQueue.Unlock();

            if (NULL == pEvent) continue;

            // Class must be a Level I class or a Level II
            // mirror class
            /*
            if (pEvent->vscp_class < 512) {
                frame.can_id = getCANidFromVSCPevent(pEvent);
                frame.can_id |= CAN_EFF_FLAG; // Always extended
                if (0 != pEvent->sizeData) {
                    frame.len = (pEvent->sizeData > 8 ? 8 : pEvent->sizeData);
                    memcpy(frame.data, pEvent->pdata, frame.len);
                }
            } 
            else if (pEvent->vscp_class < 1024) {
                pEvent->vscp_class -= 512;
                frame.can_id = getCANidFromVSCPevent(pEvent);
                frame.can_id |= CAN_EFF_FLAG; // Always extended
                if (0 != pEvent->sizeData) {
                    frame.len = ((pEvent->sizeData - 16) > 8 ? 8 : pEvent->sizeData - 16);
                    memcpy(frame.data, pEvent->pdata + 16, frame.len);
                }
            }
            */ 
            
            // Set mac destination to broadcast ff:ff:ff:ff:ff:ff 
			packet[ 0 ] = 0xff;
			packet[ 1 ] = 0xff;
			packet[ 2 ] = 0xff;
			packet[ 3 ] = 0xff;
			packet[ 4 ] = 0xff;
			packet[ 5 ] = 0xff;

			// set mac source to configured value - 6..11
			memcpy(packet + 6, m_pObj->m_localMac, 6);

			// Set the type - always 0x2574 (9598)
			packet[ 12 ] = 0x25;
			packet[ 13 ] = 0x7e;

			// rawEthernet frame version
			packet[ 14 ] = 0x00;

			// Head
			packet[ 15 ] = (event.head & VSCP_HEADER_PRIORITY_MASK);
			packet[ 16 ] = 0x00;
			packet[ 17 ] = 0x00;
			packet[ 18 ] = 0x00; // LSB

			// VSCP sub source address For this interface it's 0x0000
			packet[ 19 ] = 0x00;
			packet[ 20 ] = 0x00;

			// Timestamp
			uint32_t timestamp = event.timestamp;
			packet[ 21 ] = (timestamp & 0xff000000) >> 24;
			packet[ 22 ] = (timestamp & 0x00ff0000) >> 16;
			packet[ 23 ] = (timestamp & 0x0000ff00) >> 8;
			packet[ 24 ] = (timestamp & 0x000000ff);

			// obid
			uint32_t obid = event.obid;
			packet[ 25 ] = (obid & 0xff000000) >> 24;
			packet[ 26 ] = (obid & 0x00ff0000) >> 16;
			packet[ 27 ] = (obid & 0x0000ff00) >> 8;
			packet[ 28 ] = (obid & 0x000000ff);

			// VSCP Class
			uint16_t vscp_class = event.vscp_class;
			packet[ 29 ] = (vscp_class & 0xff00) >> 8;
			packet[ 30 ] = (vscp_class & 0xff);

			// VSCP Type
			uint16_t vscp_type = event.vscp_type;
			packet[ 31 ] = (vscp_type & 0xff00) >> 8;
			packet[ 32 ] = (vscp_type & 0xff);

			// Size
			packet[ 33 ] = event.sizeData >> 8;
			packet[ 34 ] = event.sizeData & 0xff;

			// VSCP Data
			memcpy(packet + 35, event.pdata, event.sizeData);

			// Send the packet
			if (0 != pcap_sendpacket(fp, packet, 35 + event.sizeData)) {
				//fprintf(stderr,"\nError sending the packet: %s\n", pcap_geterr(fp));
				// An error sending the frame - we do nothing
				// TODO: Send error frame back to daemon????
			}

            // Remove the event
            m_pObj->m_mutexSendQueue.Lock();
            vscp_deleteVSCPevent(pEvent);
            m_pObj->m_mutexSendQueue.Unlock();

		} // Event received

	} // work loop   
예제 #13
0
void *
CWrkReadThread::Entry()
{
	pcap_t *fp;
	char errbuf[ PCAP_ERRBUF_SIZE ];
	//uint8_t packet[ 512 ];

	// First log on to the host and get configuration 
	// variables

	if (m_srv.doCmdOpen(m_pObj->m_host,
			m_pObj->m_username,
			m_pObj->m_password) <= 0) {
		return NULL;
	}

	// Find the channel id
	m_srv.doCmdGetChannelID(&m_pObj->m_ChannelIDtx);

	// It is possible that there is configuration data the server holds 
	// that we need to read in. 
	// We look for 
	//      prefix_interface Communication interface to work on
	//      prefix_localmac MAC address to use for outgoing packets
	//      prefix_filter to find a filter. A string is expected.
	//      prefix_mask to find a mask. A string is expected.

	/*	
		// Interface
		wxString varInterface;
		if (m_srv.getVariableString(m_pObj->m_prefix + _T("_interface"), &varInterface)) {
			m_pObj->m_interface = varInterface;
		}

		wxString varLocalMac;
		if (m_srv.getVariableString(m_pObj->m_prefix + _T("_localmac"), &varLocalMac)) {
			varLocalMac.MakeUpper();
			wxStringTokenizer tkz(varLocalMac, ":\n");
			for (int i = 0; i < 6; i++) {
				if (tkz.HasMoreTokens()) break;
				wxString str = _("0X") + tkz.GetNextToken();
				m_pObj->m_localMac[ i ] = readStringValue(str);
				m_pObj->m_localGUIDtx.setAt((9 + i), m_pObj->m_localMac[ i ]);
				m_pObj->m_localGUIDrx.setAt((9 + i), m_pObj->m_localMac[ i ]);
			}
		}

	 */
	// We want to use our own Ethernet based GUID for this interface
	//wxString strGUID;
	//m_pObj->m_localGUIDtx.toString(strGUID);
	//m_srv.doCmdSetGUID((const char *) strGUID.ToAscii());

	// Open the adapter 
	if ((fp = pcap_open_live(m_pObj->m_interface.ToAscii(), // name of the device
			65536, // portion of the packet to capture. It doesn't matter in this case 
			1, // promiscuous mode (nonzero means promiscuous)
			1000, // read timeout
			errbuf // error buffer
			)) == NULL) {
		//fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
		return NULL;
	}

	int rv;
	struct pcap_pkthdr *header;
	const u_char *pkt_data;

	while (!TestDestroy() &&
			!m_pObj->m_bQuit &&
			(rv = pcap_next_ex(fp, &header, &pkt_data)) >= 0) {

		// Check for timeout            
		if (0 == rv) continue;

		// Check if this is VSCP
		if ((0x25 == pkt_data[ 12 ]) &&
				(0x7e == pkt_data[ 13 ])) {

			// We have a packet - send it as a VSCP event    
			vscpEventEx eventex;

			eventex.head = pkt_data[ 15 ] & 0xe0; // Priority

			eventex.GUID[ 0 ] = 0xff; // Ethernet predefined  GUID
			eventex.GUID[ 1 ] = 0xff;
			eventex.GUID[ 2 ] = 0xff;
			eventex.GUID[ 3 ] = 0xff;
			eventex.GUID[ 4 ] = 0xff;
			eventex.GUID[ 5 ] = 0xff;
			eventex.GUID[ 6 ] = 0xff;
			eventex.GUID[ 7 ] = 0xfe;
			eventex.GUID[ 8 ] = pkt_data[ 6 ]; // Source MAC address
			eventex.GUID[ 9 ] = pkt_data[ 7 ];
			eventex.GUID[ 10 ] = pkt_data[ 8 ];
			eventex.GUID[ 11 ] = pkt_data[ 9 ];
			eventex.GUID[ 12 ] = pkt_data[ 10 ];
			eventex.GUID[ 13 ] = pkt_data[ 11 ];
			eventex.GUID[ 14 ] = pkt_data[ 19 ]; // Device sub address
			eventex.GUID[ 15 ] = pkt_data[ 20 ];

			eventex.timestamp = (pkt_data[ 21 ] << 24) +
					(pkt_data[ 22 ] << 16) +
					(pkt_data[ 23 ] << 8) +
					pkt_data[ 24 ];

			eventex.obid = (pkt_data[ 25 ] << 24) +
					(pkt_data[ 26 ] << 16) +
					(pkt_data[ 27 ] << 8) +
					pkt_data[ 28 ];

			eventex.vscp_class = (pkt_data[ 29 ] << 8) +
                    pkt_data[ 30 ];

			eventex.vscp_type = (pkt_data[ 31 ] << 8) +
					pkt_data[ 32 ];

			eventex.sizeData = (pkt_data[ 33 ] << 8) +
					pkt_data[ 34 ];

			// If the packet is smaller then the set datasize just 
			// disregard it
			if ((eventex.sizeData + 35) > (uint16_t) header->len) continue;

			for (int i = 0; i < eventex.sizeData; i++) {
				eventex.data[ i ] = pkt_data[ 35 + i ];
            }

            vscpEvent *pEvent = new vscpEvent;
            if (NULL != pEvent) {
                
                vscp_convertVSCPfromEx(pEvent, &eventex);

                if (vscp_doLevel2FilterEx( &eventex, &m_pObj->m_vscpfilter)) {
                    m_pObj->m_mutexReceiveQueue.Lock();
                    m_pObj->m_receiveList.push_back(pEvent);
                    m_pObj->m_semReceiveQueue.Post();
                    m_pObj->m_mutexReceiveQueue.Unlock();
                }
                else {
                    vscp_deleteVSCPevent(pEvent);
                }
            }

        }

	} // work loop   

	// Close listner
	pcap_close(fp);

	// Close the channel
	//m_srv.doCmdClose();

	return NULL;
}
예제 #14
0
void *
threadWorker(void *pData)
{
    CLogWrkThreadObj *pObj = (CLogWrkThreadObj *)pData;
    if (NULL == pObj) {
        syslog(LOG_CRIT,
               "No thread object supplied to worker thread. Aborting!");
        return NULL;
    }

    // Check pointers
    if (NULL == pObj->m_pLog) {
        syslog(LOG_CRIT,
               "No valid logger object suppied to worker thread. Aborting!");
        return NULL;
    }

    // First log on to the host and get configuration
    // variables

    if (VSCP_ERROR_SUCCESS ==
        pObj->m_srv.doCmdOpen(pObj->m_pLog->m_host,
                              pObj->m_pLog->m_username,
                              pObj->m_pLog->m_password) <= 0) {
        return NULL;
    }

    // Find the channel id
    uint32_t ChannelID;
    pObj->m_srv.doCmdGetChannelID(&ChannelID);

    // It is possible that there is configuration data the server holds
    // that we need to read in.
    // We look for
    //      prefix_filter to find a filter. A string is expected.
    //      prefix_mask to find a mask. A string is expected.
    //      prefix_path to overide the file path for the log file. A string is
    //      expected. prefix_rewrite to override the overwrite flag. A bool is
    //      expected.

    // Get filter data
    std::string varFilter;
    std::string varMask;

    std::string strFilter = pObj->m_pLog->m_prefix + std::string("_filter");
    std::string strMask   = pObj->m_pLog->m_prefix + std::string("_mask");
    if ((VSCP_ERROR_SUCCESS ==
         pObj->m_srv.getRemoteVariableValue(strFilter, varFilter)) &&
        (VSCP_ERROR_SUCCESS ==
         pObj->m_srv.getRemoteVariableValue(strMask, varMask))) {
        pObj->m_srv.doCmdFilter(varFilter, varMask);
    }

    // get overriden file path
    std::string strPath = pObj->m_pLog->m_prefix + std::string("_path");
    std::string varPath;
    if (VSCP_ERROR_SUCCESS ==
        pObj->m_srv.getRemoteVariableValue(strPath, varPath)) {
        pObj->m_pLog->m_path = varPath;
    }

    std::string strRewrite = pObj->m_pLog->m_prefix + std::string("_rewrite");
    bool bOverwrite;
    if (VSCP_ERROR_SUCCESS ==
        pObj->m_srv.getRemoteVariableBool(strRewrite, &bOverwrite)) {
        if (bOverwrite) {
            pObj->m_pLog->m_flags |= LOG_FILE_OVERWRITE;
        } else {
            pObj->m_pLog->m_flags &= ~LOG_FILE_OVERWRITE;
        }
    }

    bool bVSCPWorksFormat;
    std::string strVscpWorkdFmt =
      pObj->m_pLog->m_prefix + std::string("_vscpworksfmt");
    if (VSCP_ERROR_SUCCESS ==
        pObj->m_srv.getRemoteVariableBool(strVscpWorkdFmt, &bVSCPWorksFormat)) {
        if (bVSCPWorksFormat) {
            pObj->m_pLog->m_flags |= LOG_FILE_VSCP_WORKS;
        } else {
            pObj->m_pLog->m_flags &= ~LOG_FILE_VSCP_WORKS;
        }
    }

    // XML setup
    std::string str;
    std::string strSetupXML;
    std::string strName = pObj->m_pLog->m_prefix + std::string("_setup");
    if (VSCP_ERROR_SUCCESS ==
        pObj->m_srv.getRemoteVariableValue(strName, strSetupXML, true)) {
        XML_Parser xmlParser = XML_ParserCreate("UTF-8");
        XML_SetUserData(xmlParser, pObj->m_pLog);
        XML_SetElementHandler(xmlParser, startSetupParser, endSetupParser);

        int bytes_read;
        void *buff = XML_GetBuffer(xmlParser, XML_BUFF_SIZE);

        strncpy((char *)buff, strSetupXML.c_str(), strSetupXML.length());

        bytes_read = strSetupXML.length();
        if (!XML_ParseBuffer(xmlParser, bytes_read, bytes_read == 0)) {
            syslog(LOG_ERR, "Failed parse XML setup.");
        }

        XML_ParserFree(xmlParser);
    }

    // Close server connection
    pObj->m_srv.doCmdClose();

    // Open the file
    if (!pObj->m_pLog->openFile()) return NULL;

    while (!pObj->m_pLog->m_bQuit) {

        // Wait for events
        if ((-1 == vscp_sem_wait(&pObj->m_pLog->m_semSendQueue, 500)) &&
            errno == ETIMEDOUT) {
            continue;
        }

        if (pObj->m_pLog->m_sendList.size()) {

            pthread_mutex_lock(&pObj->m_pLog->m_mutexSendQueue);
            vscpEvent *pEvent = pObj->m_pLog->m_sendList.front();
            pObj->m_pLog->m_sendList.pop_front();
            pthread_mutex_unlock(&pObj->m_pLog->m_mutexSendQueue);

            if (NULL == pEvent) continue;
            pObj->m_pLog->writeEvent(pEvent);
            vscp_deleteVSCPevent(pEvent);
            pEvent = NULL;

        } // Event received

    } // Receive loop

    // Close the channel
    pObj->m_srv.doCmdClose();

    return NULL;
}
예제 #15
0
void *
CSocketCanWorkerTread::Entry()
{
    int sock;
    char devname[IFNAMSIZ + 1];
    fd_set rdfs;
    struct timeval tv;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct cmsghdr *cmsg;
    struct canfd_frame frame;
    char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
    const int canfd_on = 1;

    ::wxInitialize();

    // Check pointers
    if (NULL == m_pObj) return NULL;

    strncpy(devname, m_pObj->m_interface.ToAscii(), sizeof(devname) - 1);
#if DEBUG
    syslog(LOG_ERR, "CWriteSocketCanTread: Interface: %s\n", ifname);
#endif

    while (!TestDestroy() && !m_pObj->m_bQuit) {

        sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
        if (sock < 0) {

            if (ENETDOWN == errno) {
                sleep(1);
                continue;
            }

            syslog(LOG_ERR,
                   "%s",
                   (const char *) "CReadSocketCanTread: Error while opening socket. Terminating!");

            m_pObj->m_bQuit;
            continue;
        }

        strcpy(ifr.ifr_name, devname);
        ioctl(sock, SIOCGIFINDEX, &ifr);

        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;

#ifdef DEBUG
        printf("using interface name '%s'.\n", ifr.ifr_name);
#endif

        // try to switch the socket into CAN FD mode
        setsockopt(sock,
                   SOL_CAN_RAW,
                   CAN_RAW_FD_FRAMES,
                   &canfd_on,
                   sizeof(canfd_on));

        if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
            syslog(LOG_ERR,
                   "%s",
                   (const char *) "CReadSocketCanTread: Error in socket bind. Terminating!");
            close(sock);
            sleep(2);
            continue;
        }

        bool bInnerLoop = true;
        while (!TestDestroy() && !m_pObj->m_bQuit && bInnerLoop) {

            FD_ZERO(&rdfs);
            FD_SET(sock, &rdfs);

            tv.tv_sec = 0;
            tv.tv_usec = 5000; // 5ms timeout

            int ret;
            if ( ( ret = select(sock + 1, &rdfs, NULL, NULL, &tv ) ) <  0) {
                // Error
                if (ENETDOWN == errno) {
                    // We try to get contact with the net
                    // again if it goes down
                    bInnerLoop = false;
                }
                else {
                    m_pObj->m_bQuit = true;
                }
                continue;
            }

            if ( ret ) {

                // There is data to read

                ret = read(sock, &frame, sizeof(struct can_frame));
                if (ret < 0) {
                    if (ENETDOWN == errno) {
                        // We try to get contact with the net
                        // again if it goes down
                        bInnerLoop = false;
                        sleep(2);
                    }
                    else {
                        m_pObj->m_bQuit = true;
                    }
                    continue;
                }

                // Must be Extended
                if (!(frame.can_id & CAN_EFF_FLAG)) continue;

                // Mask of control bits
                frame.can_id &= CAN_EFF_MASK;

                vscpEvent *pEvent = new vscpEvent();
                if (NULL != pEvent) {

                    pEvent->pdata = new uint8_t[frame.len];
                    if (NULL == pEvent->pdata) {
                        delete pEvent;
                        continue;
                    }

                    // GUID will be set to GUID of interface
                    // by driver interface with LSB set to nickname
                    memset(pEvent->GUID, 0, 16);
                    pEvent->GUID[VSCP_GUID_LSB] = frame.can_id & 0xff;

                    // Set VSCP class
                    pEvent->vscp_class = vscp_getVSCPclassFromCANALid(frame.can_id);

                    // Set VSCP type
                    pEvent->vscp_type = vscp_getVSCPtypeFromCANALid(frame.can_id);

                    // Copy data if any
                    pEvent->sizeData = frame.len;
                    if (frame.len) {
                        memcpy(pEvent->pdata, frame.data, frame.len);
                    }

                    if (vscp_doLevel2Filter(pEvent, &m_pObj->m_vscpfilter)) {
                        m_pObj->m_mutexReceiveQueue.Lock();
                        //m_pObj->m_receiveQueue.Append(pEvent);
                        m_pObj->m_receiveList.push_back(pEvent);
                        m_pObj->m_semReceiveQueue.Post();
                        m_pObj->m_mutexReceiveQueue.Unlock();
                    } else {
                        vscp_deleteVSCPevent(pEvent);
                    }
                }

            } else {

                // Check if there is event(s) to send
                if (m_pObj->m_sendList.size() /*m_pObj->m_sendQueue.GetCount()*/) {

                    // Yes there are data to send
                    // So send it out on the CAN bus

                    //VSCPEVENTLIST_SEND::compatibility_iterator nodeClient;
                    m_pObj->m_mutexSendQueue.Lock();
                    //nodeClient = m_pObj->m_sendQueue.GetFirst();
                    vscpEvent *pEvent = m_pObj->m_sendList.front();
                    m_pObj->m_sendList.pop_front();
                    m_pObj->m_mutexSendQueue.Unlock();

                    if (NULL == pEvent) continue;

                    // Class must be a Level I class or a Level II
                    // mirror class
                    if (pEvent->vscp_class < 512) {
                        frame.can_id = vscp_getCANALidFromVSCPevent(pEvent);
                        frame.can_id |= CAN_EFF_FLAG; // Always extended
                        if (0 != pEvent->sizeData) {
                            frame.len = (pEvent->sizeData > 8 ? 8 : pEvent->sizeData);
                            memcpy(frame.data, pEvent->pdata, frame.len);
                        }
                    } else if (pEvent->vscp_class < 1024) {
                        pEvent->vscp_class -= 512;
                        frame.can_id = vscp_getCANALidFromVSCPevent(pEvent);
                        frame.can_id |= CAN_EFF_FLAG; // Always extended
                        if (0 != pEvent->sizeData) {
                            frame.len = ((pEvent->sizeData - 16) > 8 ? 8 : pEvent->sizeData - 16);
                            memcpy(frame.data, pEvent->pdata + 16, frame.len);
                        }
                    }

                    // Remove the event
                    m_pObj->m_mutexSendQueue.Lock();
                    //m_pObj->m_sendQueue.DeleteNode(nodeClient);
                    vscp_deleteVSCPevent(pEvent);
                    m_pObj->m_mutexSendQueue.Unlock();


                    // Write the data
                    int nbytes = write(sock, &frame, sizeof(struct can_frame));

                } // event to send
            }  // No data to read
        } // Inner loop

        // Close the socket
        close(sock);

    } // Outer loop

    return NULL;

}