//********************************************************************// // Transmission d'une trame //********************************************************************// U8 tcCanVector::ReqTrameUU(tObjetCanUU* pObjetCan,tTrameCan* pTrameCan) { Vstatus StatutOld; Vevent vEvent; vEvent.tag = V_TRANSMIT_MSG; vEvent.tagData.msg.id = pObjetCan->Id & ~cCanRemoteFrameFlag; vEvent.tagData.msg.flags = pObjetCan->Id&cCanRemoteFrameFlag?VCAN_MSG_FLAG_REMOTE_FRAME:0; vEvent.tagData.msg.dlc = pTrameCan->Longueur; if ( pObjetCan->ModeHighVoltage == cTrue ) { // On vide la file d'emission hard ncdFlushTransmitQueue(m_gPortHandle,m_gChannelMask); // On positionne le flag wake-up vEvent.tagData.msg.flags = MSGFLAG_WAKEUP | MSGFLAG_OVERRUN; } memcpy(vEvent.tagData.msg.data,pTrameCan->Buffer,pTrameCan->Longueur); StatutOld=m_StatutReq; m_CanCardMutex.Lock(); m_StatutReq = ncdTransmit(m_gPortHandle, m_gChannelMask, &vEvent); if (m_StatutReq == VERR_QUEUE_IS_FULL) // Queue pleine { m_StatutReq = 0; // Evite d'afficher un CanOk quand on peut à nouveau emettre return cFaux; } else if (m_StatutReq != 0) // Erreur { if (m_StatutReq != StatutOld) { char Buffer[256]; sprintf(Buffer,"tcCanVector::ReqTrameUU> Emission failed (%04X)",m_StatutReq); SetMsg(cErrorMsg,Buffer); } return cFaux; } else if (m_StatutReq != StatutOld) // Ok { SetMsg(cErrorMsg,"tcCanVector::ReqTrameUU> Bus CAN OK"); } if (pObjetCan->FCallBackCon!=NULL) // On signale une fin d"émission par callback si demandée { pObjetCan->FCallBackCon(pObjetCan,pObjetCan->ParamCallBackCon); } m_CanCardMutex.Unlock(); return cVrai; }
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 }