diff -r 8d22c323fe0f -r 7d845f5d730c drivers/can_kvaser/can_kvaser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_kvaser/can_kvaser.c Mon Feb 18 17:14:22 2008 +0100 @@ -0,0 +1,307 @@ + +/* +Copyright (C): Giuseppe Massimo BERTANI +gmbertani@users.sourceforge.net + + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file can_kvaser.c + * @author GMB + * @date 17/1/08 + * + * This file is needed to interface Kvaser's CAN Leaf (USB-CAN adapter) + * and probably others Kvaser's products compatible with Kvaser's CANLIB, + * to CANfestival open source CANopen stack. + * + * It was tested under Linux 2.6 with "Leaf Professional" and CANLIB 4.72 Beta (Oct 1,2007) +*/ + +#include +#include +#include +#include +#include +#include + +/* includes Kvaser's CANLIB header */ +#include + +#include "can_driver.h" + + +/** + * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0 + * so fd0 needs to be decremented before use. + * + */ +UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m) +{ +canStatus retval = canOK; +unsigned flags = 0; +unsigned long timeStamp; + + fd0--; + + /* checking for input message (blocking) */ + retval = canReadWait((int)fd0, (long*)&m->cob_id, &m->data, (unsigned*)&m->len, &flags, &timeStamp, -1); + if (retval != canOK) + { + fprintf(stderr, "canReceive_driver (Kvaser) : canReadWait() error, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", + m->cob_id, m->len, flags, retval); + canClose((int)fd0); + return retval; + } + + m->rtr = 0; + if (flags & canMSG_RTR) + { + m->rtr = 1; + } + + if (flags & canMSG_EXT) + { + /* TODO: is it correct to set this info in cob_id? */ + m->cob_id |= 0x20000000; + } + + //fprintf(stderr, "canReceive_driver (Kvaser) : canReadWait() received packet, cob_id=%08X, len=%u, flags=%08X, timestamp=%d returned value = %d\n", + // m->cob_id, m->len, flags, timeStamp, retval); + + return retval; +} + +/** + * + * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0 + * so fd0 needs to be decremented before use. + * + */ +UNS8 canSend_driver(CAN_HANDLE fd0, Message *m) +{ +canStatus retval = canOK; +unsigned flags = 0; + + fd0--; + + flags |= canMSG_STD; + + if (m->cob_id & 0x20000000) + { + /* TODO: is it correct to desume this info from cob_id? */ + flags |= canMSG_EXT; + } + + if (m->cob_id & 0x40000000) + { + flags |= canMSG_RTR; + } + + /* + * TODO: when should I set canMSG_ERROR_FRAME? + */ + + retval = canWriteWait((int)fd0, m->cob_id, m->data, m->len, 10000, flags); + if (retval != canOK) + { + fprintf(stderr, "canSend_driver (Kvaser) : canWriteWait() error, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", + m->cob_id, m->len, flags, retval); + canClose((int)fd0); + return retval; + } + + //fprintf(stderr, "canSend_driver (Kvaser) : canWriteWait() send packet, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", + // m->cob_id, m->len, flags, retval); + return retval; + +} + + +/** + * + */ +int TranslateBaudRate(char* optarg) +{ + if(!strcmp( optarg, "1M")) + return BAUD_1M; + if(!strcmp( optarg, "500K")) + return BAUD_500K; + if(!strcmp( optarg, "250K")) + return BAUD_250K; + if(!strcmp( optarg, "125K")) + return BAUD_125K; + if(!strcmp( optarg, "100K")) + return BAUD_100K; + if(!strcmp( optarg, "62K")) + return BAUD_62K; + if(!strcmp( optarg, "50K")) + return BAUD_50K; + + return 0; +} + +/** + * Channels and their descriptors are numbered starting from zero. + * So I need to increment by 1 the handle returned by CANLIB because + * CANfestival CAN_HANDLEs with value zero are considered NOT VALID. + * + * The baud rate could be given directly as bit/s + * or using one of the BAUD_* constants defined + * in canlib.h + */ +CAN_HANDLE canOpen_driver(s_BOARD *board) +{ +int fd0 = -1; +int channel, baud; +canStatus retval = canOK; + + fd0--; + + sscanf(board->busname, "%d", &channel); + + baud = TranslateBaudRate(board->baudrate); + + if (baud == 0) + { + sscanf(board->baudrate, "%d", &baud); + } + + fd0 = canOpenChannel(channel, canWANT_EXCLUSIVE|canWANT_EXTENDED); + if (fd0 < 0) + { + fprintf(stderr, "canOpen_driver (Kvaser) : error opening channel %d\n", channel); + return (CAN_HANDLE)(fd0+1); + } + canBusOff(fd0); + + /* values for tseg1, tseg2, sjw, noSamp and syncmode + * come from canlib example "simplewrite.c". The doc + * says that default values will be taken if baud is one of + * the BAUD_* values + */ + retval = canSetBusParams(fd0, baud, 4, 3, 1, 1, 0); + if (retval != canOK) + { + fprintf(stderr, "canOpen_driver (Kvaser) : canSetBusParams() error, returned value = %d, baud=%d, \n", retval, baud); + canClose((int)fd0); + return (CAN_HANDLE)retval; + } + + canSetBusOutputControl(fd0, canDRIVER_NORMAL); + if (retval != canOK) + { + fprintf(stderr, "canOpen_driver (Kvaser) : canSetBusOutputControl() error, returned value = %d\n", retval); + canClose((int)fd0); + return (CAN_HANDLE)retval; + } + + + + + retval = canBusOn(fd0); + if (retval != canOK) + { + fprintf(stderr, "canOpen_driver (Kvaser) : canBusOn() error, returned value = %d\n", retval); + canClose((int)fd0); + return (CAN_HANDLE)retval; + } + + return (CAN_HANDLE)(fd0+1); + +} + +UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud) +{ +int baudrate; +canStatus retval = canOK; + + + baudrate = TranslateBaudRate(baud); + if (baudrate == 0) + { + sscanf(baud, "%d", &baudrate); + } + + + fprintf(stderr, "%x-> changing to baud rate %s[%d]\n", (int)fd0, baud, baudrate); + + canBusOff((int)fd0); + + /* values for tseg1, tseg2, sjw, noSamp and syncmode + * come from canlib example "simplewrite.c". The doc + * says that default values will be taken if baud is one of + * the BAUD_* values + */ + retval = canSetBusParams((int)fd0, baudrate, 4, 3, 1, 1, 0); + if (retval != canOK) + { + fprintf(stderr, "canChangeBaudRate_driver (Kvaser) : canSetBusParams() error, returned value = %d, baud=%d, \n", retval, baud); + canClose((int)fd0); + return (UNS8)retval; + } + + canSetBusOutputControl((int)fd0, canDRIVER_NORMAL); + if (retval != canOK) + { + fprintf(stderr, "canChangeBaudRate_driver (Kvaser) : canSetBusOutputControl() error, returned value = %d\n", retval); + canClose((int)fd0); + return (UNS8)retval; + } + + retval = canBusOn((int)fd0); + if (retval != canOK) + { + fprintf(stderr, "canChangeBaudRate_driver (Kvaser) : canBusOn() error, returned value = %d\n", retval); + canClose((int)fd0); + return (UNS8)retval; + } + + return 0; +} + + +/** + * + * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0 + * so fd0 needs to be decremented before use. + */ +int canClose_driver(CAN_HANDLE fd0) +{ +canStatus retval = canOK; + + fd0--; + + retval = canBusOff((int)fd0); + if (retval != canOK) + { + fprintf(stderr, "canClose_driver (Kvaser) : canBusOff() error, returned value = %d\n", retval); + canClose((int)fd0); + return retval; + } + + retval = canClose((int)fd0); + if (retval != canOK) + { + fprintf(stderr, "canClose_driver (Kvaser) : canClose() error, returned value = %d\n", retval); + return retval; + } + + return retval; +} +