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 etisserant@145: #define extra_PCAN_init_params\ etisserant@145: ,getenv("PCANHwType") ? strtol(getenv("PCANHwType"),NULL,0):0\ etisserant@145: ,getenv("PCANIO_Port") ? strtol(getenv("PCANIO_Port"),NULL,0):0\ etisserant@145: ,getenv("PCANInterupt") ? strtol(getenv("PCANInterupt"),NULL,0):0 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 greg@563: hEvent2 = CreateEvent(NULL, // lpEventAttributes greg@563: FALSE, // bManualReset greg@563: FALSE, // bInitialState greg@563: ""); // lpName greg@563: 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 greg@563: hEvent1 = CreateEvent(NULL, // lpEventAttributes greg@563: FALSE, // bManualReset greg@563: FALSE, // bInitialState greg@563: ""); // lpName 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 ****************/ greg@563: UNS8 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: /***************************************************************************/ greg@563: UNS8 canSend_driver (CAN_HANDLE fd0, Message * 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: 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: { etisserant@145: errno = CAN2_Write (&peakMsg); greg@267: } greg@563: else etisserant@145: #endif etisserant@145: if(first_board == (s_BOARD *)fd0) greg@267: { greg@267: errno = CAN_Write (&peakMsg); greg@267: } greg@563: else etisserant@145: goto fail; etisserant@145: if (errno) etisserant@145: { etisserant@145: 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: } etisserant@145: 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: /***************************************************************************/ groke6@384: UNS8 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: /***************************************************************************/ greg@563: CAN_HANDLE 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: /***************************************************************************/ greg@563: int canClose_driver (CAN_HANDLE fd0) etisserant@145: { etisserant@145: #ifdef PCAN2_HEADER_ etisserant@145: // if not the first handler etisserant@145: if(second_board == (s_BOARD *)fd0) etisserant@145: { greg@570: CAN2_SetRcvEvent(NULL); greg@570: CAN2_Close (); greg@566: SetEvent(hEvent2); etisserant@145: second_board = (s_BOARD *)NULL; greg@563: }else etisserant@145: #endif etisserant@145: if(first_board == (s_BOARD *)fd0) etisserant@145: { greg@570: CAN_SetRcvEvent(NULL); greg@570: CAN_Close (); greg@566: SetEvent(hEvent1); etisserant@145: first_board = (s_BOARD *)NULL; etisserant@145: } etisserant@145: return 0; etisserant@145: }