drivers/can_kvaser/can_kvaser.c
author fbeaulier
Tue, 16 Aug 2011 14:15:52 +0200
changeset 663 70fc3603e36f
parent 631 08b6b903f84a
permissions -rw-r--r--
timers_unix.c : remove sigint and sigterm catch
sdo : Allow multiple servers
The sdo transfer struct is not anymore referenced by server's node id but by
client or server number in the OD. Node id is not relevant in SDO transfert.

/*
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 <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>

/* includes Kvaser's CANLIB header */
#include <canlib.h>

#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 const *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;
}