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