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 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" 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: etisserant@145: static s_BOARD *first_board = NULL; greg@563: greg@563: //Create the Event for the first board greg@563: HANDLE hEvent1 = NULL; greg@563: greg@563: greg@563: #ifdef PCAN2_HEADER_ greg@563: static s_BOARD *second_board = NULL; greg@563: 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: /***************************************************************************/ etisserant@145: int TranslateBaudeRate(char* optarg){ 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: greg@566: 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) { etisserant@145: if(baudrate = TranslateBaudeRate(board->baudrate)) greg@566: { greg@566: ret = CAN2_Init(baudrate, CAN_INIT_TYPE_ST extra_PCAN_init_params); greg@566: if(ret != CAN_ERR_OK) greg@566: return 0; greg@566: } greg@563: greg@563: //Create the Event for the first board edouard@625: if(hEvent2 != NULL){ edouard@625: hEvent2 = CreateEvent(NULL, // lpEventAttributes edouard@625: FALSE, // bManualReset edouard@625: FALSE, // bInitialState edouard@625: ""); // lpName edouard@625: } greg@563: //Set Event Handle for CANReadExt greg@563: CAN2_SetRcvEvent(hEvent2); greg@563: } greg@563: else greg@563: #endif greg@563: if(first_board == (s_BOARD *)board) { etisserant@145: if(baudrate = TranslateBaudeRate(board->baudrate)) greg@566: { greg@566: ret = CAN_Init(baudrate, CAN_INIT_TYPE_ST extra_PCAN_init_params); greg@566: if(ret != CAN_ERR_OK) greg@566: return 0; greg@566: } greg@566: //Create the Event for the first board edouard@625: if(hEvent1 != NULL){ edouard@625: hEvent1 = CreateEvent(NULL, // lpEventAttributes edouard@625: FALSE, // bManualReset edouard@625: FALSE, // bInitialState edouard@625: ""); // lpName edouard@625: } greg@563: //Set Event Handle for CANReadExt greg@563: CAN_SetRcvEvent(hEvent1); greg@563: } greg@566: return 1; greg@563: } greg@563: greg@563: /********* functions which permit to communicate with the board ****************/ edouard@633: UNS8 __stdcall canReceive_driver (CAN_HANDLE fd0, Message * m) greg@563: { greg@563: int ret=0; etisserant@145: UNS8 data; etisserant@145: TPCANMsg peakMsg; greg@563: TPCANTimestamp peakRcvTime; 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 greg@570: 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. greg@570: if(first_board == (s_BOARD *)fd0) { greg@570: result = WaitForSingleObject(hEvent1, INFINITE); greg@570: if (result == WAIT_OBJECT_0) greg@570: { greg@570: Res = CAN_ReadEx(&peakMsg, &peakRcvTime); greg@570: // Exit receive thread when handle is no more valid greg@570: if(Res & CAN_ERRMASK_ILLHANDLE) greg@570: return 1; greg@570: } greg@570: } greg@570: else greg@570: Res = CAN_ERR_BUSOFF; greg@570: greg@570: // A message was received : we process the message(s) greg@570: if (Res == CAN_ERR_OK) greg@570: { greg@570: // if something different that 11bit or rtr... problem greg@570: if (peakMsg.MSGTYPE & ~(MSGTYPE_STANDARD | MSGTYPE_RTR)) greg@570: { greg@570: if (peakMsg.MSGTYPE == CAN_ERR_BUSOFF) greg@570: { greg@570: printf ("!!! Peak board read : re-init\n"); greg@570: canInit((s_BOARD*) fd0); greg@570: usleep (10000); greg@570: } greg@570: greg@570: // If status, return status if 29bit, return overrun greg@570: return peakMsg.MSGTYPE == greg@570: MSGTYPE_STATUS ? peakMsg.DATA[2] : CAN_ERR_OVERRUN; greg@570: } greg@570: m->cob_id = peakMsg.ID; greg@570: greg@570: if (peakMsg.MSGTYPE == CAN_INIT_TYPE_ST) /* bits of MSGTYPE_ */ greg@570: m->rtr = 0; greg@570: else greg@570: m->rtr = 1; greg@570: m->len = peakMsg.LEN; /* count of data bytes (0..8) */ greg@570: for (data = 0; data < peakMsg.LEN; data++) greg@570: 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: } greg@570: }while(Res != CAN_ERR_OK); greg@563: return 0; greg@563: } greg@563: greg@563: /***************************************************************************/ edouard@633: UNS8 __stdcall canSend_driver (CAN_HANDLE fd0, Message const * m) etisserant@145: { etisserant@145: UNS8 data; gregory@598: DWORD localerrno; etisserant@145: TPCANMsg peakMsg; etisserant@365: peakMsg.ID = m->cob_id; /* 11/29 bit code */ etisserant@145: if (m->rtr == 0) etisserant@145: peakMsg.MSGTYPE = CAN_INIT_TYPE_ST; /* bits of MSGTYPE_ */ etisserant@145: else etisserant@145: { etisserant@145: peakMsg.MSGTYPE = CAN_INIT_TYPE_ST_RTR; /* bits of MSGTYPE_ */ etisserant@145: } etisserant@145: peakMsg.LEN = m->len; etisserant@145: /* count of data bytes (0..8) */ etisserant@145: for (data = 0; data < m->len; data++) etisserant@145: 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: { gregory@598: errno = localerrno = CAN2_Write (&peakMsg); greg@267: } greg@563: else etisserant@145: #endif etisserant@145: if(first_board == (s_BOARD *)fd0) greg@267: { gregory@598: errno = localerrno = CAN_Write (&peakMsg); greg@267: } greg@563: else etisserant@145: goto fail; gregory@598: if (localerrno) gregory@598: { gregory@598: if (localerrno == 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: } gregory@598: while (localerrno != 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: /***************************************************************************/ edouard@633: UNS8 __stdcall 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: /***************************************************************************/ edouard@633: CAN_HANDLE __stdcall canOpen_driver (s_BOARD * board) etisserant@145: { greg@267: char busname[64]; 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: etisserant@145: /***************************************************************************/ edouard@633: int __stdcall canClose_driver (CAN_HANDLE fd0) etisserant@145: { etisserant@145: #ifdef PCAN2_HEADER_ edouard@625: // if not the first handler edouard@625: if(second_board == (s_BOARD *)fd0) edouard@625: { edouard@625: CAN2_SetRcvEvent(NULL); edouard@625: CAN2_Close (); edouard@625: if(hEvent2) edouard@625: { edouard@625: SetEvent(hEvent2); edouard@625: CloseHandle(hEvent2); edouard@625: hEvent2 = NULL; edouard@625: } edouard@625: second_board = (s_BOARD *)NULL; edouard@625: }else edouard@625: #endif edouard@625: if(first_board == (s_BOARD *)fd0) edouard@625: { edouard@625: CAN_SetRcvEvent(NULL); edouard@625: CAN_Close (); edouard@625: if(hEvent1) edouard@625: { edouard@625: SetEvent(hEvent1); edouard@625: CloseHandle(hEvent1); edouard@625: hEvent1 = NULL; edouard@625: } edouard@625: first_board = (s_BOARD *)NULL; edouard@625: } edouard@625: return 0; edouard@625: }