diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1f0a0cd --- /dev/null +++ b/main.cpp @@ -0,0 +1,506 @@ +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <termios.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <linux/can.h> +#include <linux/can/raw.h> +#include <vector> + +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pthread.h> + +#include <linux/input.h> +#include <linux/uinput.h> + +#include "abi-ipc.h" +#include "ABICommands.h" + +#define DEFAULT_ABI_RX_DEVICE "/dev/mocca0" +#define DEFAULT_ABI_TX_DEVICE "/dev/mocca0" +#define UINPUT_DEVICE "/dev/uinput" + +using namespace K2L::Automotive::ABI_IPC; +using namespace K2L::Automotive::ABI; + +#include "HVAC_Bin_jitter10.c" + +class AbiMainHandler : public CABIListener +{ +private: + AbiUsbIpc *abiIpc; + IABI *abi; + bool isConnected; + unsigned int connectionLabel; + Bus canBuses[6] = { CAN1, CAN2, CAN3, CAN4, CAN5, CAN6}; + Bus xcanBuses[6] = { XCAN1, XCAN2, XCAN3, XCAN4, XCAN5, XCAN6}; + Bus linBuses[6] = { LIN1, LIN2, LIN3, LIN4, LIN5, LIN6}; + int busCount = 6; + int socketId = -1; + struct can_frame txCanFrame; + struct sockaddr_can addr; + struct ifreq ifr; + + pthread_t receivingThread; + pthread_t sendingThread; + BYTE busToSend = 0xFF; + + pthread_mutex_t mutex; + BYTE currentState[8]; + BYTE nextState[8]; + bool sendNextState = false; + + int uinputFileDescriptor = -1; + + virtual void OnCanRxMessage(IABI* pAbi, void* pContext, unsigned long long timeStamp, Bus bus, unsigned int messageId, bool extended, BYTE* payload, int payloadLength) + { + if (messageId == 0x25B && payloadLength >= 8) + { + if (payload[6] & 0x01) + { + printf("MEDIA\n"); + SendKey(KEY_MEDIA); + } + if (payload[7] & 0x01) + { + printf("MAP\n"); + SendKey(KEY_FN_F11); + } + if (payload[5] & 0x08) + { + printf("COM\n"); + SendKey(KEY_PHONE); + } + if (payload[6] & 0x08) + { + printf("NAV\n"); + SendKey(KEY_FN_F12); + } + if (payload[4] & 0x20) + { + printf("BACK\n"); + SendKey(KEY_BACK); + } + if (payload[5] & 0x01) + { + printf("OPTION\n"); + SendKey(KEY_OPTION); + } + if (payload[3] & 0x01) + { + printf("iDRIVE (ENTER)\n"); + SendKey(KEY_ENTER); + } + uint8_t code = (payload[3] >> 4); + if (code == 1) + { + printf("iDRIVE (UP)\n"); + SendKey(KEY_UP); + } + if (code == 7) + { + printf("iDRIVE (DOWN)\n"); + SendKey(KEY_DOWN); + } + if (code == 0xA) + { + printf("iDRIVE (LEFT)\n"); + SendKey(KEY_LEFT); + } + if (code == 0x4) + { + printf("iDRIVE (RIGHT)\n"); + SendKey(KEY_RIGHT); + } + } + else + { + if (CAN1 <= bus && bus <= CAN6) + { + printf("CAN%i: RX %04X Std", bus - CAN1 + 1, messageId, payloadLength); + } + if (XCAN1 <= bus && bus <= XCAN6) + { + printf("CAN%i: RX %04X Ext", bus - XCAN1 + 1, messageId, payloadLength); + } + printf(":"); + for(int i = 0; i < payloadLength; i++) + { + printf(" %2X", payload[i]); + } + printf("\n"); + } + } + + void SendKey(unsigned int code) + { + if(this->uinputFileDescriptor < 0) + { + return; + } + + struct input_event ev; + + memset(&ev, 0, sizeof(ev)); + + ev.type = EV_KEY; + ev.code = code; + ev.value = 1; + + if (write(this->uinputFileDescriptor, &ev, sizeof(ev)) >= 0) + { + printf("Key: %X\n", code); + } + } + + virtual void OnLinRxMessage(IABI* pAbi, void* pContext, unsigned long long timeStamp, Bus bus, unsigned int sourceAddress, + unsigned int messageId, BYTE* payload, int payloadLength) + { + if (LIN1 <= bus && bus <= LIN6) + { + printf("LIN%i: RX %02X ", bus - LIN1 + 1, messageId, payloadLength); + } + printf(":"); + for(int i = 0; i < payloadLength; i++) + { + printf(" %2X", payload[i]); + } + printf("\n"); + if (this->busToSend == 0xFF) + { + this->busToSend = bus - LIN1 + 1; + printf("Selected bus LIN%i\n", this->busToSend); + } + + if (messageId == 0x2D) + { + // StatusAfterCalibration + CheckResult("Identify", CABICommands::Identify(abi)); + unsigned long long result; + CheckResult("Relay", CABICommands::SetRelay( abi, false, result)); + } + if (messageId == 0x31 && payloadLength >= 8) + { + // Status + if (pthread_mutex_lock(&mutex) == 0) + { + printf("Save state"); + for(int i = 0; i < payloadLength; i++) + { + printf(" %2X", payload[i]); + } + printf("...\n"); + memcpy(currentState, payload, 8); + if (memcmp(currentState, nextState, 8) == 0) + { + sendNextState = false; + } + else if (sendNextState) + { + printf("Next state is ready to send...\n" ); + struct can_frame frame; + frame.can_id = 0x01; + frame.can_dlc = 8; + memcpy(&frame.data, this->nextState, 8); + sendto(socketId, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, sizeof(addr)); + } + pthread_mutex_unlock(&mutex); + } + } + } + + static void *ReceiveThread( void *param ) + { + if( NULL == param ) + { + printf("ERROR: Virtual CAN receiving thread could not be started\n" ); + pthread_exit( 0 ); + } + AbiMainHandler *that = ( AbiMainHandler * )param; + + printf("Virtual CAN receiving thread started...\n" ); + int nbytes = 0; + struct can_frame frame; + while( that->isConnected ) + { + nbytes = read(that->socketId, &frame, sizeof(struct can_frame)); + if (nbytes < 0) + { + printf("ERROR: could not read CAN frame"); + } + + if (frame.can_id == 0x01 && frame.can_dlc >= 8) + { + printf(""); + printf("Send next state LIN%i: ", that->busToSend); + for(int i = 0; i < 8; i++) + { + printf(" %2X", that->nextState[i]); + } + printf("...\n"); + CheckResult("Send", CABICommands::SendLINMessage(that->abi, 150, that->busToSend, 0x30, frame.can_dlc, frame.data)); + if (pthread_mutex_lock(&(that->mutex)) == 0) + { + memcpy(that->nextState, frame.data, 8); + that->sendNextState = true; + pthread_mutex_unlock(&(that->mutex)); + } + continue; + } + + printf("Virtual CAN: message received %x: ", frame.can_id ); + for(int i = 0; i < frame.can_dlc; i++) + { + printf(" %2X", frame.data[i]); + } + printf("\n"); + + bool send = false; + if (frame.can_dlc >= 8 && pthread_mutex_lock(&(that->mutex)) == 0) + { + if (that->sendNextState) + { + printf("Save next state...\n"); + memcpy(that->nextState, frame.data, 8); + } + else + { + send = true; + memcpy(that->nextState, frame.data, 8); + that->sendNextState = true; + } + pthread_mutex_unlock(&(that->mutex)); + } + + if (send) + { + printf("Send new state...\n"); + CheckResult("Send", CABICommands::SendLINMessage(that->abi, 151, that->busToSend, frame.can_id, frame.can_dlc, frame.data)); + } + } + pthread_exit( 0 ); + } + + virtual void OnLinTxMessage(IABI* pAbi, void* pContext, unsigned long long timeStamp, unsigned short handle, Bus bus, unsigned int targetAddress, + unsigned int messageId, BYTE* payload, int payloadLength) + { + if (LIN1 <= bus && bus <= LIN6) + { + printf("LIN%i: TX %02X ", bus - LIN1 + 1, messageId, payloadLength); + } + printf(":"); + for(int i = 0; i < payloadLength; i++) + { + printf(" %2X", payload[i]); + } + printf("\n"); + + if (pthread_mutex_lock(&mutex) == 0) + { + memcpy(currentState, payload, 8); + pthread_mutex_unlock(&mutex); + } + } + + static void CheckResult( const char *command, int result ) + { + if( 0 == result ) + printf( "Command '%s' succeeded\n", command ); + else + printf( "Command '%s' failed, with error code: %d\n", command, result ); + } + + bool SetupAbiDevice() + { + //Lets the Active LED twinkle fast + CheckResult( "Identify", CABICommands::Identify( abi ) ); + + CheckResult( "Delete all receivers", CABICommands::Delete( abi, 0 ) ); + unsigned long long result; + CheckResult("Relay", CABICommands::SetRelay( abi, true, result)); + + for(int i = 0; i < busCount; i++) + { + CheckResult( "Start CAN", CABICommands::StartCan( abi, canBuses[i], canTransceiverFast, canSpeed500) ); + + CheckResult( "Add CAN receiver", CABICommands::AddReceiver( abi, 100 + i, canBuses[i], 0x0, 0x7FF ) ); + CheckResult( "Start CAN receiver", CABICommands::Start( abi, 100 + i ) ); + + CheckResult( "Add extended CAN receiver", CABICommands::AddReceiver( abi, 110 + i, xcanBuses[i], 0x0, 0x1FFFFFFF ) ); + CheckResult( "Start extended CAN receiver", CABICommands::Start( abi, 110 + i ) ); + } + + for(int i = 0; i < busCount; i++) + { + CheckResult( "Start LIN", CABICommands::StartLin(abi, linBuses[i], sizeof(bin_data), (BYTE*)bin_data)); + + CheckResult( "Add LIN receiver", CABICommands::AddReceiver( abi, 120 + i, linBuses[i], 0xFF, 0 ) ); + CheckResult( "Start LIN receiver", CABICommands::Start( abi, 120 + i ) ); + } + + this->socketId = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (this->socketId < 0) + { + printf("ERROR: socket could not be created\n"); + return false; + } + + strcpy(ifr.ifr_name, "vcan0" ); + if(ioctl(this->socketId, SIOCGIFINDEX, &ifr)) + { + printf("ERROR: ioctl failed\n"); + return false; + } + + addr.can_family = AF_CAN; + addr.can_ifindex = ifr.ifr_ifindex; + + if (bind(this->socketId, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + printf("ERROR: bind failed\n"); + return false; + } + + int recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */ + setsockopt(this->socketId, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, + &recv_own_msgs, sizeof(recv_own_msgs)); + + return true; + } + +public: + AbiMainHandler() : isConnected( false ), connectionLabel( 0xFFFFFFFF ) + { + abiIpc = new AbiUsbIpc(); + abi = CABIFactory::CreateAbi(); + pthread_mutex_init(&mutex, NULL); + this->uinputFileDescriptor = open(UINPUT_DEVICE, O_WRONLY | O_NONBLOCK); + if(this->uinputFileDescriptor < 0) + { + printf("ERROR: Cannot open UInput!\n"); + } + else if(ioctl(this->uinputFileDescriptor, UI_SET_EVBIT, EV_KEY) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_MEDIA) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_PHONE) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_MENU) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_BACK) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_OPTION) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_FN_F11) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_FN_F12) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_SCROLLDOWN) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_SCROLLUP) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_UP) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_LEFT) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_RIGHT) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_DOWN) >= 0 + && ioctl(this->uinputFileDescriptor, UI_SET_KEYBIT, KEY_ENTER) >= 0) + { + struct uinput_user_dev uidev; + + memset(&uidev, 0, sizeof(uidev)); + + snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample"); + uidev.id.bustype = BUS_USB; + uidev.id.vendor = 0x1234; + uidev.id.product = 0xfedc; + uidev.id.version = 1; + + if (write(this->uinputFileDescriptor, &uidev, sizeof(uidev)) >= 0 + && ioctl(this->uinputFileDescriptor, UI_DEV_CREATE) >= 0) + { + printf("UInput ready...\n"); + } + else + { + printf("ERROR: cannot create UInput device...\n"); + } + } + else + { + printf("ERROR: UInput failed!\n"); + } + } + + ~AbiMainHandler() + { + CheckResult( "Delete all receivers", CABICommands::Delete( abi, 0 ) ); + + for(int i = 0; i < busCount; i++) + { + CheckResult( "Stop LIN", CABICommands::StopLin(abi, linBuses[i])); + } + + if(this->socketId != -1) + { + close(this->socketId); + printf("Socket closed\n"); + } + + if(this->uinputFileDescriptor >= 0) + { + if (ioctl(this->uinputFileDescriptor, UI_DEV_DESTROY) >= 0) + { + printf("UInput device destroyed\n"); + } + close(this->uinputFileDescriptor); + printf("UInput closed\n"); + } + } + + bool Connect( const char *cdevRx, const char *cdevTx ) + { + if( isConnected ) + { + isConnected = false; + abiIpc->Disconnect(); + } + bool isSingleDevice = ( 0 == strcmp( cdevRx, cdevTx ) ); + bool success = isSingleDevice ? abiIpc->Connect( cdevRx ) : abiIpc->Connect( cdevRx, cdevTx ); + if( success ) + { + int err = abi->Init( abiIpc ); + if( 0 == err ) + { + abi->Start( this ); + isConnected = SetupAbiDevice(); + if( pthread_create( &this->receivingThread, NULL, ReceiveThread, this ) ) + { + printf( "Failed to create receive thread\n" ); + return false; + } + } + } + + return isConnected; + } +}; + +int main( int argc, char *argv[] ) +{ + AbiMainHandler mainHandler; + bool success = mainHandler.Connect( DEFAULT_ABI_RX_DEVICE, DEFAULT_ABI_TX_DEVICE ); + + if(success) + { + printf( "OptoLyzer MOCCA compact connected...\n"); + printf("Press any key to finish...\n"); + getchar(); + } + else + { + printf( "ERROR: ABI could not started...\n", success ); + } + + return 0; +} + + |