CClientList::~CClientList() { //dll_removeAllNodes( &m_list ); while ( NULL != m_clientList.pHead ) { CClientItem *pClientItem = (CClientItem *)m_clientList.pTail->pObject; if ( NULL != pClientItem ) delete pClientItem; m_clientList.pTail->pObject = NULL; dll_removeNode( &m_clientList, m_clientList.pTail ); } }
bool CClientList::removeClient( CClientItem *pClientItem ) { if ( NULL == pClientItem ) return false; dllnode *pNode = dll_findNodeFromID( &m_clientList, pClientItem->m_clientID ); removeData( &pClientItem->m_inputQueue ); if ( NULL != pNode ) { dll_removeNode( &m_clientList, pNode ); } return true; }
BOOL dll_removeAllNodes( struct DoubleLinkedList *pdll ) { if ( NULL == pdll ) return FALSE; while ( NULL != pdll->pHead ) { dll_removeNode( pdll, pdll->pTail ); } dll_init( pdll, 0 ); pdll->nCount = 0; return TRUE; };
bool CPeakObj::readMsg( canalMsg *pMsg ) { bool rv = false; if ( ( NULL != m_receiveList.pHead ) && ( NULL != m_receiveList.pHead->pObject ) ) { memcpy( pMsg, m_receiveList.pHead->pObject, sizeof( canalMsg ) ); LOCK_MUTEX( m_receiveMutex ); dll_removeNode( &m_receiveList, m_receiveList.pHead ); UNLOCK_MUTEX( m_receiveMutex ); rv = true; } return rv; }
int CCAN232Obj::readMsg( canalMsg *pMsg ) { int rv = false; if ( ( NULL != m_can232obj.m_rcvList.pHead ) && ( NULL != m_can232obj.m_rcvList.pHead->pObject ) ) { WaitForSingleObject( m_can232ObjMutex, INFINITE ); memcpy( pMsg, m_can232obj.m_rcvList.pHead->pObject, sizeof( canalMsg ) ); dll_removeNode( &m_can232obj.m_rcvList, m_can232obj.m_rcvList.pHead ); ReleaseMutex( m_can232ObjMutex ); rv = true; } return rv; }
int CCAN232Obj::readMsg(canalMsg *pMsg) { int rv = false; if ((NULL != m_can232obj.m_rcvList.pHead) && (NULL != m_can232obj.m_rcvList.pHead->pObject)) { LOCK_MUTEX(m_can232ObjMutex); memcpy(pMsg, m_can232obj.m_rcvList.pHead->pObject, sizeof( canalMsg)); dll_removeNode(&m_can232obj.m_rcvList, m_can232obj.m_rcvList.pHead); UNLOCK_MUTEX(m_can232ObjMutex); rv = true; } return rv; }
CClientItem::~CClientItem() { //dll_removeAllNodes( &m_inputQueue ); while ( NULL != m_inputQueue.pHead ) { CClientItem *pClientItem = (CClientItem *)m_inputQueue.pTail->pObject; if ( NULL != pClientItem ) { if ( NULL != ( (vscpMsg2*)pClientItem )->pdata ) { delete [] ( ( (vscpMsg2*)pClientItem )->pdata ); ( (vscpMsg2*)pClientItem )->pdata = NULL; } } dll_removeNode( &m_inputQueue, m_inputQueue.pTail ); } }
bool CApoxObj::waitResponse( responseMsg *pMsg, uint32_t timeout ) { uint32_t start = GetTickCount(); while ( GetTickCount() < ( start + timeout ) ){ if ( ( NULL != m_responseList.pHead ) && ( NULL != m_responseList.pHead->pObject ) ) { memcpy( pMsg, m_responseList.pHead->pObject, sizeof( responseMsg ) ); LOCK_MUTEX( m_responseMutex ); dll_removeNode( &m_responseList, m_responseList.pHead ); UNLOCK_MUTEX( m_responseMutex ); return true; } } return false; }
void CClientList::removeData( DoubleLinkedList* pdll ) { // Must be something to worl with if ( NULL == pdll ) return; while ( NULL != pdll->pHead ) { CClientItem *pClientItem = (CClientItem *)pdll->pTail->pObject; if ( NULL != pClientItem ) { if ( NULL != ( (vscpMsg2*)pClientItem )->pdata ) { delete [] ( ( (vscpMsg2*)pClientItem )->pdata ); ( (vscpMsg2*)pClientItem )->pdata = NULL; } } dll_removeNode( pdll, pdll->pTail ); } }
void clientThreadLevel2( void *pThreadObject ) { char *p; char buf[ MAX_PATH ]; vscpEvent *pEvent; dllnode *pNode; CControlObject *pctrlObject = NULL; HANDLE hMap; // http://msdn.microsoft.com/msdnmag/issues/0300/security/default.aspx // here we use a SECURITY_DESCRIPTOR to say // that we don't want *any DACL at all* SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE); SECURITY_ATTRIBUTES sa = { sizeof sa, &sd, TRUE }; _clientstruct clientInfo; memcpy( &clientInfo, (_clientstruct *)pThreadObject, sizeof( _clientstruct ) ); pctrlObject = clientInfo.m_pctrlObject; // We need to create a clientobject and add this object to the list CClientItem *pClientItem = new CClientItem; if ( NULL == pClientItem ) { delete (_clientstruct *)pThreadObject; // Delete the client structure ExitThread( -1 ); } // This is a Level II Client pClientItem->m_ClientLevel = CLIENT_ITEM_LEVEL2; // We need to get the shared memory sprintf( buf, CANAL_LISTEN_CLIENT_SHM_TEMPLATE, clientInfo.m_shmid ); if ( NULL == ( hMap = ::OpenFileMapping( FILE_MAP_WRITE, TRUE, buf ) ) ) { delete (_clientstruct *)pThreadObject; // Delete the client structure ExitThread( -1 ); } struct __shmCanalLevelII *pLevel2 = (struct __shmCanalLevelII *)MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 ); if ( NULL == pLevel2 ) { delete (_clientstruct *)pThreadObject; // Delete the client structure CloseHandle( hMap ); ExitThread( -1 ); } void *pDataArea= pLevel2->m_data; vscpEvent *pEventArea = &pLevel2->m_VSCP_Event; pLevel2->m_command = VSCP_COMMAND_NOOP; // Create the client command semaphore HANDLE hSemCmd; sprintf( buf, CANAL_CLIENT_COMMAND_SEM_TEMPLATE, clientInfo.m_shmid ); if ( NULL == ( hSemCmd = CreateSemaphore( &sa, 0, 1, buf ) ) ) { delete (_clientstruct *)pThreadObject; // Delete the client structure CloseHandle( hMap ); ExitThread( -1 ); } // Create the client Done semaphore HANDLE hSemDone; sprintf( buf, CANAL_CLIENT_DONE_SEM_TEMPLATE, clientInfo.m_shmid ); if ( NULL == ( hSemDone = CreateSemaphore( &sa, 0, 1, buf ) ) ) { delete (_clientstruct *)pThreadObject; // Delete the client structure CloseHandle( hSemCmd ); CloseHandle( hMap ); ExitThread( -1 ); } // Share the command semaphore pLevel2->m_semCmd = clientInfo.m_shmid; // Add the client to the Client List pctrlObject->m_wxClientMutex.Lock(); pctrlObject->addClient( pClientItem ); pctrlObject->m_wxClientMutex.Unlock(); pLevel2->m_test = 0xaa55; // Confirm to client that we are here pClientItem->m_bOpen = true; while ( pClientItem->m_bOpen && !pctrlObject->m_bQuit ) { // Wait for command from client if ( WAIT_OBJECT_0 != WaitForSingleObject( hSemCmd, 500 ) ) { continue; } switch( pLevel2->m_command ) { // * * * * O P E N * * * * case VSCP_COMMAND_OPEN: wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread2: Open"); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * C L O S E * * * * case VSCP_COMMAND_CLOSE: wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread2: Close"); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; pClientItem->m_bOpen = false; break; // * * * * S E N D * * * * case VSCP_COMMAND_SEND: wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread2: Send %X", pClientItem->m_clientID ); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; pNode = new dllnode; if ( NULL != pNode ) { pEvent = new vscpEvent; // Create new VSCP Message if ( NULL != pEvent ) { // Save the originating clients id so // this client dont get the message back pNode->obid = pClientItem->m_clientID; // Copy message memcpy( pEvent, pEventArea, sizeof( vscpEvent ) ); // And data... if ( pEvent->sizeData > 0 ) { // Copy in data pEvent->pdata = new uint8_t[ pEvent->sizeData ]; if ( NULL != pEvent->pdata ) { memcpy( pEvent->pdata, pDataArea ,pEvent->sizeData ); } } else { // No data pEvent->pdata = NULL; } // Check if GUID of interface should be used // as packet GUID if ( pLevel2->m_cmdArg1 ) { memcpy( pEvent->GUID, pClientItem->m_GUID, 16 ); } // Statistics pClientItem->m_statistics.cntTransmitData += pEvent->sizeData; pClientItem->m_statistics.cntTransmitFrames++; // We use the message id as the sort key for the message // in the queue. The high part of this id is the priority // for the message. // The non-id part should possibly be nulled but this depends // on if we regard the message as "sent" or not. If not, a // message with a lower id should be transfered first over the // bus. pNode->Key = pEvent->head; pNode->pKey = &pNode->Key; pNode->pObject = pEvent; // There must be room in the send queue if ( pctrlObject->m_maxItemsInSendQueue > pctrlObject->m_sendLevel2Queue.nCount ) { pctrlObject->m_wxQ2OutMutex.Lock(); if ( !dll_addNode( &pctrlObject->m_sendLevel2Queue, pNode ) ) { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_SEND_STORAGE; } else { pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; SetEvent( pctrlObject->m_hEventSendQ2 ); } pctrlObject->m_wxQ2OutMutex.Unlock(); } else { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_BUFFER_FULL; if ( NULL != pNode ) { if ( NULL != pNode->pObject ) { if ( NULL != pEvent->pdata ) delete [] pEvent->pdata; delete pEvent; } delete pNode; } } } else { delete pNode; pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_SEND_MSG_ALLOCATON; } } // dllNode break; // * * * * R E C E I V E * * * * case VSCP_COMMAND_RECEIVE: wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread2: Receive - before client lock %X", pClientItem->m_clientID ); pClientItem->m_wxMsgMutex.Lock(); if ( !pClientItem->m_bOpen ) { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { dllnode *pNode; vscpEvent *pEvent = (vscpEvent *)pEventArea; if ( NULL != ( pNode = pClientItem->m_inputQueue.pHead ) ) { // There is a message available pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; // Copy message memcpy( pEvent, pNode->pObject, sizeof( vscpEvent ) ); // If there is data it also must be copied if ( ( pEvent->sizeData > 0 ) && ( NULL != pEvent->pdata ) ) { memcpy( pDataArea, pEvent->pdata, pEvent->sizeData ); } // Remove the old data if ( NULL != pEvent->pdata ) delete pEvent->pdata; pEvent->pdata = NULL; // Data stored in message // Remove the node dll_removeNode( &pClientItem->m_inputQueue, pNode ); // If queue empty reset receive flag if ( NULL == ( pNode = pClientItem->m_inputQueue.pHead ) ) { ResetEvent( pClientItem->m_hEventReceive ); } } } pClientItem->m_wxMsgMutex.Unlock(); break; // * * * * D A T A A V A I L A B L E * * * * case VSCP_COMMAND_CHECKDATA: //wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread%n: Data Available %X", pClientItem->m_clientID. pClientItem->m_inputQueue.nCount); pClientItem->m_wxMsgMutex.Lock(); if ( !pClientItem->m_bOpen ) { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; unsigned int *pnMsg = (unsigned int *)pDataArea; //*pnMsg = dll_getNodeCount( &pClientItem->m_inputQueue ); *pnMsg = pClientItem->m_inputQueue.nCount; } pClientItem->m_wxMsgMutex.Unlock(); break; // * * * * S T A T U S * * * * case VSCP_COMMAND_STATUS: if ( !pClientItem->m_bOpen ) { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; // Status memcpy( pDataArea, &pClientItem->m_status, sizeof( canalStatus ) ); } break; // * * * * S T A T I S T I C S * * * * case VSCP_COMMAND_STATISTICS: if ( !pClientItem->m_bOpen ) { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { memcpy( pDataArea, &pClientItem->m_statistics, sizeof( &pClientItem->m_statistics ) ); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; } break; // * * * * F I L T E R * * * * case VSCP_COMMAND_FILTER: if ( !pClientItem->m_bOpen ) { pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { // Set filter memcpy( &pClientItem->m_filter, pDataArea, sizeof( vscpEventFilter ) ); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; } break; // * * * * V E R S I O N * * * * case VSCP_COMMAND_VERSION: // Get version p = (char *)pDataArea; *( p + POS_VSCPD_MAJOR_VERSION ) = CANAL_MAIN_VERSION; *( p + POS_VSCPD_MINOR_VERSION ) = CANAL_MINOR_VERSION; *( p + POS_VSCPD_SUB_VERSION ) = CANAL_SUB_VERSION; pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * G E T I / F G U I D * * * * case VSCP_COMMAND_GET_GUID: memcpy( pDataArea, pClientItem->m_GUID, 16 ); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * S E T I / F G U I D * * * * case VSCP_COMMAND_SET_GUID: memcpy( pClientItem->m_GUID, pDataArea, 16 ); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * G E T C H A N N E L I D * * * * case VSCP_COMMAND_GET_CHID: break; // * * * * N O O P * * * * case VSCP_COMMAND_NOOP: wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread2: NOOP %X", pClientItem->m_clientID); pLevel2->m_Response = CANAL_RESPONSE_SUCCESS; break; default: wxLogTrace("wxTRACE_Canald_LevelII", "ClientThread2: Unknown command %X", pClientItem->m_clientID); pLevel2->m_Response = CANAL_RESPONSE_ERROR; pLevel2->m_ResponseCode = CANAL_IFERROR_UNKNOWN_COMMAND; break; } // We are Done ReleaseSemaphore( hSemDone, 1, NULL ); } // while running wxLogTrace( "wxTRACE_Canald_LevelII", "ClientThread2: About to end. ClientId = %X", pClientItem->m_clientID ); // Remove messages in the client queues pctrlObject->removeClient( pClientItem ); wxLogDebug("ClientThread2: Removed client item."); delete (_clientstruct *)pThreadObject; CloseHandle( hMap ); CloseHandle( hSemCmd ); CloseHandle( hSemDone ); wxLogDebug("ClientThread2: Exit."); ExitThread( 0 ); }
void workThread( void *pThreadObject ) { bool bRun = true; bool bActivity = true; short nPollCnt = 0; DWORD errorCode = 0; HANDLE can232ObjMutex; // Must hav a valid work object if ( NULL == pThreadObject ) ExitThread( errorCode ); // Get the object pointer in place struct _can232obj *pcan232obj = (struct _can232obj *)pThreadObject; can232ObjMutex = OpenMutex( MUTEX_ALL_ACCESS, false, CAN232_OBJ_MUTEX ); while ( pcan232obj->m_bRun ) { /////////////////////////////////////////////////////////////////////// // Receive /////////////////////////////////////////////////////////////////////// WaitForSingleObject( can232ObjMutex, INFINITE ); int cnt; unsigned char c; c = pcan232obj->m_comm.readChar( &cnt ); while ( 0 != cnt ) { bActivity = true; if ( CAN232_STATE_NONE == pcan232obj->m_state ) { if ( ('t' == c ) || ( 'T' == c ) || ('r' == c ) || ( 'R' == c ) ) { pcan232obj->m_state = CAN232_STATE_MSG; pcan232obj->m_receiveBuf[ 0 ] = c; pcan232obj->m_cntRcv = 1; } } else if ( CAN232_STATE_MSG == pcan232obj->m_state ) { pcan232obj->m_receiveBuf[ pcan232obj->m_cntRcv++ ] = c; if ( 0x0d == c ) { // One full message received // If there is place in the queue // add message to it if ( pcan232obj->m_rcvList.nCount < CAN232_MAX_RCVMSG ) { PCANALMSG pMsg = new canalMsg; pMsg->flags = 0; if ( NULL != pMsg ) { dllnode *pNode = new dllnode; if ( NULL != pNode ) { if ( !can323ToCanal( pcan232obj->m_receiveBuf, pMsg ) ) { pNode->pObject = pMsg; dll_addNode( &pcan232obj->m_rcvList, pNode ); // Update statistics pcan232obj->m_stat.cntReceiveData += pMsg->sizeData; pcan232obj->m_stat.cntReceiveFrames += 1; } else { // Failed to translate message delete pMsg; delete pNode; } } else { delete pMsg; } } } pcan232obj->m_state = CAN232_STATE_NONE; } if ( pcan232obj->m_cntRcv > sizeof( pcan232obj->m_receiveBuf ) ) { // Problems start all over again pcan232obj->m_state = CAN232_STATE_NONE; } } c = pcan232obj->m_comm.readChar( &cnt ); } // while ReleaseMutex( can232ObjMutex ); /////////////////////////////////////////////////////////////////////// // Transmit /////////////////////////////////////////////////////////////////////// WaitForSingleObject( can232ObjMutex, INFINITE ); // Is there anything to transmit if ( ( NULL != pcan232obj->m_sndList.pHead ) && ( NULL != pcan232obj->m_sndList.pHead->pObject ) ) { char buf[ 80 ]; canalMsg msg; bActivity = true; memcpy( &msg, pcan232obj->m_sndList.pHead->pObject, sizeof( canalMsg ) ); dll_removeNode( &pcan232obj->m_sndList, pcan232obj->m_sndList.pHead ); // Must be a valid standard id if ( !( msg.flags & CANAL_IDFLAG_EXTENDED ) && ( msg.id > 0x7ff ) ) { msg.id &= 0x7ff; }; // Must be a valid extended id if ( ( msg.flags & CANAL_IDFLAG_EXTENDED ) && ( msg.id > 0x1fffffff ) ) { msg.id &= 0x1fffffff; } if ( msg.flags & CANAL_IDFLAG_EXTENDED ) { sprintf( buf, "T%08.8lX%i", msg.id, msg.sizeData ); } else { sprintf( buf, "t%03.3lX%i", msg.id, msg.sizeData ); } if ( msg.sizeData ) { char hex[5]; for ( int i= 0; i< msg.sizeData; i++ ) { sprintf( hex, "%02.2X", msg.data[i] ); strcat( buf, hex ); } } // Send the data char szResponse[ 32 ]; pcan232obj->m_comm.write( buf, true, true ); pcan232obj->m_comm.readBuf( szResponse, sizeof( szResponse ), -1 ); // Update statistics pcan232obj->m_stat.cntTransmitData += msg.sizeData; pcan232obj->m_stat.cntTransmitFrames += 1; // If not in autopoll mode if ( 0x0d == *szResponse ) { } // If in autopoll mode extended message else if ( ( msg.flags & CANAL_IDFLAG_EXTENDED ) && ( 'Z' == *szResponse ) ) { } // If in autopoll mode standard message else if ( !( msg.flags & CANAL_IDFLAG_EXTENDED ) && ( 'z' == *szResponse ) ) { } } // If not in autopoll mode we do a poll for all frames first nPollCnt++; if ( !pcan232obj->m_bAuto && ( nPollCnt > 5 ) ) { pcan232obj->m_comm.write( "A", true, true ); nPollCnt = 0; } ReleaseMutex( can232ObjMutex ); if ( !bActivity ) Sleep ( 100 ); bActivity = false; } // Release the mutex for other threads to use ReleaseMutex( can232ObjMutex ); ExitThread( errorCode ); }
void *workThreadTransmit( void *pObject ) #endif { #ifdef WIN32 DWORD errorCode = 0; #else int rv = 0; #endif CPeakObj * pobj = ( CPeakObj *)pObject; if ( NULL == pobj ) { #ifdef WIN32 ExitThread( errorCode ); // Fail #else pthread_exit( &rv ); #endif } while ( pobj->m_bRun ) { LOCK_MUTEX( pobj->m_peakMutex ); // Noting to do if we should end... if ( !pobj->m_bRun ) continue; // Is there something to transmit... int ret; while ( ( NULL != pobj->m_transmitList.pHead ) && ( NULL != pobj->m_transmitList.pHead->pObject ) ) { canalMsg msg; memcpy( &msg, pobj->m_transmitList.pHead->pObject, sizeof( canalMsg ) ); LOCK_MUTEX( pobj->m_transmitMutex ); dll_removeNode( &pobj->m_transmitList, pobj->m_transmitList.pHead ); UNLOCK_MUTEX( pobj->m_transmitMutex ); PeakCanMsg peakMsg; peakMsg.id = msg.id; peakMsg.msgType = 0; peakMsg.len = msg.sizeData; memcpy( peakMsg.data, msg.data, peakMsg.len ); // Check if RTR if ( ( msg.flags & CANAL_IDFLAG_RTR ) ) { peakMsg.msgType |= PCAN_MSGTYPE_RTR; } // Check if extended if ( ( msg.flags & CANAL_IDFLAG_EXTENDED ) ) { peakMsg.msgType |= PCAN_MSGTYPE_EXTENDED; } if ( PEAK_CAN_ERR_OK == ( ret = pobj->m_procWrite( &peakMsg ) ) ) { // Message sent successfully // Update statistics pobj->m_stat.cntTransmitData += msg.sizeData; pobj->m_stat.cntTransmitFrames += 1; } else { // Failed - put message back in queue front PCANALMSG pMsg = new canalMsg; if ( NULL != pMsg ) { // Copy in data memcpy ( pMsg, &msg, sizeof( canalMsg ) ); dllnode *pNode = new dllnode; if ( NULL != pNode ) { pNode->pObject = pMsg; LOCK_MUTEX( pobj->m_transmitMutex ); dll_addNodeHead( &pobj->m_transmitList, pNode ); UNLOCK_MUTEX( pobj->m_transmitMutex ); } else { delete pMsg; } } // unable to allocate storage } // faild to send message } // while data // No data to write UNLOCK_MUTEX( pobj->m_peakMutex ); SLEEP( 1 ); //} } // while #ifdef WIN32 ExitThread( errorCode ); #else pthread_exit( &rv ); #endif }
void *workThreadTransmit( void *pObject ) #endif { #ifdef WIN32 DWORD errorCode = 0; #else int rv = 0; #endif CVectorObj * pobj = ( CVectorObj *)pObject; if ( NULL == pobj ) { #ifdef WIN32 ExitThread( errorCode ); // Fail #else pthread_exit( &rv ); #endif } while ( pobj->m_bRun ) { LOCK_MUTEX( pobj->m_vectorMutex ); // Noting to do if we should end... if ( !pobj->m_bRun ) continue; // Is there something to transmit while ( ( NULL != pobj->m_transmitList.pHead ) && ( NULL != pobj->m_transmitList.pHead->pObject ) ) { canalMsg msg; memcpy( &msg, pobj->m_transmitList.pHead->pObject, sizeof( canalMsg ) ); LOCK_MUTEX( pobj->m_transmitMutex ); dll_removeNode( &pobj->m_transmitList, pobj->m_transmitList.pHead ); UNLOCK_MUTEX( pobj->m_transmitMutex ); VCAN_EVENT event; event.tag = V_TRANSMIT_MSG; // id event.tagData.msg.id = msg.id; if ( msg.flags & CANAL_IDFLAG_EXTENDED ) { event.tagData.msg.id |= VCAN_EXT_MSG_ID; // Extended } // size event.tagData.msg.dlc = msg.sizeData; // Vector flags event.tagData.msg.flags = 0; if ( msg.flags & CANAL_IDFLAG_RTR ) { event.tagData.msg.flags |= MSGFLAG_REMOTE_FRAME; // RTR } // Data memcpy( event.tagData.msg.data, msg.data, msg.sizeData ); if ( VERR_QUEUE_IS_FULL != ncdTransmit( pobj->m_portHandle, pobj->m_channelMask, &event ) ) { // Message sent successfully // Update statistics pobj->m_stat.cntTransmitData += msg.sizeData; pobj->m_stat.cntTransmitFrames += 1; } else { // Failed - put message back in queue front PCANALMSG pMsg = new canalMsg; if ( NULL != pMsg ) { // Copy in data memcpy ( pMsg, &msg, sizeof( canalMsg ) ); dllnode *pNode = new dllnode; if ( NULL != pNode ) { pNode->pObject = pMsg; LOCK_MUTEX( pobj->m_transmitMutex ); dll_addNodeHead( &pobj->m_transmitList, pNode ); UNLOCK_MUTEX( pobj->m_transmitMutex ); } else { delete pMsg; } } } // send message } // while data // No data to write UNLOCK_MUTEX( pobj->m_vectorMutex ); SLEEP( 1 ); //} } // while #ifdef WIN32 ExitThread( errorCode ); #else pthread_exit( &rv ); #endif }
void clientThreadLevel1( void *pThreadObject ) { char buf[ MAX_PATH ]; char *p; canalMsg *pMsg; dllnode *pNode; CControlObject *pctrlObject = NULL; HANDLE hMap; wxLogDebug("Level I Client Started"); // http://msdn.microsoft.com/msdnmag/issues/0300/security/default.aspx // here we use a SECURITY_DESCRIPTOR to say // that we don't want *any DACL at all* SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE); SECURITY_ATTRIBUTES sa = { sizeof sa, &sd, TRUE }; _clientstruct clientInfo; memcpy( &clientInfo, (_clientstruct *)pThreadObject, sizeof( _clientstruct ) ); pctrlObject = clientInfo.m_pctrlObject; // We need to create a clientobject and add this object to the list CClientItem *pClientItem = new CClientItem; if ( NULL == pClientItem ) { delete (_clientstruct *)pThreadObject; // Delete the client structure ExitThread( -1 ); } wxLogDebug("Level I Client 1"); // This is a Level II Client pClientItem->m_ClientLevel = CLIENT_ITEM_LEVEL1; // We need to get the shared memory sprintf( buf, CANAL_LISTEN_CLIENT_SHM_TEMPLATE, clientInfo.m_shmid ); if ( NULL == ( hMap = ::OpenFileMapping( FILE_MAP_WRITE, TRUE, buf ) ) ) { delete (_clientstruct *)pThreadObject; // Delete the client structure ExitThread( -1 ); } wxLogDebug("Level I Client 5"); struct __shmCanalLevelI *pLevel1 = (struct __shmCanalLevelI *)MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 ); if ( NULL == pLevel1 ) { delete (_clientstruct *)pThreadObject; // Delete the client structure CloseHandle( hMap ); ExitThread( -1 ); } wxLogDebug("Level I Client 6"); void *pDataArea= pLevel1->m_data; pLevel1->m_command = CANAL_COMMAND_NOOP; // Create the client command semaphore HANDLE hSemCmd; sprintf( buf, CANAL_CLIENT_COMMAND_SEM_TEMPLATE, clientInfo.m_shmid ); if ( NULL == ( hSemCmd = CreateSemaphore( &sa, 0, 1, buf ) ) ) { delete (_clientstruct *)pThreadObject; // Delete the client structure CloseHandle( hMap ); ExitThread( -1 ); } wxLogDebug("Level I Client 7"); // Create the client Done semaphore HANDLE hSemDone; sprintf( buf, CANAL_CLIENT_DONE_SEM_TEMPLATE, clientInfo.m_shmid ); if ( NULL == ( hSemDone = CreateSemaphore( &sa, 0, 1, buf ) ) ) { delete (_clientstruct *)pThreadObject; // Delete the client structure CloseHandle( hSemCmd ); CloseHandle( hMap ); ExitThread( -1 ); } wxLogDebug("Level I Client 7"); // Share the command semaphore pLevel1->m_semCmd = clientInfo.m_shmid; // Add the client to the Client List pctrlObject->m_wxClientMutex.Lock(); pctrlObject->addClient( pClientItem ); pctrlObject->m_wxClientMutex.Unlock(); pLevel1->m_test = 0xaa55; // Confirm to client that we are here pClientItem->m_bOpen = true; while ( pClientItem->m_bOpen && !pctrlObject->m_bQuit ) { // Wait for command from client if ( WAIT_OBJECT_0 != WaitForSingleObject( hSemCmd, 500 ) ) { continue; } switch( pLevel1->m_command ) { // * * * * O P E N * * * * case CANAL_COMMAND_OPEN: pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * C L O S E * * * * case CANAL_COMMAND_CLOSE: pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; pClientItem->m_bOpen = false; break; // * * * * S E N D * * * * case CANAL_COMMAND_SEND: pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; pNode = new dllnode; if ( NULL != pNode ) { pMsg = new canalMsg; // Create new Canal Message if ( NULL != pMsg ) { // Save the originating clients id so // this client dont get the message back pNode->obid = pClientItem->m_clientID; // Copy message memcpy( pMsg, pDataArea, sizeof( canalMsg ) ); // Statistics pClientItem->m_statistics.cntTransmitData += pMsg->sizeData; pClientItem->m_statistics.cntTransmitFrames++; // We use the message id as the sort key for the message // in the queue. The high part of this id is the priority // for the message. // The non-id part should possibly be nulled but this depends // on if we regard the message as "sent" or not. If not, a // message with a lower id should be transfered first over the // bus. pNode->Key = pMsg->id; pNode->pKey = &pNode->Key; pNode->pObject = pMsg; // There must be room in the send queue if ( pctrlObject->m_maxItemsInSendQueue > pctrlObject->m_sendLevel1Queue.nCount ) { pctrlObject->m_wxQ1OutMutex.Lock(); if ( !dll_addNode( &pctrlObject->m_sendLevel1Queue, pNode ) ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_SEND_STORAGE; } else { pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; SetEvent( pctrlObject->m_hEventSendQ1 ); } pctrlObject->m_wxQ1OutMutex.Unlock(); } else { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_BUFFER_FULL; if ( NULL != pNode ) { if ( NULL != pNode->pObject ) { delete pMsg; } delete pNode; } } } else { delete pNode; pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_SEND_MSG_ALLOCATON; } } // dllNode break; // * * * * R E C E I V E * * * * case CANAL_COMMAND_RECEIVE: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { pctrlObject->m_wxClientMutex.Lock(); dllnode *pNode; canalMsg *pMsg = (canalMsg *)pDataArea; if ( NULL != ( pNode = pClientItem->m_inputQueue.pHead ) ) { // There is a message available pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; memcpy( pMsg, pNode->pObject, sizeof( canalMsg ) ); // Remove the node dll_removeNode( &pClientItem->m_inputQueue, pNode ); // If queue empty reset receive flag if ( NULL == ( pNode = pClientItem->m_inputQueue.pHead ) ) { ResetEvent( pClientItem->m_hEventReceive ); } } pctrlObject->m_wxClientMutex.Unlock(); } break; // * * * * D A T A A V A I L A B L E * * * * case CANAL_COMMAND_CHECKDATA: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; unsigned int *pnMsg = (unsigned int *)pDataArea; //*pnMsg = dll_getNodeCount( &pClient->m_inputQueue ); *pnMsg = pClientItem->m_inputQueue.nCount; } break; // * * * * S T A T U S * * * * case CANAL_COMMAND_STATUS: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; // Status memcpy( pDataArea, &pClientItem->m_status, sizeof( canalStatus ) ); } break; // * * * * S T A T I S T I C S * * * * case CANAL_COMMAND_STATISTICS: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { memcpy( pDataArea, &pClientItem->m_statistics, sizeof( &pClientItem->m_statistics ) ); pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; } break; // * * * * F I L T E R * * * * case CANAL_COMMAND_FILTER: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { // Set filter memcpy( &pClientItem->m_filter, pDataArea, sizeof( pClientItem->m_filter ) ); pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; } break; // * * * * M A S K * * * * case CANAL_COMMAND_MASK: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { // Set mask memcpy( &pClientItem->m_mask, pDataArea, sizeof( pClientItem->m_mask ) ); pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; } break; // * * * * B A U D R A T E * * * * case CANAL_COMMAND_BAUDRATE: if ( !pClientItem->m_bOpen ) { pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_CHANNEL_CLOSED; } else { // Set baudrate // ============ // We don't have yo do more here the baudrate change // is just simulated in the pipe interface pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; } break; // * * * * V E R S I O N * * * * case CANAL_COMMAND_VERSION: // Get version p = (char *)pDataArea; *( p + POS_VSCPD_MAJOR_VERSION ) = CANAL_MAIN_VERSION; *( p + POS_VSCPD_MINOR_VERSION ) = CANAL_MINOR_VERSION; *( p + POS_VSCPD_SUB_VERSION ) = CANAL_SUB_VERSION; pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * D L L - V E R S I O N * * * * case CANAL_COMMAND_DLL_VERSION: // Get DLL version // This application returns the vscp daemon // version. p = (char *)pDataArea; *( p + POS_VSCPD_MAJOR_VERSION ) = VSCPD_MAJOR_VERSION; *( p + POS_VSCPD_MINOR_VERSION ) = VSCPD_MINOR_VERSION; *( p + POS_VSCPD_SUB_VERSION ) = VSCPD_SUB_VERSION; *( p + POS_VSCPD_SUB_VERSION + 1 ) = 0; pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * V E N D O R S T R I N G * * * * case CANAL_COMMAND_VENDOR_STRING: // Get vendor string pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; p = (char *)pDataArea; strcpy( p, VENDOR_STRING ); break; // * * * * L E V E L * * * * case CANAL_COMMAND_LEVEL: // Get i/f supported levels p = (char *)pDataArea; *( p + 0 ) = 0; *( p + 1 ) = 0; *( p + 2 ) = 0; *( p + 3 ) = CANAL_LEVEL_STANDARD; pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; break; // * * * * N O O P * * * * case CANAL_COMMAND_NOOP: pLevel1->m_Response = CANAL_RESPONSE_SUCCESS; break; default: pLevel1->m_Response = CANAL_RESPONSE_ERROR; pLevel1->m_ResponseCode = CANAL_IFERROR_UNKNOWN_COMMAND; break; } // We are Done ReleaseSemaphore( hSemDone, 1, NULL ); } // while running // Client not needed anymore pctrlObject->removeClient( pClientItem ); delete (_clientstruct *)pThreadObject; CloseHandle( hMap ); CloseHandle( hSemCmd ); CloseHandle( hSemDone ); ExitThread( 0 ); }
void *workThreadTransmit( void *pObject ) #endif { #ifdef WIN32 DWORD errorCode = 0; #else int rv = 0; #endif CIxxObj * pobj = ( CIxxObj *)pObject; if ( NULL == pobj ) { #ifdef WIN32 ExitThread( errorCode ); // Fail #else pthread_exit( &rv ); #endif } while ( pobj->m_bRun ) { LOCK_MUTEX( pobj->m_ixxMutex ); // Noting to do if we should end... if ( !pobj->m_bRun ) continue; // Is there something to transmit while ( ( NULL != pobj->m_transmitList.pHead ) && ( NULL != pobj->m_transmitList.pHead->pObject ) ) { canalMsg msg; memcpy( &msg, pobj->m_transmitList.pHead->pObject, sizeof( canalMsg ) ); LOCK_MUTEX( pobj->m_transmitMutex ); dll_removeNode( &pobj->m_transmitList, pobj->m_transmitList.pHead ); UNLOCK_MUTEX( pobj->m_transmitMutex ); if ( !( msg.flags & CANAL_IDFLAG_RTR ) ) { // Standard message if ( VCI_OK == VCI_TransmitObj( pobj->m_hBoard, pobj->m_hTxQue, msg.id, msg.sizeData, msg.data ) ) { // Message sent successfully // Update statistics pobj->m_stat.cntTransmitData += msg.sizeData; pobj->m_stat.cntTransmitFrames += 1; } else { // Failed - put message back in queue front PCANALMSG pMsg = new canalMsg; if ( NULL != pMsg ) { // Copy in data memcpy ( pMsg, &msg, sizeof( canalMsg ) ); dllnode *pNode = new dllnode; if ( NULL != pNode ) { pNode->pObject = pMsg; LOCK_MUTEX( pobj->m_transmitMutex ); dll_addNodeHead( &pobj->m_transmitList, pNode ); UNLOCK_MUTEX( pobj->m_transmitMutex ); } else { delete pMsg; } } } } else { // Remote request if ( VCI_OK == VCI_RequestObj( pobj->m_hBoard, pobj->m_hTxQue, msg.id, msg.sizeData ) ) { // Message sent successfully // Update statistics pobj->m_stat.cntTransmitFrames += 1; } else { // Failed - put message back in queue front PCANALMSG pMsg = new canalMsg; if ( NULL != pMsg ) { // Copy in data memcpy ( pMsg, &msg, sizeof( canalMsg ) ); dllnode *pNode = new dllnode; if ( NULL != pNode ) { pNode->pObject = pMsg; LOCK_MUTEX( pobj->m_transmitMutex ); dll_addNodeHead( &pobj->m_transmitList, pNode ); UNLOCK_MUTEX( pobj->m_transmitMutex ); } else { delete pMsg; } } } } } // while data // No data to write UNLOCK_MUTEX( pobj->m_ixxMutex ); SLEEP( 1 ); //} } // while #ifdef WIN32 ExitThread( errorCode ); #else pthread_exit( &rv ); #endif }
void *workThread(void *pObject) { int rv = 0; int cnt; bool bActivity = true; short nPollCnt = 0; char szResponse[ 32 ]; printf("can232obj in workThread\n"); CCAN232Obj * pcan232obj = (CCAN232Obj *) pObject; if (NULL == pcan232obj) { pthread_exit(&rv); } while (pcan232obj->m_can232obj.m_bRun) { /////////////////////////////////////////////////////////////////////// // Receive /////////////////////////////////////////////////////////////////////// LOCK_MUTEX(pcan232obj->m_can232ObjMutex); // Noting to do if we should end... if (!pcan232obj->m_can232obj.m_bRun) continue; int cnt; unsigned char c; //printf("workThread - Receive\n"); c = pcan232obj->m_can232obj.m_comm.readChar(&cnt); while (-1 != cnt) { bActivity = true; if (CAN232_STATE_NONE == pcan232obj->m_can232obj.m_state) { if (('t' == c) || ('T' == c) || ('r' == c) || ('R' == c)) { pcan232obj->m_can232obj.m_state = CAN232_STATE_MSG; pcan232obj->m_can232obj.m_receiveBuf[ 0 ] = c; pcan232obj->m_can232obj.m_cntRcv = 1; } } else if (CAN232_STATE_MSG == pcan232obj->m_can232obj.m_state) { pcan232obj->m_can232obj.m_receiveBuf[ pcan232obj->m_can232obj.m_cntRcv++ ] = c; if (0x0d == c) { // One full message received If there is place in the queue // add message to it if (pcan232obj->m_can232obj.m_rcvList.nCount < CAN232_MAX_RCVMSG) { PCANALMSG pMsg = new canalMsg; pMsg->flags = 0; if (NULL != pMsg) { dllnode *pNode = new dllnode; if (NULL != pNode) { printf("workThread R - m_receiveBuf = [%s]\n", pcan232obj->m_can232obj.m_receiveBuf); int cnt = pcan232obj->m_can232obj.m_cntRcv; printf("workThread R - m_receiveBuf ["); for (int i = 0; i < cnt; i++) { printf("%02X ", pcan232obj->m_can232obj.m_receiveBuf[i]); } printf("]\n"); if (!can232ToCanal(pcan232obj->m_can232obj.m_receiveBuf, pMsg)) { pNode->pObject = pMsg; dll_addNode(&pcan232obj->m_can232obj.m_rcvList, pNode); // Update statistics pcan232obj->m_can232obj.m_stat.cntReceiveData += pMsg->sizeData; pcan232obj->m_can232obj.m_stat.cntReceiveFrames += 1; printf("workThread R - RcvFrames = [%ld]\n\n", pcan232obj->m_can232obj.m_stat.cntReceiveFrames); } else { // Failed to translate message printf("workThread R - Receive Failed to translate message\n"); delete pMsg; delete pNode; } } else { delete pMsg; } } } pcan232obj->m_can232obj.m_state = CAN232_STATE_NONE; } if (pcan232obj->m_can232obj.m_cntRcv > sizeof( pcan232obj->m_can232obj.m_receiveBuf)) { // Problems start all over again pcan232obj->m_can232obj.m_state = CAN232_STATE_NONE; } } c = pcan232obj->m_can232obj.m_comm.readChar(&cnt); } // while ( 0 != cnt ) UNLOCK_MUTEX(pcan232obj->m_can232ObjMutex); /////////////////////////////////////////////////////////////////////// // Transmit /////////////////////////////////////////////////////////////////////// //printf("workThread - Transmit\n"); LOCK_MUTEX(pcan232obj->m_can232ObjMutex); // Is there something to transmit // while ( ( NULL != pcan232obj->m_can232obj.m_sndList.pHead ) && // ( NULL != pcan232obj->m_can232obj.m_sndList.pHead->pObject ) ) { if ((NULL != pcan232obj->m_can232obj.m_sndList.pHead) && (NULL != pcan232obj->m_can232obj.m_sndList.pHead->pObject)) { char buf[ 80 ]; canalMsg msg; bActivity = true; memcpy(&msg, pcan232obj->m_can232obj.m_sndList.pHead->pObject, sizeof( canalMsg)); dll_removeNode(&pcan232obj->m_can232obj.m_sndList, pcan232obj->m_can232obj.m_sndList.pHead); // Must be a valid standard id if (!(msg.flags & CANAL_IDFLAG_EXTENDED) && (msg.id > 0x7ff)) { msg.id &= 0x7ff; }; // Must be a valid extended id if ((msg.flags & CANAL_IDFLAG_EXTENDED) && (msg.id > 0x1fffffff)) { msg.id &= 0x1fffffff; } // Currently there is a bug in ice old asm can232 tranceiver, and allow only small hex digits if (msg.flags & CANAL_IDFLAG_EXTENDED) { sprintf(buf, "T%8.8lx%i", msg.id, msg.sizeData); } else { sprintf(buf, "t%3.3lx%i", msg.id, msg.sizeData); } if (msg.sizeData) { char hex[5]; for (int i = 0; i < msg.sizeData; i++) { sprintf(hex, "%2.2X", msg.data[i]); //sprintf( hex, "%02.2x", msg.data[i] ); strcat(buf, hex); } strcat(buf, "\r"); } // Send the data pcan232obj->m_can232obj.m_comm.comm_puts(buf, strlen(buf), true); printf("workThread T - Write ["); for (int i = 0; i < strlen(buf); i++) { if (buf[i] == 0x0D) { printf("[CR]"); } else { printf("%c", buf[i]); } } printf("]\n"); pcan232obj->m_can232obj.m_comm.comm_gets(szResponse, sizeof( szResponse), 10000); printf("workThread T - Read ["); for (int i = 0; i < strlen(szResponse); i++) { if (szResponse[i] == 0x0D) { printf("[CR]"); } else { printf("%c", szResponse[i]); } } printf("]\n\n"); // needed !! At least at 19200 baud SLEEP(100); // Update statistics pcan232obj->m_can232obj.m_stat.cntTransmitData += msg.sizeData; pcan232obj->m_can232obj.m_stat.cntTransmitFrames += 1; //} // while there is something to transmit } // if there is something to transmit // If not in autopoll mode we do a poll for all frames first nPollCnt++; if (!pcan232obj->m_can232obj.m_bAuto && (nPollCnt > 5)) { char szCmd[5]; sprintf(szCmd, "A\r"); pcan232obj->m_can232obj.m_comm.comm_puts(szCmd, strlen(szCmd), true); nPollCnt = 0; } UNLOCK_MUTEX(pcan232obj->m_can232ObjMutex); if (!bActivity) SLEEP(100); bActivity = false; } // while( pcan232obj->m_can232obj.m_bRun ) pthread_exit(&rv); }
void *workThreadTransmit( void *pObject ) #endif { #ifdef WIN32 DWORD errorCode = 0; #else int rv = 0; #endif CApoxObj * pobj = ( CApoxObj *)pObject; if ( NULL == pobj ) { #ifdef WIN32 ExitThread( errorCode ); // Fail #else pthread_exit( &rv ); #endif } while ( pobj->m_bRun ) { // Noting to do if we should end... if ( !pobj->m_bRun ) continue; // Is there something to transmit while ( ( NULL != pobj->m_transmitList.pHead ) && ( NULL != pobj->m_transmitList.pHead->pObject ) ) { canalMsg msg; memcpy( &msg, pobj->m_transmitList.pHead->pObject, sizeof( canalMsg ) ); LOCK_MUTEX( pobj->m_transmitMutex ); dll_removeNode( &pobj->m_transmitList, pobj->m_transmitList.pHead ); UNLOCK_MUTEX( pobj->m_transmitMutex ); // Outgoing CAN message // -------------------------- // [0] ([1][RTR][EXT][unused 0..4]) // [1] ID MSB // [2] ID // [3] ID // [4] ID LSB // [5] FUTURE USE (CANopen or DeviceNet) // ex. Wait for response? Etc.. // [6] FUTURE USE (CANopen or DeviceNet) // [7] RESERVED FOR TX FLAGS // [8] DATA LEN (0-8) // [9-16] uint8_t sendData[ 20 ]; short size = 0; sendData[ size++ ] = 0x80 | ( ( msg.flags & CANAL_IDFLAG_RTR ) ? 0x40:0x00) | ( ( msg.flags & CANAL_IDFLAG_EXTENDED ) ? 0x20 : 0x00 ); sendData[ size++ ] = ( uint8_t )( msg.id >> 24 ) & 0x1f; sendData[ size++ ] = ( uint8_t )( msg.id >> 16 ) & 0xff; sendData[ size++ ] = ( uint8_t )( msg.id >> 8 ) & 0xff; sendData[ size++ ] = ( uint8_t )( msg.id ) & 0xff; sendData[size++] = 0x00; // future use sendData[size++] = 0x00; // future use sendData[size++] = 0; // txFlags; sendData[size++] = msg.sizeData; memcpy( sendData, msg.data, msg.sizeData ); size += msg.sizeData; LOCK_MUTEX( pobj->m_apoxMutex ); if ( USB_OK == pobj->sendUSBMsg( sendData, size ) ) { // Message sent successfully // Update statistics pobj->m_stat.cntTransmitData += msg.sizeData; pobj->m_stat.cntTransmitFrames += 1; } else { // Failed - put message back in queue front PCANALMSG pMsg = new canalMsg; if ( NULL != pMsg ) { // Copy in data memcpy ( pMsg, &msg, sizeof( canalMsg ) ); dllnode *pNode = new dllnode; if ( NULL != pNode ) { pNode->pObject = pMsg; LOCK_MUTEX( pobj->m_transmitMutex ); dll_addNodeHead( &pobj->m_transmitList, pNode ); UNLOCK_MUTEX( pobj->m_transmitMutex ); } else { delete pMsg; } } } UNLOCK_MUTEX( pobj->m_apoxMutex ); } // while data // No data to write SLEEP( 1 ); //} } // while #ifdef WIN32 ExitThread( errorCode ); #else pthread_exit( &rv ); #endif }