etisserant@38: /* greg@563: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@145: etisserant@145: Copyright (C): Edouard TISSERANT and Francis DUPIN JaFojtik@696: Modified by: Jaroslav Fojtik etisserant@145: etisserant@145: See COPYING file for copyrights details. etisserant@145: etisserant@145: This library is free software; you can redistribute it and/or etisserant@145: modify it under the terms of the GNU Lesser General Public etisserant@145: License as published by the Free Software Foundation; either etisserant@145: version 2.1 of the License, or (at your option) any later version. etisserant@145: etisserant@145: This library is distributed in the hope that it will be useful, etisserant@145: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@145: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@145: Lesser General Public License for more details. etisserant@145: etisserant@145: You should have received a copy of the GNU Lesser General Public etisserant@145: License along with this library; if not, write to the Free Software etisserant@145: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@38: */ etisserant@38: etisserant@145: #if defined(WIN32) && !defined(__CYGWIN__) etisserant@145: #define usleep(micro) Sleep(micro%1000 ? (micro/1000) + 1 : (micro/1000)) etisserant@145: #else etisserant@145: #include etisserant@145: #include etisserant@145: #include etisserant@145: #include etisserant@145: #endif etisserant@145: etisserant@145: #include "cancfg.h" etisserant@145: #include "can_driver.h" greg@267: #include "def.h" JaFojtik@713: JaFojtik@713: JaFojtik@713: #define VERSION_2 JaFojtik@713: JaFojtik@713: /* dummy implementation for older version. */ JaFojtik@713: #ifndef VERSION_2 JaFojtik@713: void CAN_SetRcvEvent(HANDLE hEventx) JaFojtik@713: { JaFojtik@713: SetEvent(hEventx); JaFojtik@713: } JaFojtik@713: #endif JaFojtik@713: JaFojtik@713: JaFojtik@713: JaFojtik@713: etisserant@41: #ifndef extra_PCAN_init_params etisserant@145: #define extra_PCAN_init_params /**/ etisserant@145: #else greg@574: long int print_getenv(const char* pcanparam) greg@574: { greg@574: char* param=NULL; greg@574: long int res=0; greg@574: greg@574: param = getenv(pcanparam); greg@574: if(param != NULL){ greg@574: res = strtol(param,NULL,0); greg@574: } greg@574: else greg@574: printf("Environment variable %s not defined !\n", pcanparam); greg@574: printf("Found environment variable %s : %ld\n", pcanparam ,res); greg@574: return res; greg@574: } etisserant@145: #define extra_PCAN_init_params\ greg@574: ,print_getenv("PCANHwType")\ greg@574: ,print_getenv("PCANIO_Port")\ greg@574: ,print_getenv("PCANInterupt") etisserant@145: #endif etisserant@145: JaFojtik@713: etisserant@145: static s_BOARD *first_board = NULL; greg@563: //Create the Event for the first board greg@563: HANDLE hEvent1 = NULL; JaFojtik@713: CRITICAL_SECTION InitLock1; JaFojtik@713: CRITICAL_SECTION InitLock2; greg@563: greg@563: greg@563: #ifdef PCAN2_HEADER_ JaFojtik@713: static s_BOARD *second_board = NULL; JaFojtik@713: HANDLE hEvent2 = NULL; greg@563: #endif etisserant@145: etisserant@145: // Define for rtr CAN message etisserant@145: #define CAN_INIT_TYPE_ST_RTR MSGTYPE_STANDARD | MSGTYPE_RTR etisserant@145: etisserant@145: /***************************************************************************/ JaFojtik@713: static int TranslateBaudeRate(char* optarg) JaFojtik@713: { etisserant@145: if(!strcmp( optarg, "1M")) return CAN_BAUD_1M; etisserant@145: if(!strcmp( optarg, "500K")) return CAN_BAUD_500K; etisserant@145: if(!strcmp( optarg, "250K")) return CAN_BAUD_250K; etisserant@145: if(!strcmp( optarg, "125K")) return CAN_BAUD_125K; etisserant@145: if(!strcmp( optarg, "100K")) return CAN_BAUD_100K; etisserant@145: if(!strcmp( optarg, "50K")) return CAN_BAUD_50K; etisserant@145: if(!strcmp( optarg, "20K")) return CAN_BAUD_20K; etisserant@145: if(!strcmp( optarg, "10K")) return CAN_BAUD_10K; etisserant@145: if(!strcmp( optarg, "5K")) return CAN_BAUD_5K; etisserant@145: if(!strcmp( optarg, "none")) return 0; etisserant@145: return 0x0000; etisserant@145: } etisserant@145: JaFojtik@713: static UNS8 canInit (s_BOARD *board) etisserant@145: { etisserant@145: int baudrate; greg@566: int ret = 0; greg@563: greg@329: #ifdef PCAN2_HEADER_ etisserant@145: // if not the first handler greg@563: if(second_board == (s_BOARD *)board) { JaFojtik@713: if(hEvent2==NULL) JaFojtik@713: { /* Create the Event for the first board */ JaFojtik@713: hEvent2 = CreateEvent(NULL, // lpEventAttributes JaFojtik@713: FALSE, // bManualReset JaFojtik@713: FALSE, // bInitialState JaFojtik@713: ""); // lpName JaFojtik@713: InitializeCriticalSection(&InitLock2); JaFojtik@713: } JaFojtik@713: JaFojtik@713: EnterCriticalSection(&InitLock2); etisserant@145: if(baudrate = TranslateBaudeRate(board->baudrate)) greg@566: { JaFojtik@713: ret = CAN2_Init(baudrate, CAN_INIT_TYPE_ST extra_PCAN_init_params); JaFojtik@713: if(ret != CAN_ERR_OK) JaFojtik@713: { JaFojtik@713: LeaveCriticalSection(&InitLock2); JaFojtik@713: return 0; JaFojtik@713: } edouard@625: } greg@563: //Set Event Handle for CANReadExt greg@563: CAN2_SetRcvEvent(hEvent2); JaFojtik@713: LeaveCriticalSection(&InitLock2); greg@563: } greg@563: else greg@563: #endif greg@563: if(first_board == (s_BOARD *)board) { JaFojtik@713: //Create the Event for the first board JaFojtik@713: if(hEvent1==NULL) JaFojtik@713: { JaFojtik@713: hEvent1 = CreateEvent(NULL, // lpEventAttributes JaFojtik@713: FALSE, // bManualReset JaFojtik@713: FALSE, // bInitialState JaFojtik@713: ""); // lpName JaFojtik@713: InitializeCriticalSection(&InitLock1); JaFojtik@713: } JaFojtik@713: JaFojtik@713: EnterCriticalSection(&InitLock1); etisserant@145: if(baudrate = TranslateBaudeRate(board->baudrate)) greg@566: { JaFojtik@713: ret = CAN_Init(baudrate, CAN_INIT_TYPE_ST extra_PCAN_init_params); JaFojtik@713: if(ret != CAN_ERR_OK) JaFojtik@713: { JaFojtik@713: LeaveCriticalSection(&InitLock1); JaFojtik@713: return 0; JaFojtik@713: } edouard@625: } greg@563: //Set Event Handle for CANReadExt greg@563: CAN_SetRcvEvent(hEvent1); JaFojtik@713: LeaveCriticalSection(&InitLock1); greg@563: } greg@566: return 1; greg@563: } greg@563: greg@563: /********* functions which permit to communicate with the board ****************/ JaFojtik@713: UNS8 LIBAPI canReceive_driver(CAN_HANDLE fd0, Message * m) JaFojtik@713: { JaFojtik@713: static int HeavyCounter = 0; greg@563: int ret=0; etisserant@145: UNS8 data; etisserant@145: TPCANMsg peakMsg; JaFojtik@713: #ifdef CAN_READ_EX greg@563: TPCANTimestamp peakRcvTime; JaFojtik@713: #endif etisserant@145: DWORD Res; greg@563: DWORD result; greg@570: // loop until valid message or fatal error greg@570: do{ greg@570: #ifdef PCAN2_HEADER_ greg@570: // if not the first handler greg@570: if(second_board == (s_BOARD *)fd0) { greg@570: //wait for CAN msg... greg@570: result = WaitForSingleObject(hEvent2, INFINITE); greg@570: if (result == WAIT_OBJECT_0) greg@570: Res = CAN2_ReadEx(&peakMsg, &peakRcvTime); greg@570: // Exit receive thread when handle is no more valid JaFojtik@713: if(Res & CAN_ERRMASK_ILLHANDLE) greg@570: return 1; greg@570: } greg@570: else greg@570: #endif greg@570: greg@570: // We read the queue looking for messages. JaFojtik@713: if(first_board == (s_BOARD *)fd0) JaFojtik@713: { JaFojtik@713: #ifdef VERSION_2 greg@570: result = WaitForSingleObject(hEvent1, INFINITE); greg@570: if (result == WAIT_OBJECT_0) JaFojtik@713: #endif greg@570: { JaFojtik@713: #ifdef CAN_READ_EX greg@570: Res = CAN_ReadEx(&peakMsg, &peakRcvTime); JaFojtik@713: #else JaFojtik@713: Res = CAN_Read(&peakMsg); JaFojtik@713: #endif greg@570: // Exit receive thread when handle is no more valid JaFojtik@713: #ifdef CAN_ERRMASK_ILLHANDLE JaFojtik@713: if(Res & CAN_ERRMASK_ILLHANDLE) return 1; JaFojtik@713: #else JaFojtik@713: if(Res & CAN_ERR_ILLHANDLE) return 1; JaFojtik@713: #endif JaFojtik@713: JaFojtik@713: #ifndef VERSION_2 JaFojtik@713: if(Res != CAN_ERR_OK) JaFojtik@713: result = WaitForSingleObject(hEvent1, 1); //pooling JaFojtik@713: #endif greg@570: } greg@570: } JaFojtik@713: #ifdef VERSION_2 greg@570: else greg@570: Res = CAN_ERR_BUSOFF; JaFojtik@713: #endif JaFojtik@713: greg@570: // A message was received : we process the message(s) JaFojtik@713: if(Res == CAN_ERR_OK) JaFojtik@713: { JaFojtik@713: switch(peakMsg.MSGTYPE) JaFojtik@713: { JaFojtik@713: case MSGTYPE_STATUS: JaFojtik@713: switch(peakMsg.DATA[3]) JaFojtik@713: { JaFojtik@713: case CAN_ERR_BUSHEAVY: JaFojtik@713: break; JaFojtik@713: case CAN_ERR_BUSOFF: JaFojtik@713: printf ("Peak board read BUSOFF: re-init!!!\n"); JaFojtik@713: canInit((s_BOARD*)fd0); JaFojtik@713: usleep(33); JaFojtik@713: break; JaFojtik@713: } JaFojtik@713: return peakMsg.DATA[3]; /* if something different that 11bit or rtr... problem */ JaFojtik@713: JaFojtik@713: case MSGTYPE_STANDARD: /* bits of MSGTYPE_ */ JaFojtik@713: case MSGTYPE_EXTENDED: JaFojtik@713: m->rtr = 0; JaFojtik@713: break; JaFojtik@713: JaFojtik@713: case MSGTYPE_RTR: /* bits of MSGTYPE_ */ JaFojtik@713: m->rtr = 1; JaFojtik@713: break; JaFojtik@713: JaFojtik@713: default: return CAN_ERR_OVERRUN; /* If status, return status if 29bit, return overrun. */ JaFojtik@713: JaFojtik@713: } JaFojtik@713: JaFojtik@713: m->cob_id = peakMsg.ID; JaFojtik@713: if (peakMsg.MSGTYPE == CAN_INIT_TYPE_ST) /* bits of MSGTYPE_ */ JaFojtik@713: m->rtr = 0; JaFojtik@713: else JaFojtik@713: m->rtr = 1; JaFojtik@713: m->len = peakMsg.LEN; /* count of data bytes (0..8) */ JaFojtik@713: for (data = 0; data < peakMsg.LEN; data++) hacking@730: m->data[data] = peakMsg.DATA[data]; /* data bytes, up to 8 */ greg@570: #if defined DEBUG_MSG_CONSOLE_ON greg@570: MSG("in : "); greg@570: print_message(m); greg@570: #endif greg@570: } greg@570: else greg@570: { greg@570: // not benign error => fatal error greg@570: if (!(Res & CAN_ERR_QRCVEMPTY greg@570: || Res & CAN_ERR_BUSLIGHT greg@570: || Res & CAN_ERR_BUSHEAVY)) greg@570: { greg@570: printf ("canReceive returned error (%d)\n", Res); greg@566: return 1; greg@566: } greg@570: } JaFojtik@713: } while(Res != CAN_ERR_OK); greg@563: return 0; greg@563: } greg@563: greg@563: /***************************************************************************/ JaFojtik@713: UNS8 LIBAPI canSend_driver(CAN_HANDLE fd0, Message const *m) etisserant@145: { etisserant@145: UNS8 data; etisserant@145: TPCANMsg peakMsg; etisserant@365: peakMsg.ID = m->cob_id; /* 11/29 bit code */ etisserant@145: if (m->rtr == 0) etisserant@145: { JaFojtik@713: if(peakMsg.ID > 0x7FF) JaFojtik@713: peakMsg.MSGTYPE = MSGTYPE_EXTENDED; /* bits of MSGTYPE_ */ JaFojtik@713: else JaFojtik@713: peakMsg.MSGTYPE = MSGTYPE_STANDARD; /* bits of MSGTYPE_ */ JaFojtik@713: } JaFojtik@713: else JaFojtik@713: peakMsg.MSGTYPE = MSGTYPE_RTR; /* bits of MSGTYPE_ */ JaFojtik@713: etisserant@145: peakMsg.LEN = m->len; etisserant@145: /* count of data bytes (0..8) */ etisserant@145: for (data = 0; data < m->len; data++) hacking@730: peakMsg.DATA[data] = m->data[data]; /* data bytes, up to 8 */ greg@563: etisserant@145: do etisserant@145: { etisserant@145: #ifdef PCAN2_HEADER_ etisserant@145: // if not the first handler etisserant@145: if(second_board == (s_BOARD *)fd0) greg@267: { JaFojtik@713: errno = CAN2_Write (&peakMsg); greg@267: } greg@563: else etisserant@145: #endif etisserant@145: if(first_board == (s_BOARD *)fd0) greg@267: { JaFojtik@713: errno = CAN_Write (&peakMsg); greg@267: } greg@563: else etisserant@145: goto fail; JaFojtik@713: if (errno) JaFojtik@713: { JaFojtik@713: if (errno == CAN_ERR_BUSOFF) etisserant@145: { etisserant@145: printf ("!!! Peak board write : re-init\n"); etisserant@145: canInit((s_BOARD*)fd0); etisserant@145: usleep (10000); etisserant@145: } etisserant@145: usleep (1000); etisserant@145: } etisserant@145: } JaFojtik@713: while (errno != CAN_ERR_OK); etisserant@341: #if defined DEBUG_MSG_CONSOLE_ON greg@454: MSG("out : "); etisserant@341: print_message(m); etisserant@341: #endif etisserant@145: return 0; etisserant@145: fail: etisserant@145: return 1; etisserant@145: } etisserant@145: etisserant@145: /***************************************************************************/ JaFojtik@713: UNS8 LIBAPI canChangeBaudRate_driver(CAN_HANDLE fd, char* baud) groke6@384: { groke6@384: printf("canChangeBaudRate not yet supported by this driver\n"); groke6@384: return 0; groke6@384: } groke6@384: groke6@384: /***************************************************************************/ JaFojtik@713: LIBPUBLIC CAN_HANDLE LIBAPI canOpen_driver(s_BOARD * board) JaFojtik@713: { greg@267: char* pEnd; greg@566: int ret; greg@563: greg@267: //printf ("Board Busname=%d.\n",strtol(board->busname, &pEnd,0)); greg@267: if (strtol(board->busname, &pEnd,0) == 0) greg@267: { greg@267: first_board = board; greg@566: //printf ("First Board selected\n"); greg@566: ret = canInit(board); greg@566: if(ret) greg@566: return (CAN_HANDLE)board; greg@267: } greg@329: #ifdef PCAN2_HEADER_ greg@267: if (strtol(board->busname, &pEnd,0) == 1) greg@267: { greg@329: second_board = board; greg@566: //printf ("Second Board selected\n"); greg@566: ret = canInit(board); greg@566: if(ret) greg@566: return (CAN_HANDLE)board; greg@267: } greg@329: #endif greg@329: return NULL; etisserant@145: } etisserant@145: JaFojtik@713: etisserant@145: /***************************************************************************/ JaFojtik@713: int LIBAPI canClose_driver(CAN_HANDLE fd0) etisserant@145: { etisserant@145: #ifdef PCAN2_HEADER_ JaFojtik@713: // if not the first handler JaFojtik@713: if(second_board == (s_BOARD *)fd0) JaFojtik@713: { JaFojtik@713: CAN2_SetRcvEvent(NULL); JaFojtik@713: CAN2_Close (); JaFojtik@713: if(hEvent2) JaFojtik@713: { JaFojtik@713: SetEvent(hEvent2); JaFojtik@713: CloseHandle(hEvent2); JaFojtik@713: hEvent2 = NULL; JaFojtik@713: } JaFojtik@713: second_board = (s_BOARD *)NULL; JaFojtik@713: }else JaFojtik@713: #endif JaFojtik@713: if(first_board == (s_BOARD *)fd0) JaFojtik@713: { JaFojtik@713: CAN_SetRcvEvent(NULL); JaFojtik@713: CAN_Close (); JaFojtik@713: if(hEvent1) JaFojtik@713: { JaFojtik@713: SetEvent(hEvent1); JaFojtik@713: CloseHandle(hEvent1); JaFojtik@713: hEvent1 = NULL; JaFojtik@713: } JaFojtik@713: first_board = (s_BOARD *)NULL; JaFojtik@713: } JaFojtik@713: return 0; JaFojtik@713: }